Skip to content

Commit

Permalink
- Move to the ImGui Docking branch (ocornut/imgui#2109)
Browse files Browse the repository at this point in the history
  • Loading branch information
lonutCava committed Oct 2, 2018
1 parent 1a8130e commit f9bb297
Show file tree
Hide file tree
Showing 30 changed files with 8,448 additions and 9,692 deletions.
268 changes: 265 additions & 3 deletions Source Code/Editor/Editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,17 @@

#include <imgui_internal.h>

#include <SDL/include/SDL_syswm.h>

#define SDL_HAS_WARP_MOUSE_GLOBAL SDL_VERSION_ATLEAST(2,0,4)
#define SDL_HAS_CAPTURE_MOUSE SDL_VERSION_ATLEAST(2,0,4)
#define SDL_HAS_WINDOW_OPACITY SDL_VERSION_ATLEAST(2,0,5)
#define SDL_HAS_ALWAYS_ON_TOP SDL_VERSION_ATLEAST(2,0,5)
#define SDL_HAS_USABLE_DISPLAY_BOUNDS SDL_VERSION_ATLEAST(2,0,5)
#define SDL_HAS_PER_MONITOR_DPI SDL_VERSION_ATLEAST(2,0,4)
#define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6)
#define SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH SDL_VERSION_ATLEAST(2,0,5)

This comment has been minimized.

Copy link
@ocornut

ocornut Oct 2, 2018

It's a really bad idea to copy all this code which will evolve over time, why not using the functions from imgui_impl_sdl2.cpp directly?

This comment has been minimized.

Copy link
@ocornut

ocornut Oct 2, 2018

Otherwise, looking forward to your feedback and finding out if this is a good replacement to your previous solution :)

This comment has been minimized.

Copy link
@IonutCava

IonutCava Oct 2, 2018

Owner

Copied the code as a reference mostly so that I can tick each function off one by one, as I hook everything up to my own platform & window management systems.
Wanted to port them over before pushing, but my lunch break ran out so I just left the code at the bottom (and some at the top) of the file to look at later today. 😊

I assume the platform & IO interfaces won’t change that much. (create/destroy windows, change title, change size, etc) ‘cause I already have my own code to handle that, but even if they do, the viewport stuff is on my “nice to have/not critical” list. It’s disabled for now, anyway.

As far as the docking system goes, everything works as expected so far, (even with a menu bar) but I have a lot of code to port over from Flix01’s docking system (what I was previously using), so I’m looking forward to finding & reporting bugs 😃

imgui

namespace Divide {

namespace {
Expand All @@ -35,6 +46,31 @@ namespace {
I32 previous_window_opacity = 255;
bool show_test_window = true;
};

struct ImGuiViewportDataSDL2
{
SDL_Window* Window;
Uint32 WindowID;
bool WindowOwned;
SDL_GLContext GLContext;

ImGuiViewportDataSDL2() { Window = NULL; WindowID = 0; WindowOwned = false; GLContext = NULL; }
~ImGuiViewportDataSDL2() { IM_ASSERT(Window == NULL && GLContext == NULL); }
};

static void ImGui_ImplSDL2_CreateWindow(ImGuiViewport* viewport);
static void ImGui_ImplSDL2_DestroyWindow(ImGuiViewport* viewport);
static void ImGui_ImplSDL2_ShowWindow(ImGuiViewport* viewport);
static ImVec2 ImGui_ImplSDL2_GetWindowPos(ImGuiViewport* viewport);
static void ImGui_ImplSDL2_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos);
static ImVec2 ImGui_ImplSDL2_GetWindowSize(ImGuiViewport* viewport);
static void ImGui_ImplSDL2_SetWindowSize(ImGuiViewport* viewport, ImVec2 size);
static void ImGui_ImplSDL2_SetWindowTitle(ImGuiViewport* viewport, const char* title);
static void ImGui_ImplSDL2_SetWindowFocus(ImGuiViewport* viewport);
static bool ImGui_ImplSDL2_GetWindowFocus(ImGuiViewport* viewport);
static void ImGui_ImplSDL2_RenderWindow(ImGuiViewport* viewport, void*);
static void ImGui_ImplSDL2_SwapBuffers(ImGuiViewport* viewport, void*);
static void ImGui_ImplSDL2_UpdateMonitors();

Editor::Editor(PlatformContext& context, ImGuiStyleEnum theme, ImGuiStyleEnum lostFocusTheme, ImGuiStyleEnum dimmedTheme)
: PlatformContextComponent(context),
Expand Down Expand Up @@ -145,6 +181,11 @@ bool Editor::init(const vec2<U16>& renderResolution) {
io.Fonts->ClearTexData();
}

io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoTaskBarIcons;
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoMerge;
io.KeyMap[ImGuiKey_Tab] = Input::KeyCode::KC_TAB;
io.KeyMap[ImGuiKey_LeftArrow] = Input::KeyCode::KC_LEFT;
io.KeyMap[ImGuiKey_RightArrow] = Input::KeyCode::KC_RIGHT;
Expand All @@ -168,12 +209,46 @@ bool Editor::init(const vec2<U16>& renderResolution) {
io.SetClipboardTextFn = SetClipboardText;
io.GetClipboardTextFn = GetClipboardText;
io.ClipboardUserData = nullptr;
io.ImeWindowHandle = _mainWindow->handle()._handle;
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;
#if SDL_HAS_WARP_MOUSE_GLOBAL
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
#endif
#if SDL_HAS_CAPTURE_MOUSE
io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport;
#endif
io.DisplaySize = ImVec2((float)renderResolution.width, (float)renderResolution.height);
io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
}

ImGui::SetCurrentContext(_imguiContext[to_base(Context::Editor)]);

ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Platform_CreateWindow = ImGui_ImplSDL2_CreateWindow;
platform_io.Platform_DestroyWindow = ImGui_ImplSDL2_DestroyWindow;
platform_io.Platform_ShowWindow = ImGui_ImplSDL2_ShowWindow;
platform_io.Platform_SetWindowPos = ImGui_ImplSDL2_SetWindowPos;
platform_io.Platform_GetWindowPos = ImGui_ImplSDL2_GetWindowPos;
platform_io.Platform_SetWindowSize = ImGui_ImplSDL2_SetWindowSize;
platform_io.Platform_GetWindowSize = ImGui_ImplSDL2_GetWindowSize;
platform_io.Platform_SetWindowFocus = ImGui_ImplSDL2_SetWindowFocus;
platform_io.Platform_GetWindowFocus = ImGui_ImplSDL2_GetWindowFocus;
platform_io.Platform_SetWindowTitle = ImGui_ImplSDL2_SetWindowTitle;
platform_io.Platform_RenderWindow = ImGui_ImplSDL2_RenderWindow;
platform_io.Platform_SwapBuffers = ImGui_ImplSDL2_SwapBuffers;

#if SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
#endif
ImGui_ImplSDL2_UpdateMonitors();
ImGuiViewportDataSDL2* data = IM_NEW(ImGuiViewportDataSDL2)();
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
data->Window = _mainWindow->getRawWindow();
data->WindowID = SDL_GetWindowID(_mainWindow->getRawWindow());
data->WindowOwned = false;
data->GLContext = SDL_GL_GetCurrentContext();
main_viewport->PlatformUserData = data;
main_viewport->PlatformHandle = data->Window;

_panelManager->init(renderResolution);

ImGui::ResetStyle(_currentTheme);
Expand Down Expand Up @@ -392,7 +467,11 @@ bool Editor::framePostRenderStarted(const FrameEvent& evt) {

ImGui::Render();
renderDrawList(ImGui::GetDrawData(), _mainWindow->getGUID(), true);

if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
}
return true;
}

Expand Down Expand Up @@ -856,4 +935,187 @@ ImGuiIO& Editor::GetIO(U8 idx) {
return _imguiContext[idx]->IO;
}


//--------------------------------------------------------------------------------------------------------
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
// This is an _advanced_ and _optional_ feature, allowing the back-end to create and handle multiple viewports simultaneously.
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
//--------------------------------------------------------------------------------------------------------

static void ImGui_ImplSDL2_CreateWindow(ImGuiViewport* viewport)
{
ImGuiViewportDataSDL2* data = IM_NEW(ImGuiViewportDataSDL2)();
viewport->PlatformUserData = data;

ImGuiViewport* main_viewport = ImGui::GetMainViewport();
ImGuiViewportDataSDL2* main_viewport_data = (ImGuiViewportDataSDL2*)main_viewport->PlatformUserData;

// Share GL resources with main context
bool use_opengl = (main_viewport_data->GLContext != NULL);
SDL_GLContext backup_context = NULL;
if (use_opengl)
{
backup_context = SDL_GL_GetCurrentContext();
SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
SDL_GL_MakeCurrent(main_viewport_data->Window, main_viewport_data->GLContext);
}

// We don't enable SDL_WINDOW_RESIZABLE because it enforce windows decorations
Uint32 sdl_flags = 0;
sdl_flags |= SDL_WINDOW_OPENGL;//use_opengl ? SDL_WINDOW_OPENGL : SDL_WINDOW_VULKAN;
sdl_flags |= SDL_WINDOW_HIDDEN;
sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? SDL_WINDOW_BORDERLESS : 0;
sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? 0 : SDL_WINDOW_RESIZABLE;
#if SDL_HAS_ALWAYS_ON_TOP
sdl_flags |= (viewport->Flags & ImGuiViewportFlags_TopMost) ? SDL_WINDOW_ALWAYS_ON_TOP : 0;
#endif
data->Window = SDL_CreateWindow("No Title Yet", (int)viewport->Pos.x, (int)viewport->Pos.y, (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags);
data->WindowOwned = true;
if (use_opengl)
{
data->GLContext = SDL_GL_CreateContext(data->Window);
SDL_GL_SetSwapInterval(0);
}
if (use_opengl && backup_context)
SDL_GL_MakeCurrent(data->Window, backup_context);
viewport->PlatformHandle = (void*)data->Window;
}

static void ImGui_ImplSDL2_DestroyWindow(ImGuiViewport* viewport)
{
if (ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData)
{
if (data->GLContext && data->WindowOwned)
SDL_GL_DeleteContext(data->GLContext);
if (data->Window && data->WindowOwned)
SDL_DestroyWindow(data->Window);
data->GLContext = NULL;
data->Window = NULL;
IM_DELETE(data);
}
viewport->PlatformUserData = viewport->PlatformHandle = NULL;
}

static void ImGui_ImplSDL2_ShowWindow(ImGuiViewport* viewport)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
#if defined(_WIN32)
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (SDL_GetWindowWMInfo(data->Window, &info))
{
HWND hwnd = info.info.win.window;

// SDL hack: Hide icon from task bar
// Note: SDL 2.0.6+ has a SDL_WINDOW_SKIP_TASKBAR flag which is supported under Windows but the way it create the window breaks our seamless transition.
if (viewport->Flags & ImGuiViewportFlags_NoTaskBarIcon)
{
LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
ex_style &= ~WS_EX_APPWINDOW;
ex_style |= WS_EX_TOOLWINDOW;
::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style);
}

// SDL hack: SDL always activate/focus windows :/
if (viewport->Flags & ImGuiViewportFlags_NoFocusOnAppearing)
{
::ShowWindow(hwnd, SW_SHOWNA);
return;
}
}
#endif

SDL_ShowWindow(data->Window);
}

static ImVec2 ImGui_ImplSDL2_GetWindowPos(ImGuiViewport* viewport)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
int x = 0, y = 0;
SDL_GetWindowPosition(data->Window, &x, &y);
return ImVec2((float)x, (float)y);
}

static void ImGui_ImplSDL2_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
SDL_SetWindowPosition(data->Window, (int)pos.x, (int)pos.y);
}

static ImVec2 ImGui_ImplSDL2_GetWindowSize(ImGuiViewport* viewport)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
int w = 0, h = 0;
SDL_GetWindowSize(data->Window, &w, &h);
return ImVec2((float)w, (float)h);
}

static void ImGui_ImplSDL2_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
SDL_SetWindowSize(data->Window, (int)size.x, (int)size.y);
}

static void ImGui_ImplSDL2_SetWindowTitle(ImGuiViewport* viewport, const char* title)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
SDL_SetWindowTitle(data->Window, title);
}

static void ImGui_ImplSDL2_SetWindowFocus(ImGuiViewport* viewport)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
SDL_RaiseWindow(data->Window);
}

static bool ImGui_ImplSDL2_GetWindowFocus(ImGuiViewport* viewport)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
return (SDL_GetWindowFlags(data->Window) & SDL_WINDOW_INPUT_FOCUS) != 0;
}

static void ImGui_ImplSDL2_RenderWindow(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
if (data->GLContext)
SDL_GL_MakeCurrent(data->Window, data->GLContext);
}

static void ImGui_ImplSDL2_SwapBuffers(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
if (data->GLContext)
{
SDL_GL_MakeCurrent(data->Window, data->GLContext);
SDL_GL_SwapWindow(data->Window);
}
}

// FIXME-PLATFORM: SDL doesn't have an event to notify the application of display/monitor changes
static void ImGui_ImplSDL2_UpdateMonitors()
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Monitors.resize(0);
int display_count = SDL_GetNumVideoDisplays();
for (int n = 0; n < display_count; n++)
{
// Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime.
ImGuiPlatformMonitor monitor;
SDL_Rect r;
SDL_GetDisplayBounds(n, &r);
monitor.MainPos = monitor.WorkPos = ImVec2((float)r.x, (float)r.y);
monitor.MainSize = monitor.WorkSize = ImVec2((float)r.w, (float)r.h);
#if SDL_HAS_USABLE_DISPLAY_BOUNDS
SDL_GetDisplayUsableBounds(n, &r);
monitor.WorkPos = ImVec2((float)r.x, (float)r.y);
monitor.WorkSize = ImVec2((float)r.w, (float)r.h);
#endif
#if SDL_HAS_PER_MONITOR_DPI
float dpi = 0.0f;
if (SDL_GetDisplayDPI(n, &dpi, NULL, NULL))
monitor.DpiScale = dpi / 96.0f;
#endif
platform_io.Monitors.push_back(monitor);
}
}
}; //namespace Divide
1 change: 0 additions & 1 deletion Source Code/Editor/Widgets/Headers/PanelManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ namespace Divide {

protected:
F32 calcMainMenuHeight();
void drawDockedTabWindows(ImGui::PanelManagerWindowData& wd);
void setSelectedCamera(Camera* camera);
Camera* getSelectedCamera() const;

Expand Down
15 changes: 0 additions & 15 deletions Source Code/Editor/Widgets/PanelManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,18 +232,6 @@ namespace Divide {

s_globalCache = &context().kernel().resourceCache();

if (!ImGui::TabWindow::DockPanelIconTextureID) {
ImVector<unsigned char> rgba_buffer;int w, h;
ImGui::TabWindow::GetDockPanelIconImageRGBA(rgba_buffer, &w, &h);
ImGui::TabWindow::DockPanelIconTextureID =
LoadTextureFromMemory(_textures[to_base(TextureUsage::Dock)],
"Docking Texture",
w,
h,
4,
&rgba_buffer[0]);
}

# ifdef YES_IMGUIIMAGEEDITOR
ImGui::ImageEditor::SetGenerateOrUpdateTextureCallback(&GenerateOrUpdateTexture); // This will be called only with channels=3 or channels=4
ImGui::ImageEditor::SetFreeTextureCallback(&FreeTextureDelegate);
Expand Down Expand Up @@ -319,9 +307,6 @@ namespace Divide {
setPanelManagerBoundsToIncludeMainMenuIfPresent(w, h); // This line is only necessary if we have a global menu bar
}

void PanelManager::drawDockedTabWindows(ImGui::PanelManagerWindowData& wd) {
}

void PanelManager::setSelectedCamera(Camera* camera) {
_selectedCamera = camera;
}
Expand Down
6 changes: 3 additions & 3 deletions Source Code/Libs/imgui/.github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ You may use the Issue Tracker to submit bug reports, feature requests or suggest
**Guidelines to report an issue or ask a question:**
- Please provide your imgui version number.
- Please state if you have made substantial modifications to your copy of imgui.
- Try to be explicit with your expectations and what you have tried. What you have in mind or in your code is not obvious to other people.
- Try to be explicit with your Goals, your Expectations and what you have Tried. What you have in mind or in your code is not obvious to other people. People frequently discuss problems without first mentioning their goal.
- If you are discussing an assert or a crash, please provide a debugger callstack. Never state "it crashes" without additional information. If you don't know how to use a debugger and retrieve a callstack, learning about it will be useful.
- Please make sure that your compilation settings have asserts enabled. Calls to IM_ASSERT() are scattered in the code to help catch common issues. By default IM_ASSERT() calls the standard assert() function. To verify that your asserts are enabled, add the line `IM_ASSERT(false);` in your main() function. Your application should display an error message and abort. If your application report an error, it means that your asserts are disabled. Please make sure they are enabled.
- When discussing issues related to rendering or inputs, please state the OS/back-end/renderer you are using. Please state if you are using a vanilla copy of the example back-ends (imgui_impl_XXX files), or a modified one, or if you built your own.
Expand All @@ -27,10 +27,10 @@ You may use the Issue Tracker to submit bug reports, feature requests or suggest
- When requesting a new feature, please describe the usage context (how you intend to use it, why you need it, etc.).

**Some unfortunate words of warning**
- If you are or were involved in cheating schemes (e.g. DLL injection) for competitive online multi-player games, please don't post here. We won't answer and you will be blocked. We've had too many of you. Please stop.
- If you are or were involved in cheating schemes (e.g. DLL injection) for competitive online multi-player games, please don't post here. We won't answer and you will be blocked. We've had too many of you.
- Due to frequent abuse of this service from aforementioned users, if your GitHub account is anonymous and was created five minutes ago please understand that your post will receive more scrutiny and incomplete questions may be dismissed.

If you have been using dear imgui for a while or have been using C/C++ for several years or have demonstrated good behavior here, it is ok to not fullfill every item to the letter. Those are guidelines and experienced users or members of the community will know what information are useful in a given context.
If you have been using dear imgui for a while or have been using C/C++ for several years or have demonstrated good behavior here, it is ok to not fullfill every item to the letter. Those are guidelines and experienced users or members of the community will know which information are useful in a given context.

## How to create an Pull Request
- When adding a feature, please describe the usage context (how you intend to use it, why you need it, etc.).
Expand Down
Loading

0 comments on commit f9bb297

Please sign in to comment.