From 5f84d95fed8689ac0504e5cda6cfc79e9a156efd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Thu, 20 Oct 2016 22:04:01 -0700 Subject: [PATCH] Replaced ImGui docking with simpler code. --- 3rdparty/ocornut-imgui/imgui_user.h | 1 + 3rdparty/ocornut-imgui/imgui_user.inl | 1 + 3rdparty/ocornut-imgui/imgui_wm.cpp | 1688 ----------------------- 3rdparty/ocornut-imgui/imgui_wm.h | 310 ----- 3rdparty/ocornut-imgui/widgets/dock.h | 21 + 3rdparty/ocornut-imgui/widgets/dock.inl | 1105 +++++++++++++++ examples/common/imgui/imgui.h | 1 - examples/common/imgui/ocornut_imgui.cpp | 355 +---- 8 files changed, 1130 insertions(+), 2352 deletions(-) delete mode 100644 3rdparty/ocornut-imgui/imgui_wm.cpp delete mode 100644 3rdparty/ocornut-imgui/imgui_wm.h create mode 100644 3rdparty/ocornut-imgui/widgets/dock.h create mode 100644 3rdparty/ocornut-imgui/widgets/dock.inl diff --git a/3rdparty/ocornut-imgui/imgui_user.h b/3rdparty/ocornut-imgui/imgui_user.h index 60b8df40c..45ae2c013 100644 --- a/3rdparty/ocornut-imgui/imgui_user.h +++ b/3rdparty/ocornut-imgui/imgui_user.h @@ -45,3 +45,4 @@ namespace ImGui #include "widgets/file_list.h" #include "widgets/memory_editor.h" #include "widgets/gizmo.h" +#include "widgets/dock.h" \ No newline at end of file diff --git a/3rdparty/ocornut-imgui/imgui_user.inl b/3rdparty/ocornut-imgui/imgui_user.inl index c03955f18..b88fdd0dc 100644 --- a/3rdparty/ocornut-imgui/imgui_user.inl +++ b/3rdparty/ocornut-imgui/imgui_user.inl @@ -75,3 +75,4 @@ namespace ImGui #include "widgets/file_list.inl" #include "widgets/memory_editor.inl" #include "widgets/gizmo.inl" +#include "widgets/dock.inl" \ No newline at end of file diff --git a/3rdparty/ocornut-imgui/imgui_wm.cpp b/3rdparty/ocornut-imgui/imgui_wm.cpp deleted file mode 100644 index 09de2797a..000000000 --- a/3rdparty/ocornut-imgui/imgui_wm.cpp +++ /dev/null @@ -1,1688 +0,0 @@ -/* - * Copyright 2011-2016 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause - */ - -/* - * Based on ImWindow code from: - * https://github.com/thennequin/ImWindow - * - * MIT license: - * https://github.com/thennequin/ImWindow/blob/master/LICENSE - */ - -#include "imgui_wm.h" -#include "imgui_internal.h" -#include - -#define IMGUI_NEW(type) new (ImGui::MemAlloc(sizeof(type) ) ) type -#define IMGUI_DELETE(type, obj) static_cast(obj)->~type(), ImGui::MemFree(obj) -#define IMGUI_DELETE_NULL(type, obj) for (;;) { if (NULL != obj) { IMGUI_DELETE(type, obj); obj = NULL; } break; } - -namespace ImGuiWM -{ - enum EPlatformWindowAction - { - E_PLATFORM_WINDOW_ACTION_DESTOY = 1, - E_PLATFORM_WINDOW_ACTION_SHOW = 2, - E_PLATFORM_WINDOW_ACTION_HIDE = 4, - E_PLATFORM_WINDOW_ACTION_SET_POSITION = 8, - E_PLATFORM_WINDOW_ACTION_SET_SIZE = 16, - }; - - static const ImVec2 IM_VEC2_0 = ImVec2(0, 0); - static const ImVec2 IM_VEC2_N1 = ImVec2(-1, -1); - - int Id::s_iNextId = 0; - - Id::Id() - { - m_iId = s_iNextId++; - ImFormatString(m_pId, 11, "0x%8X", m_iId); - } - - ImU32 Id::GetId() const - { - return m_iId; - } - - const char* Id::GetStr() const - { - return m_pId; - } - - Window::Window() - { - m_pTitle = NULL; - WindowManager::GetInstance()->AddWindow(this); - } - - Window::~Window() - { - WindowManager::GetInstance()->RemoveWindow(this); - ImGui::MemFree(m_pTitle); - } - - void Window::Destroy() - { - WindowManager::GetInstance()->DestroyWindow(this); - } - - void Window::SetTitle(const char* pTitle) - { - ImGui::MemFree(m_pTitle); - m_pTitle = ImStrdup(pTitle); - } - - const char* Window::GetTitle() const - { - return m_pTitle; - } - - const ImVec2& Window::GetLastPosition() const - { - return m_oLastPosition; - } - - const ImVec2& Window::GetLastSize() const - { - return m_oLastSize; - } - - Container::Container(Container* pParent) - { - IM_ASSERT(NULL != pParent); - m_pSplits[0] = NULL; - m_pSplits[1] = NULL; - m_bVerticalSplit = false; - m_iActiveWindow = 0; - m_fSplitRatio = 0.5f; - m_bIsDrag = false; - m_pParent = pParent; - m_pParentWindow = (NULL != pParent) ? pParent->m_pParentWindow : NULL; - } - - Container::Container(PlatformWindow* pParent) - { - IM_ASSERT(NULL != pParent); - m_pSplits[0] = NULL; - m_pSplits[1] = NULL; - m_bVerticalSplit = false; - m_iActiveWindow = 0; - m_fSplitRatio = 0.5f; - m_bIsDrag = false; - m_pParent = NULL; - m_pParentWindow = pParent; - } - - Container::~Container() - { - while (m_lWindows.begin() != m_lWindows.end()) - { - Window* window = *m_lWindows.begin(); - WindowManager::GetInstance()->RemoveWindow(window); - IMGUI_DELETE(Window, window); - m_lWindows.erase(m_lWindows.begin()); - } - - IMGUI_DELETE_NULL(Container, m_pSplits[0]); - IMGUI_DELETE_NULL(Container, m_pSplits[1]); - } - - void Container::CreateSplits() - { - m_pSplits[0] = IMGUI_NEW(Container)(this); - m_pSplits[1] = IMGUI_NEW(Container)(this); - } - - void Container::Dock(Window* pWindow, EDockOrientation eOrientation) - { - IM_ASSERT(NULL != pWindow); - - if (NULL != pWindow) - { - IM_ASSERT(eOrientation != E_DOCK_ORIENTATION_CENTER || !IsSplit()); - - if (!IsSplit()) - { - if (m_lWindows.size() == 0) - { - eOrientation = E_DOCK_ORIENTATION_CENTER; - } - - switch (eOrientation) - { - case E_DOCK_ORIENTATION_CENTER: - { - m_lWindows.push_back(pWindow); - m_iActiveWindow = int(m_lWindows.size() - 1); - } - break; - case E_DOCK_ORIENTATION_TOP: - { - m_bVerticalSplit = true; - CreateSplits(); - m_pSplits[0]->Dock(pWindow); - m_pSplits[1]->m_lWindows.insert(m_pSplits[1]->m_lWindows.begin(), m_lWindows.begin(), m_lWindows.end()); - m_lWindows.clear(); - m_iActiveWindow = 0; - } - break; - case E_DOCK_ORIENTATION_LEFT: - { - m_bVerticalSplit = false; - CreateSplits(); - m_pSplits[0]->Dock(pWindow); - m_pSplits[1]->m_lWindows.insert(m_pSplits[1]->m_lWindows.begin(), m_lWindows.begin(), m_lWindows.end()); - m_lWindows.clear(); - m_iActiveWindow = 0; - } - break; - case E_DOCK_ORIENTATION_RIGHT: - { - m_bVerticalSplit = false; - CreateSplits(); - m_pSplits[0]->m_lWindows.insert(m_pSplits[0]->m_lWindows.begin(), m_lWindows.begin(), m_lWindows.end()); - m_pSplits[1]->Dock(pWindow); - m_lWindows.clear(); - m_iActiveWindow = 0; - } - break; - case E_DOCK_ORIENTATION_BOTTOM: - { - m_bVerticalSplit = true; - CreateSplits(); - m_pSplits[0]->m_lWindows.insert(m_pSplits[0]->m_lWindows.begin(), m_lWindows.begin(), m_lWindows.end()); - m_pSplits[1]->Dock(pWindow); - m_lWindows.clear(); - m_iActiveWindow = 0; - } - break; - } - } - else - { - switch (eOrientation) - { - case E_DOCK_ORIENTATION_CENTER: - IM_ASSERT(false); - break; - case E_DOCK_ORIENTATION_TOP: - { - Container* pSplit0 = m_pSplits[0]; - Container* pSplit1 = m_pSplits[1]; - CreateSplits(); - m_pSplits[0]->m_lWindows.push_back(pWindow); - m_pSplits[1]->m_bVerticalSplit = m_bVerticalSplit; - m_pSplits[1]->m_fSplitRatio = m_fSplitRatio; - m_pSplits[1]->m_pSplits[0] = pSplit0; - m_pSplits[1]->m_pSplits[1] = pSplit1; - m_pSplits[1]->m_pSplits[0]->m_pParent = m_pSplits[1]; - m_pSplits[1]->m_pSplits[1]->m_pParent = m_pSplits[1]; - m_fSplitRatio = WindowManager::GetInstance()->GetConfig().m_fDragMarginSizeRatio; - m_bVerticalSplit = true; - } - break; - case E_DOCK_ORIENTATION_LEFT: - { - Container* pSplit0 = m_pSplits[0]; - Container* pSplit1 = m_pSplits[1]; - CreateSplits(); - m_pSplits[0]->m_lWindows.push_back(pWindow); - m_pSplits[1]->m_bVerticalSplit = m_bVerticalSplit; - m_pSplits[1]->m_fSplitRatio = m_fSplitRatio; - m_pSplits[1]->m_pSplits[0] = pSplit0; - m_pSplits[1]->m_pSplits[1] = pSplit1; - m_pSplits[1]->m_pSplits[0]->m_pParent = m_pSplits[1]; - m_pSplits[1]->m_pSplits[1]->m_pParent = m_pSplits[1]; - m_fSplitRatio = WindowManager::GetInstance()->GetConfig().m_fDragMarginSizeRatio; - m_bVerticalSplit = false; - } - break; - case E_DOCK_ORIENTATION_RIGHT: - { - Container* pSplit0 = m_pSplits[0]; - Container* pSplit1 = m_pSplits[1]; - CreateSplits(); - m_pSplits[1]->m_lWindows.push_back(pWindow); - m_pSplits[0]->m_bVerticalSplit = m_bVerticalSplit; - m_pSplits[0]->m_fSplitRatio = m_fSplitRatio; - m_pSplits[0]->m_pSplits[0] = pSplit0; - m_pSplits[0]->m_pSplits[1] = pSplit1; - m_pSplits[0]->m_pSplits[0]->m_pParent = m_pSplits[0]; - m_pSplits[0]->m_pSplits[1]->m_pParent = m_pSplits[0]; - m_fSplitRatio = 1.f - WindowManager::GetInstance()->GetConfig().m_fDragMarginSizeRatio; - m_bVerticalSplit = false; - } - break; - case E_DOCK_ORIENTATION_BOTTOM: - { - Container* pSplit0 = m_pSplits[0]; - Container* pSplit1 = m_pSplits[1]; - CreateSplits(); - m_pSplits[1]->m_lWindows.push_back(pWindow); - m_pSplits[0]->m_bVerticalSplit = m_bVerticalSplit; - m_pSplits[0]->m_fSplitRatio = m_fSplitRatio; - m_pSplits[0]->m_pSplits[0] = pSplit0; - m_pSplits[0]->m_pSplits[1] = pSplit1; - m_pSplits[0]->m_pSplits[0]->m_pParent = m_pSplits[0]; - m_pSplits[0]->m_pSplits[1]->m_pParent = m_pSplits[0]; - m_fSplitRatio = 1.f - WindowManager::GetInstance()->GetConfig().m_fDragMarginSizeRatio; - m_bVerticalSplit = true; - } - break; - } - } - } - } - - bool Container::UnDock(Window* pWindow) - { - if (std::find(m_lWindows.begin(), m_lWindows.end(), pWindow) != m_lWindows.end()) - { - m_lWindows.remove(pWindow); - if (m_iActiveWindow >= int(m_lWindows.size())) - { - m_iActiveWindow = int(m_lWindows.size() - 1); - } - return true; - } - - if (NULL != m_pSplits[0] && NULL != m_pSplits[1]) - { - if (m_pSplits[0]->UnDock(pWindow)) - { - if (m_pSplits[0]->IsEmpty()) - { - if (m_pSplits[1]->IsSplit()) - { - Container* pSplit = m_pSplits[1]; - m_bVerticalSplit = pSplit->m_bVerticalSplit; - IMGUI_DELETE_NULL(Container, m_pSplits[0]); - m_pSplits[0] = pSplit->m_pSplits[0]; - m_pSplits[1] = pSplit->m_pSplits[1]; - pSplit->m_pSplits[0] = NULL; - pSplit->m_pSplits[1] = NULL; - m_pSplits[0]->m_pParent = this; - m_pSplits[1]->m_pParent = this; - IMGUI_DELETE_NULL(Container, pSplit); - } - else - { - m_lWindows.insert(m_lWindows.end(), m_pSplits[1]->m_lWindows.begin(), m_pSplits[1]->m_lWindows.end()); - m_pSplits[1]->m_lWindows.clear(); - m_pSplits[1]->m_iActiveWindow = 0; - IMGUI_DELETE_NULL(Container, m_pSplits[0]); - IMGUI_DELETE_NULL(Container, m_pSplits[1]); - } - } - return true; - } - - if (m_pSplits[1]->UnDock(pWindow)) - { - if (m_pSplits[1]->IsEmpty()) - { - if (m_pSplits[0]->IsSplit()) - { - Container* pSplit = m_pSplits[0]; - m_bVerticalSplit = pSplit->m_bVerticalSplit; - IMGUI_DELETE_NULL(Container, m_pSplits[1]); - m_pSplits[0] = pSplit->m_pSplits[0]; - m_pSplits[1] = pSplit->m_pSplits[1]; - pSplit->m_pSplits[0] = NULL; - pSplit->m_pSplits[1] = NULL; - m_pSplits[0]->m_pParent = this; - m_pSplits[1]->m_pParent = this; - IMGUI_DELETE_NULL(Container, pSplit); - } - else - { - m_lWindows.insert(m_lWindows.end(), m_pSplits[0]->m_lWindows.begin(), m_pSplits[0]->m_lWindows.end()); - m_pSplits[0]->m_lWindows.clear(); - m_pSplits[0]->m_iActiveWindow = 0; - IMGUI_DELETE_NULL(Container, m_pSplits[0]); - IMGUI_DELETE_NULL(Container, m_pSplits[1]); - } - } - return true; - } - } - - return false; - } - - bool Container::IsEmpty() - { - //IM_ASSERT(IsSplit() != HasWindowTabbed()); - return !(IsSplit() || HasWindowTabbed()); - } - - bool Container::IsSplit() - { - IM_ASSERT((NULL == m_pSplits[0]) == (NULL == m_pSplits[1])); - return (NULL != m_pSplits[0] && NULL != m_pSplits[1]); - } - - bool Container::HasWindowTabbed() - { - return m_lWindows.size() > 0; - } - - Container* Container::HasWindow(const Window* pWindow) - { - if (std::find(m_lWindows.begin(), m_lWindows.end(), pWindow) != m_lWindows.end()) - { - return this; - } - else - { - if (NULL != m_pSplits[0]) - { - Container* pContainer = m_pSplits[0]->HasWindow(pWindow); - if (NULL != pContainer) - { - return pContainer; - } - } - if (NULL != m_pSplits[1]) - { - Container* pContainer = m_pSplits[1]->HasWindow(pWindow); - if (NULL != pContainer) - { - return pContainer; - } - } - } - return NULL; - } - - PlatformWindow* Container::GetPlatformWindowParent() const - { - return m_pParentWindow; - } - - void Container::Paint() - { - WindowManager* pWindowManager = WindowManager::GetInstance(); - ImGuiWindow* pWindow = ImGui::GetCurrentWindow(); - const ImGuiStyle& oStyle = ImGui::GetStyle(); - ImDrawList* pDrawList = ImGui::GetWindowDrawList(); - - const ImVec2 oPos = ImGui::GetWindowPos(); - const ImVec2 oSize = ImGui::GetWindowSize(); - const ImVec2 oMin = ImVec2(oPos.x + 1, oPos.y + 1); - const ImVec2 oMax = ImVec2(oPos.x + oSize.x - 2, oPos.y + oSize.y - 2); - - m_oLastPosition = oPos; - m_oLastSize = oSize; - - const int iSeparatorHalfSize = 2; - const int iSeparatorSize = iSeparatorHalfSize * 2; - - if (IsSplit()) - { - if (m_bVerticalSplit) - { - float iFirstHeight = oSize.y * m_fSplitRatio - iSeparatorHalfSize - pWindow->WindowPadding.x; - - ImGui::BeginChild("Split1", ImVec2(0, iFirstHeight), false, ImGuiWindowFlags_NoScrollbar); - m_pSplits[0]->Paint(); - ImGui::EndChild(); - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); - ImRect oSeparatorRect(0, iFirstHeight, oSize.x, iFirstHeight + iSeparatorSize); - ImGui::Button("", oSeparatorRect.GetSize()); - if (ImGui::IsItemHovered() || m_bIsDrag) - { - ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS); - } - ImGui::PopStyleVar(1); - - if (ImGui::IsItemActive()) - { - if (!m_bIsDrag) - { - m_bIsDrag = true; - } - m_fSplitRatio += ImGui::GetIO().MouseDelta.y / oSize.y; - m_fSplitRatio = ImClamp(m_fSplitRatio, 0.05f, 0.95f); - - } - else - { - m_bIsDrag = false; - } - - ImGui::BeginChild("Split2", ImVec2(0, 0), false, ImGuiWindowFlags_NoScrollbar); - m_pSplits[1]->Paint(/*iX, iY + iFirstHeight, iWidth, iSecondHeight*/); - ImGui::EndChild(); - } - else - { - float iFirstWidth = oSize.x * m_fSplitRatio - iSeparatorHalfSize - pWindow->WindowPadding.y; - ImGui::BeginChild("Split1", ImVec2(iFirstWidth, 0), false, ImGuiWindowFlags_NoScrollbar); - m_pSplits[0]->Paint(); - ImGui::EndChild(); - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); - ImGui::SameLine(); - - ImRect oSeparatorRect(iFirstWidth, 0, iFirstWidth + iSeparatorSize, oSize.y); - ImGui::Button("", oSeparatorRect.GetSize()); - - if (ImGui::IsItemHovered() || m_bIsDrag) - { - ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); - } - ImGui::PopStyleVar(1); - - if (ImGui::IsItemActive()) - { - if (!m_bIsDrag) - { - m_bIsDrag = true; - } - - m_fSplitRatio += ImGui::GetIO().MouseDelta.x / oSize.x; - m_fSplitRatio = ImClamp(m_fSplitRatio, 0.05f, 0.95f); - } - else - { - m_bIsDrag = false; - } - - ImGui::SameLine(); - - ImGui::BeginChild("Split2", ImVec2(0, 0), false, ImGuiWindowFlags_NoScrollbar); - m_pSplits[1]->Paint(); - ImGui::EndChild(); - } - } - else if (HasWindowTabbed()) - { - ImGui::InvisibleButton("TabListButton", ImVec2(16, 16)); - ImGui::SameLine(); - - if (ImGui::BeginPopupContextItem("TabListMenu", 0)) - { - int iIndex = 0; - for (WindowList::const_iterator itWindow = m_lWindows.begin(); itWindow != m_lWindows.end(); ++itWindow, ++iIndex) - { - if (ImGui::Selectable((*itWindow)->GetTitle())) - { - m_iActiveWindow = iIndex; - } - } - ImGui::EndPopup(); - } - - ImColor oLinesColor = ImColor(160, 160, 160, 255); - if (ImGui::IsItemHovered()) - { - oLinesColor = ImColor(255, 255, 255, 255); - } - ImVec2 oButtonMin = ImGui::GetItemRectMin(); - ImVec2 oButtonMax = ImGui::GetItemRectMax(); - ImVec2 oButtonSize = ImVec2(oButtonMax.x - oButtonMin.x, oButtonMax.y - oButtonMin.y); - pDrawList->AddLine( - ImVec2(oButtonMin.x + 1, oButtonMin.y + oButtonSize.y / 2), - ImVec2(oButtonMax.x - 1, oButtonMin.y + oButtonSize.y / 2), - oLinesColor); - - pDrawList->AddLine( - ImVec2(oButtonMin.x + 1, oButtonMin.y + oButtonSize.y / 2 - 4), - ImVec2(oButtonMax.x - 1, oButtonMin.y + oButtonSize.y / 2 - 4), - oLinesColor); - - pDrawList->AddLine( - ImVec2(oButtonMin.x + 1, oButtonMin.y + oButtonSize.y / 2 + 4), - ImVec2(oButtonMax.x - 1, oButtonMin.y + oButtonSize.y / 2 + 4), - oLinesColor); - - pDrawList->ChannelsSplit(2); - - //Tabs - int iIndex = 0; - int iNewActive = m_iActiveWindow; - int iSize = int(m_lWindows.size()); - for (WindowList::iterator it = m_lWindows.begin(); it != m_lWindows.end(); ++it) - { - const ImVec2 oTextSize = ImGui::CalcTextSize((*it)->GetTitle()); - ImVec2 oRectSize(oTextSize.x + 15, 25); - - ImGui::PushID(iIndex); - - bool bSelected = iIndex == m_iActiveWindow; - if (ImGui::InvisibleButton((*it)->GetId(), oRectSize)) - { - iNewActive = iIndex; - } - if (iIndex < (iSize - 1)) - { - ImGui::SameLine(); - } - - if (ImGui::IsItemActive()) - { - if (ImGui::IsMouseDragging()) - { - pWindowManager->StartDragWindow(*it); - } - } - - ImColor oNormalTab(50, 50, 50, 255); // normal - ImColor oSelectedTab(37, 37, 37, 255); // selected - ImColor oBorderColor(72, 72, 72, 255); // border - - ImVec2 oRectMin = ImGui::GetItemRectMin(); - ImVec2 oRectMax = ImGui::GetItemRectMax(); - - const float fOverlap = 10.f; - const float fSlopWidth = 30.f; - const float sSlopP1Ratio = 0.6f; - const float fSlopP2Ratio = 0.4f; - const float fSlopHRatio = 0.f; - const float fShadowDropSize = 15.f; - const float fShadowSlopRatio = 0.6f; - const float fShadowAlpha = 0.75f; - - pDrawList->PathClear(); - if (bSelected) - { - pDrawList->ChannelsSetCurrent(1); - } - else - { - pDrawList->ChannelsSetCurrent(0); - } - - //Drop shadows - const ImVec2 uv = GImGui->FontTexUvWhitePixel; - pDrawList->PrimReserve(3, 3); - pDrawList->PrimWriteIdx((ImDrawIdx)(pDrawList->_VtxCurrentIdx)); pDrawList->PrimWriteIdx((ImDrawIdx)(pDrawList->_VtxCurrentIdx + 1)); pDrawList->PrimWriteIdx((ImDrawIdx)(pDrawList->_VtxCurrentIdx + 2)); - pDrawList->PrimWriteVtx(ImVec2(oRectMin.x - fOverlap - fShadowDropSize, oRectMax.y), uv, ImColor(0.f, 0.f, 0.f, 0.f)); - pDrawList->PrimWriteVtx(ImVec2(oRectMin.x - fOverlap + fSlopWidth * fShadowSlopRatio, oRectMin.y), uv, ImColor(0.f, 0.f, 0.f, 0.f)); - pDrawList->PrimWriteVtx(ImVec2(oRectMin.x - fOverlap + fSlopWidth * fShadowSlopRatio, oRectMax.y), uv, ImColor(0.f, 0.f, 0.f, fShadowAlpha)); - if (bSelected) - { - pDrawList->PrimReserve(3, 3); - pDrawList->PrimWriteIdx((ImDrawIdx)(pDrawList->_VtxCurrentIdx)); pDrawList->PrimWriteIdx((ImDrawIdx)(pDrawList->_VtxCurrentIdx + 1)); pDrawList->PrimWriteIdx((ImDrawIdx)(pDrawList->_VtxCurrentIdx + 2)); - pDrawList->PrimWriteVtx(ImVec2(oRectMax.x + fOverlap + fShadowDropSize, oRectMax.y), uv, ImColor(0.f, 0.f, 0.f, 0.f)); - pDrawList->PrimWriteVtx(ImVec2(oRectMax.x + fOverlap - fSlopWidth * fShadowSlopRatio, oRectMin.y), uv, ImColor(0.f, 0.f, 0.f, 0.f)); - pDrawList->PrimWriteVtx(ImVec2(oRectMax.x + fOverlap - fSlopWidth * fShadowSlopRatio, oRectMax.y), uv, ImColor(0.f, 0.f, 0.f, fShadowAlpha)); - } - - // Draw tab and border - if (bSelected) - { - pDrawList->PathLineTo(ImVec2(oMin.x, oRectMax.y)); - } - pDrawList->PathLineTo(ImVec2(oRectMin.x - fOverlap, oRectMax.y)); - pDrawList->PathBezierCurveTo( - ImVec2(oRectMin.x + fSlopWidth * sSlopP1Ratio - fOverlap, oRectMin.y + (oRectMax.y - oRectMin.y) * fSlopHRatio), - ImVec2(oRectMin.x + fSlopWidth * fSlopP2Ratio - fOverlap, oRectMin.y), - ImVec2(oRectMin.x + fSlopWidth - fOverlap, oRectMin.y) - ); - pDrawList->PathLineTo(ImVec2(oRectMax.x - fSlopWidth + fOverlap, oRectMin.y)); - pDrawList->PathBezierCurveTo( - ImVec2(oRectMax.x - fSlopWidth * fSlopP2Ratio + fOverlap, oRectMin.y), - ImVec2(oRectMax.x - fSlopWidth * sSlopP1Ratio + fOverlap, oRectMin.y + (oRectMax.y - oRectMin.y) * fSlopHRatio), - ImVec2(oRectMax.x + fOverlap, oRectMax.y) - ); - - if (bSelected) - { - pDrawList->AddConvexPolyFilled(pDrawList->_Path.Data + 1, pDrawList->_Path.Size - 1, bSelected ? oSelectedTab : oNormalTab, true); - if (oMax.x > (oRectMax.x + fOverlap)) - { - pDrawList->PathLineTo(ImVec2(oMax.x, oRectMax.y)); - } - pDrawList->AddPolyline(pDrawList->_Path.Data, pDrawList->_Path.Size, oBorderColor, false, 1.5f, true); - } - else - { - pDrawList->AddConvexPolyFilled(pDrawList->_Path.Data, pDrawList->_Path.Size, bSelected ? oSelectedTab : oNormalTab, true); - } - - pDrawList->PathClear(); - - ImGui::RenderTextClipped( - oRectMin - , ImVec2(oRectMax.x, oRectMax.y) - , (*it)->GetTitle() - , NULL - , &oTextSize - , ImVec2(0.5f, 0.5f) - ); - - if (ImGui::BeginPopupContextItem("TabMenu")) - { - if (ImGui::Selectable("Close")) - { - (*it)->Destroy(); - } - if (ImGui::BeginMenu("Dock to")) - { - int iIndex1 = 0; - - if (pWindowManager->GetMainPlatformWindow()->GetContainer()->IsEmpty()) - { - ImGui::PushID(0); - if (ImGui::Selectable("Main")) pWindowManager->Dock((*it)); - ImGui::PopID(); - ++iIndex1; - } - const WindowList& lWindows = pWindowManager->GetWindowList(); - for (WindowList::const_iterator itWindow = lWindows.begin(); itWindow != lWindows.end(); ++itWindow) - { - if ((*it) != (*itWindow)) - { - ImGui::PushID(iIndex1); - if (ImGui::BeginMenu((*itWindow)->GetTitle())) - { - bool bHovered = false; - PlatformWindow* pPlatformWindow = pWindowManager->GetWindowParent((*itWindow)); - - ImVec2 oLastWinPos = (*itWindow)->GetLastPosition(); - ImVec2 oLastWinSize = (*itWindow)->GetLastSize(); - - ImGui::PushID(0); - if (ImGui::Selectable("Tab")) pWindowManager->DockWith((*it), (*itWindow), E_DOCK_ORIENTATION_CENTER); - if (ImGui::IsItemHovered() && NULL != pPlatformWindow) - { - bHovered = true; - pWindowManager->DrawWindowArea(pPlatformWindow, oLastWinPos, oLastWinSize, ImColor(0.f, 0.5f, 1.f, 0.5f)); - } - ImGui::PopID(); - - ImGui::PushID(1); - if (ImGui::Selectable("Top")) pWindowManager->DockWith((*it), (*itWindow), E_DOCK_ORIENTATION_TOP); - if (ImGui::IsItemHovered() && NULL != pPlatformWindow) - { - bHovered = true; - pWindowManager->DrawWindowArea(pPlatformWindow, oLastWinPos, ImVec2(oLastWinSize.x, oLastWinSize.y / 2.f), ImColor(0.f, 0.5f, 1.f, 0.5f)); - } - ImGui::PopID(); - - ImGui::PushID(2); - if (ImGui::Selectable("Left")) pWindowManager->DockWith((*it), (*itWindow), E_DOCK_ORIENTATION_LEFT); - if (ImGui::IsItemHovered() && NULL != pPlatformWindow) - { - bHovered = true; - pWindowManager->DrawWindowArea(pPlatformWindow, oLastWinPos, ImVec2(oLastWinSize.x / 2.f, oLastWinSize.y), ImColor(0.f, 0.5f, 1.f, 0.5f)); - } - ImGui::PopID(); - - ImGui::PushID(3); - if (ImGui::Selectable("Right")) pWindowManager->DockWith((*it), (*itWindow), E_DOCK_ORIENTATION_RIGHT); - if (ImGui::IsItemHovered() && NULL != pPlatformWindow) - { - bHovered = true; - pWindowManager->DrawWindowArea(pPlatformWindow, ImVec2(oLastWinPos.x + oLastWinSize.x / 2.f, oLastWinPos.y), ImVec2(oLastWinSize.x / 2.f, oLastWinSize.y), ImColor(0.f, 0.5f, 1.f, 0.5f)); - } - ImGui::PopID(); - - ImGui::PushID(4); - if (ImGui::Selectable("Bottom")) pWindowManager->DockWith((*it), (*itWindow), E_DOCK_ORIENTATION_BOTTOM); - if (ImGui::IsItemHovered() && NULL != pPlatformWindow) - { - bHovered = true; - pWindowManager->DrawWindowArea(pPlatformWindow, ImVec2(oLastWinPos.x, oLastWinPos.y + oLastWinSize.y / 2.f), ImVec2(oLastWinSize.x, oLastWinSize.y / 2.f), ImColor(0.f, 0.5f, 1.f, 0.5f)); - } - ImGui::PopID(); - - if (!bHovered) - { - if (NULL != pPlatformWindow) - { - pWindowManager->DrawWindowArea(pPlatformWindow, oLastWinPos, oLastWinSize, ImColor(0.f, 0.5f, 1.f, 0.5f)); - } - } - - ImGui::EndMenu(); - } - ImGui::PopID(); - } - ++iIndex1; - } - - ImGui::EndMenu(); - } - if (ImGui::Selectable("Float")) - { - pWindowManager->Float((*it)); - } - - ImGui::EndPopup(); - } - - ImGui::PopID(); - - ++iIndex; - } - m_iActiveWindow = iNewActive; - pDrawList->ChannelsMerge(); - - WindowList::iterator itActiveWindow = m_lWindows.begin(); - std::advance(itActiveWindow, m_iActiveWindow); - - //Draw active - IM_ASSERT(itActiveWindow != m_lWindows.end()); - if (itActiveWindow != m_lWindows.end()) - { - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, oStyle.WindowPadding); - //ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, ImColor(59, 59, 59, 255)); - ImGui::BeginChild((*itActiveWindow)->GetId(), ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar); - - ImVec2 oWinPos = ImGui::GetWindowPos(); - ImVec2 oWinSize = ImGui::GetWindowSize(); - - for (WindowList::iterator it = m_lWindows.begin(); it != m_lWindows.end(); ++it) - { - (*it)->m_oLastPosition = oWinPos; - (*it)->m_oLastSize = oWinSize; - } - (*itActiveWindow)->OnGui(); - - ImGui::EndChild(); - //ImGui::PopStyleColor(1); - ImGui::PopStyleVar(1); - } - } - else - { - // This case can happened only where it's main container - IM_ASSERT(m_pParent == NULL); - } - } - - Container* Container::GetBestDocking(const ImVec2 oCursorPos, EDockOrientation& oOutOrientation, ImVec2& oOutAreaPos, ImVec2& oOutAreaSize) - { - if (m_pParent == NULL || - (oCursorPos.x >= m_oLastPosition.x && oCursorPos.x <= (m_oLastPosition.x + m_oLastSize.x) && - oCursorPos.y >= m_oLastPosition.y && oCursorPos.y <= (m_oLastPosition.y + m_oLastSize.y))) - { - if (IsSplit()) - { - Container* pBestContainer = NULL; - pBestContainer = m_pSplits[0]->GetBestDocking(oCursorPos, oOutOrientation, oOutAreaPos, oOutAreaSize); - if (NULL != pBestContainer) - { - return pBestContainer; - } - pBestContainer = m_pSplits[1]->GetBestDocking(oCursorPos, oOutOrientation, oOutAreaPos, oOutAreaSize); - if (NULL != pBestContainer) - { - return pBestContainer; - } - } - else - { - const float c_fBoxHalfSize = 20.f; - const float c_fBoxSize = c_fBoxHalfSize * 2.f; - const float c_fMinSize = c_fBoxSize * 4.f; - const float c_fSplitRatio = 0.5f; - //const float c_fSplitRatio = oConfig.m_fDragMarginSizeRatio; - const ImColor oBoxColor(200, 200, 255, 255); - const ImColor oBoxHightlightColor(100, 100, 255, 255); - - if (m_oLastSize.x < c_fMinSize && m_oLastSize.y < c_fMinSize) - { - oOutOrientation = E_DOCK_ORIENTATION_CENTER; - oOutAreaPos = m_oLastPosition; - oOutAreaSize = m_oLastSize; - return this; - } - else - { - ImVec2 oCenter = ImVec2(m_oLastPosition.x + m_oLastSize.x / 2.f, m_oLastPosition.y + m_oLastSize.y / 2.f); - - bool bIsInCenter = false; - bool bIsInTop = false; - bool bIsInLeft = false; - bool bIsInRight = false; - bool bIsInBottom = false; - - //Center - ImRect oRectCenter(ImVec2(oCenter.x - c_fBoxHalfSize, oCenter.y - c_fBoxHalfSize), ImVec2(oCenter.x + c_fBoxHalfSize, oCenter.y + c_fBoxHalfSize)); - bIsInCenter = oRectCenter.Contains(oCursorPos); - WindowManager::GetInstance()->DrawWindowArea(m_pParentWindow, oRectCenter.Min, oRectCenter.GetSize(), bIsInCenter ? oBoxHightlightColor : oBoxColor); - - if (m_oLastSize.y >= c_fMinSize) - { - //Top - ImRect oRectTop(ImVec2(oCenter.x - c_fBoxHalfSize, oCenter.y - c_fBoxHalfSize * 4.f), ImVec2(oCenter.x + c_fBoxHalfSize, oCenter.y - c_fBoxHalfSize * 2.f)); - bIsInTop = oRectTop.Contains(oCursorPos); - WindowManager::GetInstance()->DrawWindowArea(m_pParentWindow, oRectTop.Min, oRectTop.GetSize(), bIsInTop ? oBoxHightlightColor : oBoxColor); - - //Bottom - ImRect oRectBottom(ImVec2(oCenter.x - c_fBoxHalfSize, oCenter.y + c_fBoxHalfSize * 2.f), ImVec2(oCenter.x + c_fBoxHalfSize, oCenter.y + c_fBoxHalfSize * 4.f)); - bIsInBottom = oRectBottom.Contains(oCursorPos); - WindowManager::GetInstance()->DrawWindowArea(m_pParentWindow, oRectBottom.Min, oRectBottom.GetSize(), bIsInBottom ? oBoxHightlightColor : oBoxColor); - } - - if (m_oLastSize.x >= c_fMinSize) - { - //Left - ImRect oRectLeft(ImVec2(oCenter.x - c_fBoxHalfSize * 4.f, oCenter.y - c_fBoxHalfSize), ImVec2(oCenter.x - c_fBoxHalfSize * 2.f, oCenter.y + c_fBoxHalfSize)); - bIsInLeft = oRectLeft.Contains(oCursorPos); - WindowManager::GetInstance()->DrawWindowArea(m_pParentWindow, oRectLeft.Min, oRectLeft.GetSize(), bIsInLeft ? oBoxHightlightColor : oBoxColor); - - //Right - ImRect oRectRight(ImVec2(oCenter.x + c_fBoxHalfSize * 2.f, oCenter.y - c_fBoxHalfSize), ImVec2(oCenter.x + c_fBoxHalfSize * 4.f, oCenter.y + c_fBoxHalfSize)); - bIsInRight = oRectRight.Contains(oCursorPos); - WindowManager::GetInstance()->DrawWindowArea(m_pParentWindow, oRectRight.Min, oRectRight.GetSize(), bIsInRight ? oBoxHightlightColor : oBoxColor); - } - - if (bIsInCenter) - { - oOutOrientation = E_DOCK_ORIENTATION_CENTER; - oOutAreaPos = m_oLastPosition; - oOutAreaSize = m_oLastSize; - return this; - } - else if (bIsInTop) - { - oOutOrientation = E_DOCK_ORIENTATION_TOP; - oOutAreaPos = m_oLastPosition; - oOutAreaSize = ImVec2(m_oLastSize.x, m_oLastSize.y * c_fSplitRatio); - return this; - } - else if (bIsInLeft) - { - oOutOrientation = E_DOCK_ORIENTATION_LEFT; - oOutAreaPos = m_oLastPosition; - oOutAreaSize = ImVec2(m_oLastSize.x * c_fSplitRatio, m_oLastSize.y); - return this; - } - else if (bIsInRight) - { - oOutOrientation = E_DOCK_ORIENTATION_RIGHT; - oOutAreaPos = ImVec2(m_oLastPosition.x + m_oLastSize.x * (1.f - c_fSplitRatio), m_oLastPosition.y); - oOutAreaSize = ImVec2(m_oLastSize.x * c_fSplitRatio, m_oLastSize.y); - return this; - } - else if (bIsInBottom) - { - oOutOrientation = E_DOCK_ORIENTATION_BOTTOM; - oOutAreaPos = ImVec2(m_oLastPosition.x, m_oLastPosition.y + m_oLastSize.y * (1.f - c_fSplitRatio)); - oOutAreaSize = ImVec2(m_oLastSize.x, m_oLastSize.y * c_fSplitRatio); - return this; - } - } - } - } - - return NULL; - } - - PlatformWindow::PlatformWindow(bool bMain, bool bIsDragWindow) - { - m_bMain = bMain; - m_bIsDragWindow = bIsDragWindow; - m_pContainer = IMGUI_NEW(Container)(this); - m_pPreviousState = NULL; - - ImGui::GetIO().IniFilename = NULL; - - m_pState = ImGui::CreateContext(); - } - - PlatformWindow::~PlatformWindow() - { - IMGUI_DELETE_NULL(Container, m_pContainer); - - SetState(); - if (!IsMain()) - { - ImGui::GetIO().Fonts = NULL; - } - - RestoreState(); - ImGui::DestroyContext(m_pState); - m_pState = NULL; - } - - void PlatformWindow::OnClose() - { - WindowManager::GetInstance()->OnClosePlatformWindow(this); - } - - static bool s_bStatePush = false; - - bool PlatformWindow::IsStateSet() - { - return s_bStatePush; - } - - void PlatformWindow::SetState() - { - IM_ASSERT(s_bStatePush == false); - s_bStatePush = true; - m_pPreviousState = ImGui::GetCurrentContext(); - ImGui::SetCurrentContext(m_pState); - memcpy(&m_pState->Style, &m_pPreviousState->Style, sizeof(ImGuiStyle) ); - } - - void PlatformWindow::RestoreState() - { - IM_ASSERT(s_bStatePush == true); - s_bStatePush = false; - memcpy(&m_pPreviousState->Style, &m_pState->Style, sizeof(ImGuiStyle) ); - ImGui::SetCurrentContext(m_pPreviousState); - } - - void PlatformWindow::OnLoseFocus() - { - ImGuiContext& g = *m_pState; - g.SetNextWindowPosCond = g.SetNextWindowSizeCond = g.SetNextWindowContentSizeCond = g.SetNextWindowCollapsedCond = g.SetNextWindowFocus = 0; - } - - void PlatformWindow::Paint() - { - PaintBegin(); - WindowManager::GetInstance()->Paint(this); - PaintEnd(); - } - - bool PlatformWindow::IsMain() - { - return m_bMain; - } - - void PlatformWindow::Dock(Window* pWindow) - { - m_pContainer->Dock(pWindow); - } - - bool PlatformWindow::UnDock(Window* pWindow) - { - return m_pContainer->UnDock(pWindow); - } - - Container* PlatformWindow::GetContainer() - { - return m_pContainer; - } - - Container* PlatformWindow::HasWindow(Window* pWindow) - { - return m_pContainer->HasWindow(pWindow); - } - - void PlatformWindow::PaintContainer() - { - m_pContainer->Paint(); - } - - WindowManager::DrawWindowAreaAction::DrawWindowAreaAction(PlatformWindow* pWindow, const ImVec2& oRectPos, const ImVec2& oRectSize, const ImColor& oColor) - : m_oColor(oColor) - { - m_pWindow = pWindow; - m_oRectPos = oRectPos; - m_oRectSize = oRectSize; - } - - WindowManager* WindowManager::s_pInstance = 0; - - ////////////////////////////////////////////////////////////////////////// - - WindowManager::Config::Config() - : m_fDragMarginRatio(0.1f) - , m_fDragMarginSizeRatio(0.25f) - , m_oHightlightAreaColor(0.f, 0.5f, 1.f, 0.5f) - { - } - - ////////////////////////////////////////////////////////////////////////// - - WindowManager::WindowManager() - { - s_pInstance = this; - m_pMainPlatformWindow = NULL; - m_pDragPlatformWindow = NULL; - m_pCurrentPlatformWindow = NULL; - m_pDraggedWindow = NULL; - m_oDragPreviewOffset = ImVec2(-20, -10); - } - - WindowManager::~WindowManager() - { - IMGUI_DELETE_NULL(PlatformWindow, m_pMainPlatformWindow); - IMGUI_DELETE_NULL(PlatformWindow, m_pDragPlatformWindow); - s_pInstance = 0; - ImGui::Shutdown(); - } - - bool WindowManager::Init() - { - m_pMainPlatformWindow = CreatePlatformWindow(true, NULL, false); - if (NULL != m_pMainPlatformWindow) - { - m_pMainPlatformWindow->Show(); - - m_pDragPlatformWindow = CreatePlatformWindow(false, m_pMainPlatformWindow, true); - return true; - } - return false; - } - - bool WindowManager::Run() - { - if (m_pMainPlatformWindow != NULL) - { - ImGuiIO& io = ImGui::GetIO(); - m_pMainPlatformWindow->SetSize(io.DisplaySize); - } - InternalRun(); - return m_pMainPlatformWindow != NULL; - } - - void WindowManager::Exit() - { - //TODO : Manual exit - } - - PlatformWindow* WindowManager::GetMainPlatformWindow() - { - return m_pMainPlatformWindow; - } - - WindowManager::Config& WindowManager::GetConfig() - { - return m_oConfig; - } - - void WindowManager::SetMainTitle(const char* pTitle) - { - if (NULL != m_pMainPlatformWindow) - { - m_pMainPlatformWindow->SetTitle(pTitle); - } - } - - void WindowManager::Dock(Window* pWindow, EDockOrientation eOrientation, PlatformWindow* pToPlatformWindow) - { - DockAction* pAction = IMGUI_NEW(DockAction); - pAction->m_bFloat = false; - pAction->m_pWindow = pWindow; - pAction->m_pWith = NULL; - pAction->m_eOrientation = eOrientation; - pAction->m_pToPlatformWindow = (pToPlatformWindow != NULL) ? pToPlatformWindow : m_pMainPlatformWindow; - pAction->m_pToContainer = NULL; - m_lDockActions.push_back(pAction); - } - - void WindowManager::DockTo(Window* pWindow, EDockOrientation eOrientation, Container* pContainer) - { - IM_ASSERT(NULL != pContainer); - if (NULL != pContainer) - { - DockAction* pAction = IMGUI_NEW(DockAction); - pAction->m_bFloat = false; - pAction->m_pWindow = pWindow; - pAction->m_pWith = NULL; - pAction->m_eOrientation = eOrientation; - pAction->m_pToPlatformWindow = NULL; - pAction->m_pToContainer = pContainer; - m_lDockActions.push_back(pAction); - } - } - - void WindowManager::DockWith(Window* pWindow, Window* pWithWindow, EDockOrientation eOrientation) - { - DockAction* pAction = IMGUI_NEW(DockAction); - pAction->m_bFloat = false; - pAction->m_pWindow = pWindow; - pAction->m_pWith = pWithWindow; - pAction->m_eOrientation = eOrientation; - m_lDockActions.push_back(pAction); - } - - void WindowManager::Float(Window* pWindow, const ImVec2& oPosition, const ImVec2& oSize) - { - DockAction* pAction = IMGUI_NEW(DockAction); - pAction->m_bFloat = true; - pAction->m_pWindow = pWindow; - pAction->m_oPosition = oPosition; - pAction->m_oSize = oSize; - m_lDockActions.push_back(pAction); - } - - const WindowList& WindowManager::GetWindowList() const - { - return m_lWindows; - } - - PlatformWindow* WindowManager::GetCurrentPlatformWindow() - { - return m_pCurrentPlatformWindow; - } - - PlatformWindow* WindowManager::GetWindowParent(Window* pWindow) - { - Container* pContainer = m_pMainPlatformWindow->HasWindow(pWindow); - if (NULL != pContainer) - { - return m_pMainPlatformWindow; - } - - for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end(); ++it) - { - pContainer = (*it)->HasWindow(pWindow); - if (NULL != pContainer) - { - return *it; - } - } - IM_ASSERT(false); - return NULL; - } - - void WindowManager::Log(const char* pFormat, ...) - { - char pBuffer[32768]; - va_list argptr; - va_start(argptr, pFormat); - ImFormatStringV(pBuffer, sizeof(char) * 32767, pFormat, argptr); - va_end(argptr); - LogFormatted(pBuffer); - } - - void WindowManager::PreUpdate() - { - if (NULL != m_pMainPlatformWindow) - { - m_pMainPlatformWindow->PreUpdate(); - } - - for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end(); ++it) - { - (*it)->PreUpdate(); - } - } - - void WindowManager::Update() - { - UpdatePlatformwWindowActions(); - UpdateDockActions(); - UpdateOrphans(); - - while (m_lToDestroyWindows.begin() != m_lToDestroyWindows.end()) - { - Window* pWindow = *m_lToDestroyWindows.begin(); - - m_lToDestroyWindows.remove(pWindow); - m_lOrphanWindows.remove(pWindow); - m_lWindows.remove(pWindow); - - InternalUnDock(pWindow); - - IMGUI_DELETE(Window, pWindow); - } - - while (m_lToDestroyPlatformWindows.begin() != m_lToDestroyPlatformWindows.end()) - { - PlatformWindow* pPlatformWindow = *m_lToDestroyPlatformWindows.begin(); - m_lToDestroyPlatformWindows.remove(pPlatformWindow); - m_lPlatformWindows.remove(pPlatformWindow); - IMGUI_DELETE(PlatformWindow, pPlatformWindow); - } - - UpdateDragWindow(); - - m_pCurrentPlatformWindow = m_pMainPlatformWindow; - if (NULL != m_pMainPlatformWindow) - { - m_pMainPlatformWindow->Paint(); - } - - for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end(); ++it) - { - m_pCurrentPlatformWindow = (*it); - (*it)->Paint(); - } - - m_pCurrentPlatformWindow = NULL; - } - - void WindowManager::UpdatePlatformwWindowActions() - { - while (m_lPlatformWindowActions.begin() != m_lPlatformWindowActions.end()) - { - PlatformWindowAction* pAction = *m_lPlatformWindowActions.begin(); - - IM_ASSERT((pAction->m_iFlags & E_PLATFORM_WINDOW_ACTION_SHOW & E_PLATFORM_WINDOW_ACTION_HIDE) == 0); // Can't show and hide - - if (pAction->m_iFlags & E_PLATFORM_WINDOW_ACTION_DESTOY) - { - //pAction->m_pPlatformWindow->Show(); - //todo destroy - bool bFound = false; - if (m_pMainPlatformWindow == pAction->m_pPlatformWindow) - { - while (m_lPlatformWindows.begin() != m_lPlatformWindows.end()) - { - IMGUI_DELETE(PlatformWindow, *m_lPlatformWindows.begin()); - m_lPlatformWindows.erase(m_lPlatformWindows.begin()); - } - IMGUI_DELETE(PlatformWindow, m_pMainPlatformWindow); - m_pMainPlatformWindow = NULL; - bFound = true; - } - else - { - for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end(); ++it) - { - if (*it == pAction->m_pPlatformWindow) - { - IMGUI_DELETE(PlatformWindow, *it); - m_lPlatformWindows.erase(it); - bFound = true; - break; - } - } - } - - if (!bFound) - { - IM_ASSERT(false, "ImwPlatformWindow not found, maybe already closed"); - } - } - - if (pAction->m_iFlags & E_PLATFORM_WINDOW_ACTION_SHOW) - { - pAction->m_pPlatformWindow->Show(); - } - - if (pAction->m_iFlags & E_PLATFORM_WINDOW_ACTION_HIDE) - { - pAction->m_pPlatformWindow->Hide(); - } - - if (pAction->m_iFlags & E_PLATFORM_WINDOW_ACTION_SET_POSITION) - { - pAction->m_pPlatformWindow->SetPosition(pAction->m_oPosition); - } - - if (pAction->m_iFlags & E_PLATFORM_WINDOW_ACTION_SET_SIZE) - { - pAction->m_pPlatformWindow->SetSize(pAction->m_oSize); - } - - IMGUI_DELETE(PlatformWindowAction, *m_lPlatformWindowActions.begin()); - m_lPlatformWindowActions.erase(m_lPlatformWindowActions.begin()); - } - } - - void WindowManager::UpdateDockActions() - { - while (m_lDockActions.begin() != m_lDockActions.end()) - { - DockAction* pAction = *m_lDockActions.begin(); - - InternalUnDock(pAction->m_pWindow); - - if (pAction->m_bFloat) - { - if (!InternalFloat(pAction->m_pWindow, pAction->m_oPosition, pAction->m_oSize) ) - { - InternalDock(pAction->m_pWindow, E_DOCK_ORIENTATION_LEFT, m_pMainPlatformWindow); - } - } - else - { - if (NULL != pAction->m_pWith) - { - InternalDockWith(pAction->m_pWindow, pAction->m_pWith, pAction->m_eOrientation); - } - else if (NULL != pAction->m_pToContainer) - { - InternalDockTo(pAction->m_pWindow, pAction->m_eOrientation, pAction->m_pToContainer); - } - else - { - InternalDock(pAction->m_pWindow, pAction->m_eOrientation, pAction->m_pToPlatformWindow); - } - } - - m_lOrphanWindows.remove(pAction->m_pWindow); - - IMGUI_DELETE(DockAction, pAction); - m_lDockActions.erase(m_lDockActions.begin()); - } - } - - void WindowManager::UpdateOrphans() - { - while (m_lOrphanWindows.begin() != m_lOrphanWindows.end()) - { - if (m_pMainPlatformWindow->m_pContainer->IsEmpty()) - { - InternalDock(*m_lOrphanWindows.begin(), E_DOCK_ORIENTATION_CENTER, m_pMainPlatformWindow); - } - else - { - ImVec2 oSize = ImVec2(300, 300); - ImVec2 oPos = m_pMainPlatformWindow->GetPosition(); - ImVec2 oMainSize = m_pMainPlatformWindow->GetSize(); - oPos.x += (oMainSize.x - oSize.x) / 2; - oPos.y += (oMainSize.y - oSize.y) / 2; - InternalFloat(*m_lOrphanWindows.begin(), oPos, oSize); - } - m_lOrphanWindows.erase(m_lOrphanWindows.begin()); - } - } - - void WindowManager::Paint(PlatformWindow* pWindow) - { - if (!pWindow->GetContainer()->IsEmpty() ) - { - float fY = 0.f; - - ImGui::SetNextWindowPos(ImVec2(0, fY), ImGuiSetCond_Always); - ImGui::SetNextWindowSize(ImVec2(pWindow->GetSize().x, pWindow->GetSize().y - fY), ImGuiSetCond_Always); - int iFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse; - - if (NULL != m_pDraggedWindow) - { - iFlags += ImGuiWindowFlags_NoInputs; - } - - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(5.0f, 5.0f)); - char name[64]; - ImFormatString(name, sizeof(name), "Window %p", pWindow); - ImGui::Begin(name, NULL, iFlags); - pWindow->PaintContainer(); - ImGui::End(); - ImGui::PopStyleVar(1); - - ImGui::Begin("##Overlay", NULL, ImVec2(0, 0), 0.f, ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize); - ImDrawList* pDrawList = ImGui::GetWindowDrawList(); - for (ImwList::iterator it = m_lDrawWindowAreas.begin(); it != m_lDrawWindowAreas.end();) - { - const DrawWindowAreaAction& oAction = *it; - - if (pWindow == oAction.m_pWindow) - { - ImVec2 oPosA = oAction.m_oRectPos; - ImVec2 oPosB = oAction.m_oRectSize; - oPosB.x += oPosA.x; - oPosB.y += oPosA.y; - - pDrawList->PushClipRectFullScreen(); - pDrawList->AddRectFilled(oPosA, oPosB, oAction.m_oColor); - pDrawList->PopClipRect(); - ImwList::iterator toRemove = it; - ++it; - m_lDrawWindowAreas.erase(toRemove); - } - else - { - ++it; - } - } - - ImGui::End(); - } - } - - static ImVec2 GetCursorPos() - { - ImGuiIO& io = ImGui::GetIO(); - return io.MousePos; - } - - void WindowManager::StartDragWindow(Window* pWindow) - { - if (NULL == m_pDraggedWindow) - { - m_pDraggedWindow = pWindow; - - PlatformWindowAction* pAction = IMGUI_NEW(PlatformWindowAction); - pAction->m_pPlatformWindow = m_pDragPlatformWindow; - pAction->m_iFlags = E_PLATFORM_WINDOW_ACTION_SHOW | E_PLATFORM_WINDOW_ACTION_SET_POSITION | E_PLATFORM_WINDOW_ACTION_SET_SIZE; - ImVec2 oCursorPos = GetCursorPos(); - pAction->m_oPosition = ImVec2(oCursorPos.x + m_oDragPreviewOffset.x, oCursorPos.y + m_oDragPreviewOffset.y); - pAction->m_oSize = ImVec2(pWindow->GetLastSize().x, pWindow->GetLastSize().y); - m_lPlatformWindowActions.push_back(pAction); - - Dock(pWindow, E_DOCK_ORIENTATION_CENTER, m_pDragPlatformWindow); - m_pDragPlatformWindow->m_pState->IO.MouseDown[0] = true; - } - } - - void WindowManager::StopDragWindow() - { - PlatformWindowAction* pAction = IMGUI_NEW(PlatformWindowAction); - pAction->m_pPlatformWindow = m_pDragPlatformWindow; - pAction->m_iFlags = E_PLATFORM_WINDOW_ACTION_HIDE; - m_pDragPlatformWindow->Hide(); - m_lPlatformWindowActions.push_back(pAction); - m_pDraggedWindow = NULL; - } - - void WindowManager::UpdateDragWindow() - { - if (NULL != m_pDraggedWindow) - { - m_pCurrentPlatformWindow = m_pDragPlatformWindow; - m_pDragPlatformWindow->Paint(); - m_pCurrentPlatformWindow = NULL; - - ImVec2 oCursorPos = GetCursorPos(); - m_pDragPlatformWindow->SetPosition(ImVec2(oCursorPos.x + m_oDragPreviewOffset.x, oCursorPos.y + m_oDragPreviewOffset.y)); - - //Search best dock area - EDockOrientation eBestDockOrientation; - ImVec2 oHightlightPos; - ImVec2 oHightlightSize; - Container* pBestContainer = GetBestDocking(m_pMainPlatformWindow, oCursorPos, eBestDockOrientation, oHightlightPos, oHightlightSize); - if (NULL == pBestContainer) - { - for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end() && NULL == pBestContainer; ++it) - { - pBestContainer = GetBestDocking(*it, oCursorPos, eBestDockOrientation, oHightlightPos, oHightlightSize); - } - } - if (pBestContainer) - { - DrawWindowArea(pBestContainer->GetPlatformWindowParent(), oHightlightPos, oHightlightSize, m_oConfig.m_oHightlightAreaColor); - } - - ImGuiIO& io = ImGui::GetIO(); - if (!io.MouseDown[0]) - { - if (NULL != pBestContainer) - { - DockTo(m_pDraggedWindow, eBestDockOrientation, pBestContainer); - } - else - { - Float(m_pDraggedWindow, m_pDragPlatformWindow->GetPosition(), m_pDragPlatformWindow->GetSize()); - } - - StopDragWindow(); - } - } - } - - Container* WindowManager::GetBestDocking(PlatformWindow* pPlatformWindow, const ImVec2 oCursorPos, EDockOrientation& oOutOrientation, ImVec2& oOutAreaPos, ImVec2& oOutAreaSize) - { - ImVec2 oPos = pPlatformWindow->GetPosition(); - ImVec2 oSize = pPlatformWindow->GetSize(); - if (oCursorPos.x >= oPos.x && oCursorPos.x <= (oPos.x + oSize.x) && - oCursorPos.y >= oPos.y && oCursorPos.y <= (oPos.y + oSize.y)) - { - ImVec2 oRectPos(oCursorPos.x - oPos.x, oCursorPos.y - oPos.y); - - Container* pBestContainer = pPlatformWindow->GetContainer()->GetBestDocking(oRectPos, oOutOrientation, oOutAreaPos, oOutAreaSize); - if (NULL != pBestContainer) - { - return pBestContainer; - } - - //Left - if (oRectPos.x <= oSize.x * m_oConfig.m_fDragMarginRatio) - { - oOutOrientation = E_DOCK_ORIENTATION_LEFT; - oOutAreaPos = IM_VEC2_0; - oOutAreaSize = ImVec2(oSize.x * m_oConfig.m_fDragMarginSizeRatio, oSize.y); - } - //Right - else if (oRectPos.x >= oSize.x * (1.f - m_oConfig.m_fDragMarginRatio)) - { - oOutOrientation = E_DOCK_ORIENTATION_RIGHT; - oOutAreaPos = ImVec2(oSize.x * (1.f - m_oConfig.m_fDragMarginSizeRatio), 0.f); - oOutAreaSize = ImVec2(oSize.x * m_oConfig.m_fDragMarginSizeRatio, oSize.y); - } - //Top - else if (oRectPos.y <= oSize.y * m_oConfig.m_fDragMarginRatio) - { - oOutOrientation = E_DOCK_ORIENTATION_TOP; - oOutAreaPos = IM_VEC2_0; - oOutAreaSize = ImVec2(oSize.x, oSize.y * m_oConfig.m_fDragMarginSizeRatio); - } - //Bottom - else if (oRectPos.y >= oSize.y * (1.f - m_oConfig.m_fDragMarginRatio)) - { - oOutOrientation = E_DOCK_ORIENTATION_BOTTOM; - oOutAreaPos = ImVec2(0.f, oSize.y * (1.f - m_oConfig.m_fDragMarginSizeRatio)); - oOutAreaSize = ImVec2(oSize.x, oSize.y * m_oConfig.m_fDragMarginSizeRatio); - } - else - { - oOutOrientation = E_DOCK_ORIENTATION_CENTER; - oOutAreaPos = IM_VEC2_0; - oOutAreaSize = ImVec2(oSize.x, oSize.y); - //IM_ASSERT(false); //Best dock orientation not found - return NULL; - } - return pPlatformWindow->GetContainer(); - } - return NULL; - } - - void WindowManager::AddWindow(Window* pWindow) - { - m_lWindows.push_back(pWindow); - - m_lOrphanWindows.push_back(pWindow); - } - - void WindowManager::RemoveWindow(Window* pWindow) - { - m_lWindows.remove(pWindow); - m_lOrphanWindows.remove(pWindow); - } - - void WindowManager::DestroyWindow(Window* pWindow) - { - if (NULL != pWindow && std::find(m_lToDestroyWindows.begin(), m_lToDestroyWindows.end(), pWindow) == m_lToDestroyWindows.end()) - { - m_lToDestroyWindows.push_back(pWindow); - } - } - - void WindowManager::InternalDock(Window* pWindow, EDockOrientation eOrientation, PlatformWindow* pToPlatformWindow) - { - pToPlatformWindow->m_pContainer->Dock(pWindow, eOrientation); - } - - void WindowManager::InternalDockTo(Window* pWindow, EDockOrientation eOrientation, Container* pToContainer) - { - pToContainer->Dock(pWindow, eOrientation); - } - - void WindowManager::InternalDockWith(Window* pWindow, Window* pWithWindow, EDockOrientation eOrientation) - { - Container* pContainer = m_pMainPlatformWindow->HasWindow(pWithWindow); - if (NULL != pContainer) - { - pContainer->Dock(pWindow, eOrientation); - } - - for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end(); ++it) - { - pContainer = (*it)->HasWindow(pWithWindow); - if (NULL != pContainer) - { - pContainer->Dock(pWindow, eOrientation); - break; - } - } - } - - bool WindowManager::InternalFloat(Window* pWindow, ImVec2 oPosition, ImVec2 oSize) - { - PlatformWindow* pPlatformWindow = CreatePlatformWindow(false, m_pMainPlatformWindow, false); - if (NULL == pPlatformWindow) - { - return false; - } - - m_lPlatformWindows.push_back(pPlatformWindow); - - if (oSize.x == IM_VEC2_N1.x && oSize.y == IM_VEC2_N1.y) - { - oSize = pWindow->GetLastSize(); - } - - if (oPosition.x == IM_VEC2_N1.x && oPosition.y == IM_VEC2_N1.y) - { - oPosition = GetCursorPos(); - oPosition.x -= 20; - oPosition.x -= 10; - } - pPlatformWindow->Dock(pWindow); - pPlatformWindow->SetSize(oSize); - pPlatformWindow->SetPosition(oPosition); - pPlatformWindow->Show(); - - return true; - } - - void WindowManager::InternalUnDock(Window* pWindow) - { - if (m_pMainPlatformWindow->UnDock(pWindow)) - { - return; - } - - for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end(); ++it) - { - if ((*it)->UnDock(pWindow)) - { - //Destroy empty platform window if not main window - if (!(*it)->IsMain() && (*it)->GetContainer()->IsEmpty()) - { - m_lToDestroyPlatformWindows.push_back(*it); - } - return; - } - } - - m_pDragPlatformWindow->UnDock(pWindow); - } - - void WindowManager::OnClosePlatformWindow(PlatformWindow* pWindow) - { - PlatformWindowAction* pAction = IMGUI_NEW(PlatformWindowAction); - pAction->m_iFlags = E_PLATFORM_WINDOW_ACTION_DESTOY; - pAction->m_pPlatformWindow = pWindow; - m_lPlatformWindowActions.push_back(pAction); - } - - void WindowManager::DrawWindowArea(PlatformWindow* pWindow, const ImVec2& oPos, const ImVec2& oSize, const ImColor& oColor) - { - m_lDrawWindowAreas.push_back(DrawWindowAreaAction(pWindow, oPos, oSize, oColor)); - } - - // Static - WindowManager* WindowManager::GetInstance() - { - return s_pInstance; - } - -} // namespace ImWindow diff --git a/3rdparty/ocornut-imgui/imgui_wm.h b/3rdparty/ocornut-imgui/imgui_wm.h deleted file mode 100644 index e191339e1..000000000 --- a/3rdparty/ocornut-imgui/imgui_wm.h +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright 2011-2016 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause - */ - -/* - * Based on ImWindow code from: - * https://github.com/thennequin/ImWindow - * - * MIT license: - * https://github.com/thennequin/ImWindow/blob/master/LICENSE - */ - -#ifndef IMGUI_WM_H_HEADER_GUARD -#define IMGUI_WM_H_HEADER_GUARD - -#include "imgui.h" - -typedef unsigned int ImU32; - -#ifndef ImwList -# include -# define ImwList std::list -#endif // ImList - -#ifndef ImwMap -# include -# define ImwMap std::unordered_map -#endif // ImMap - -namespace ImGuiWM -{ - enum EDockOrientation - { - E_DOCK_ORIENTATION_CENTER, - E_DOCK_ORIENTATION_TOP, - E_DOCK_ORIENTATION_LEFT, - E_DOCK_ORIENTATION_RIGHT, - E_DOCK_ORIENTATION_BOTTOM, - }; - - class Id - { - public: - Id(); - ImU32 GetId() const; - const char* GetStr() const; - - private: - ImU32 m_iId; - char m_pId[11]; - static int s_iNextId; - }; - - class Window - { - friend class WindowManager; - friend class Container; - - public: - virtual void OnGui() = 0; - virtual void OnMenu() {}; - - const char* GetId() const { return m_oId.GetStr(); } - - void Destroy(); - - void SetTitle(const char* pTitle); - const char* GetTitle() const; - - const ImVec2& GetLastPosition() const; - const ImVec2& GetLastSize() const; - - protected: - Window(); - virtual ~Window(); - - char* m_pTitle; - Id m_oId; - - ImVec2 m_oLastPosition; - ImVec2 m_oLastSize; - }; - - typedef ImwList WindowList; - - class PlatformWindow; - - class Container - { - friend class PlatformWindow; - - public: - void Dock(Window* pWindow,EDockOrientation eOrientation = E_DOCK_ORIENTATION_CENTER); - bool UnDock(Window* pWindow); - - bool IsEmpty(); - bool IsSplit(); - bool HasWindowTabbed(); - Container* HasWindow(const Window* pWindow); - PlatformWindow* GetPlatformWindowParent() const; - Container* GetBestDocking(const ImVec2 oCursorPosInContainer,EDockOrientation& oOutOrientation,ImVec2& oOutAreaPos,ImVec2& oOutAreaSize); - - protected: - Container(Container* pParent); - Container(PlatformWindow* pParent); - ~Container(); - - void CreateSplits(); - void Paint(); - - Container* m_pParent; - PlatformWindow* m_pParentWindow; - WindowList m_lWindows; - Container* m_pSplits[2]; - - float m_fSplitRatio; - bool m_bVerticalSplit; - int m_iActiveWindow; - - bool m_bIsDrag; - - ImVec2 m_oLastPosition; - ImVec2 m_oLastSize; - }; - - class PlatformWindow - { - friend class WindowManager; - - public: - PlatformWindow(bool bMainWindow,bool bIsDragWindow); - virtual ~PlatformWindow(); - - virtual bool Init(PlatformWindow* pParent) = 0; - - virtual const ImVec2& GetPosition() const = 0; - virtual const ImVec2& GetSize() const = 0; - - virtual void Show() = 0; - virtual void Hide() = 0; - virtual void SetSize(const ImVec2& size) = 0; - virtual void SetPosition(const ImVec2& pos) = 0; - virtual void SetTitle(const char* pTitle) = 0; - - bool IsMain(); - - void Dock(Window* pWindow); - bool UnDock(Window* pWindow); - - Container* GetContainer(); - Container* HasWindow(Window* pWindow); - bool IsStateSet(); - - protected: - void SetState(); - void RestoreState(); - void OnLoseFocus(); - virtual void PreUpdate() = 0; - virtual void PaintBegin() = 0; - virtual void Paint(); - virtual void PaintEnd() = 0; - virtual void Destroy() = 0; - virtual void StartDrag() = 0; - virtual void StopDrag() = 0; - virtual bool IsDraging() = 0; - - void PaintContainer(); - void OnClose(); - - Id m_oId; - bool m_bMain; - bool m_bIsDragWindow; - Container* m_pContainer; - ImGuiContext* m_pState; - ImGuiContext* m_pPreviousState; - }; - - typedef ImwList PlatformWindowList; - - class WindowManager - { - friend class Window; - friend class PlatformWindow; - friend class Container; - - struct PlatformWindowAction - { - PlatformWindow* m_pPlatformWindow; - unsigned int m_iFlags; - ImVec2 m_oPosition; - ImVec2 m_oSize; - }; - - struct DockAction - { - Window* m_pWindow; - - // Is Dock or Float - bool m_bFloat; - - //For Docking - Window* m_pWith; - EDockOrientation m_eOrientation; - PlatformWindow* m_pToPlatformWindow; - Container* m_pToContainer; - - //For Floating - ImVec2 m_oPosition; - ImVec2 m_oSize; - }; - - struct DrawWindowAreaAction - { - DrawWindowAreaAction(PlatformWindow* pWindow,const ImVec2& oRectPos,const ImVec2& oRectSize,const ImColor& oColor); - PlatformWindow* m_pWindow; - ImVec2 m_oRectPos; - ImVec2 m_oRectSize; - ImColor m_oColor; - }; - - public: - struct Config - { - Config(); - float m_fDragMarginRatio; - float m_fDragMarginSizeRatio; - ImColor m_oHightlightAreaColor; - }; - - WindowManager(); - virtual ~WindowManager(); - - bool Init(); - bool Run(); - void Exit(); - - PlatformWindow* GetMainPlatformWindow(); - Config& GetConfig(); - - void SetMainTitle(const char* pTitle); - - void Dock(Window* pWindow, EDockOrientation eOrientation = E_DOCK_ORIENTATION_CENTER, PlatformWindow* pToPlatformWindow = NULL); - void DockTo(Window* pWindow, EDockOrientation eOrientation = E_DOCK_ORIENTATION_CENTER, Container* pContainer = NULL); - void DockWith(Window* pWindow, Window* pWithWindow,EDockOrientation eOrientation = E_DOCK_ORIENTATION_CENTER); - void Float(Window* pWindow, const ImVec2& oPosition = ImVec2(-1,-1), const ImVec2& oSize = ImVec2(-1,-1)); - - const WindowList& GetWindowList() const; - PlatformWindow* GetCurrentPlatformWindow(); - PlatformWindow* GetWindowParent(Window* pWindow); - - void Log(const char* pFormat, ...); - virtual void LogFormatted(const char* pStr) = 0;; - - static WindowManager* GetInstance(); - - protected: - virtual PlatformWindow* CreatePlatformWindow(bool bMain,PlatformWindow* pParent,bool bDragWindow) = 0; - virtual void InternalRun() = 0; - - void AddWindow(Window* pWindow); - void RemoveWindow(Window* pWindow); - void DestroyWindow(Window* pWindow); - - void InternalDock(Window* pWindow,EDockOrientation eOrientation,PlatformWindow* pToPlatformWindow); - void InternalDockTo(Window* pWindow,EDockOrientation eOrientation,Container* pToContainer); - void InternalDockWith(Window* pWindow,Window* pWithWindow,EDockOrientation eOrientation); - bool InternalFloat(Window* pWindow,ImVec2 oPosition,ImVec2 oSize); - void InternalUnDock(Window* pWindow); - void InternalDrag(Window* pWindow); - - void OnClosePlatformWindow(PlatformWindow* pWindow); - - void DrawWindowArea(PlatformWindow* pWindow,const ImVec2& oPos,const ImVec2& oSize,const ImColor& oColor); - - void PreUpdate(); - void Update(); - void UpdatePlatformwWindowActions(); - void UpdateDockActions(); - void UpdateOrphans(); - - void Paint(PlatformWindow* pWindow); - - void StartDragWindow(Window* pWindow); - void StopDragWindow(); - void UpdateDragWindow(); - Container* GetBestDocking(PlatformWindow* pPlatformWindow,const ImVec2 oCursorPos,EDockOrientation& oOutOrientation,ImVec2& oOutAreaPos,ImVec2& oOutAreaSize); - - Config m_oConfig; - PlatformWindow* m_pMainPlatformWindow; - PlatformWindowList m_lPlatformWindows; - PlatformWindow* m_pDragPlatformWindow; - WindowList m_lWindows; - WindowList m_lOrphanWindows; - WindowList m_lToDestroyWindows; - PlatformWindowList m_lToDestroyPlatformWindows; - ImwList m_lPlatformWindowActions; - ImwList m_lDockActions; - ImwList m_lDrawWindowAreas; - - PlatformWindow* m_pCurrentPlatformWindow; - Window* m_pDraggedWindow; - - ImVec2 m_oDragPreviewOffset; - - static WindowManager* s_pInstance; - }; -} - -#endif // IMGUI_WM_H_HEADER_GUARD diff --git a/3rdparty/ocornut-imgui/widgets/dock.h b/3rdparty/ocornut-imgui/widgets/dock.h new file mode 100644 index 000000000..7b1232817 --- /dev/null +++ b/3rdparty/ocornut-imgui/widgets/dock.h @@ -0,0 +1,21 @@ +namespace ImGui +{ + /// + IMGUI_API void InitDockContext(); + + /// + IMGUI_API void ShutdownDockContext(); + + /// + IMGUI_API void RootDock(const ImVec2& pos, const ImVec2& size); + + /// + IMGUI_API bool BeginDock(const char* label, bool* opened = NULL, ImGuiWindowFlags extra_flags = 0); + + /// + IMGUI_API void EndDock(); + + /// + IMGUI_API void SetDockActive(); + +} // namespace ImGui diff --git a/3rdparty/ocornut-imgui/widgets/dock.inl b/3rdparty/ocornut-imgui/widgets/dock.inl new file mode 100644 index 000000000..6144d790a --- /dev/null +++ b/3rdparty/ocornut-imgui/widgets/dock.inl @@ -0,0 +1,1105 @@ +// https://github.com/vassvik/imgui_docking_minimal/ +// +// This is free and unencumbered software released into the public domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. +// +// In jurisdictions that recognize copyright laws, the author or authors +// of this software dedicate any and all copyright interest in the +// software to the public domain. We make this dedication for the benefit +// of the public at large and to the detriment of our heirs and +// successors. We intend this dedication to be an overt act of +// relinquishment in perpetuity of all present and future rights to this +// software under copyright law. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// For more information, please refer to + +#include // placement new + +namespace ImGui +{ + struct DockContext + { + enum Slot_ + { + Slot_Left, + Slot_Right, + Slot_Top, + Slot_Bottom, + Slot_Tab, + + Slot_Float, + Slot_None + }; + + + enum EndAction_ + { + EndAction_None, + EndAction_Panel, + EndAction_End, + EndAction_EndChild + }; + + + enum Status_ + { + Status_Docked, + Status_Float, + Status_Dragged + }; + + + struct Dock + { + Dock() + : id(0) + , label(NULL) + , next_tab(NULL) + , prev_tab(NULL) + , parent(NULL) + , pos(0, 0) + , size(-1, -1) + , active(true) + , status(Status_Float) + , opened(false) + { + location[0] = 0; + children[0] = children[1] = NULL; + } + + + ~Dock() { MemFree(label); } + + + ImVec2 getMinSize() const + { + if (!children[0]) return ImVec2(16, 16 + GetTextLineHeightWithSpacing()); + + ImVec2 s0 = children[0]->getMinSize(); + ImVec2 s1 = children[1]->getMinSize(); + return isHorizontal() ? ImVec2(s0.x + s1.x, ImMax(s0.y, s1.y)) + : ImVec2(ImMax(s0.x, s1.x), s0.y + s1.y); + } + + + bool isHorizontal() const { return children[0]->pos.x < children[1]->pos.x; } + + + void setParent(Dock* dock) + { + parent = dock; + for (Dock* tmp = prev_tab; tmp; tmp = tmp->prev_tab) tmp->parent = dock; + for (Dock* tmp = next_tab; tmp; tmp = tmp->next_tab) tmp->parent = dock; + } + + + Dock& getSibling() + { + IM_ASSERT(parent); + if (parent->children[0] == &getFirstTab()) return *parent->children[1]; + return *parent->children[0]; + } + + + Dock& getFirstTab() + { + Dock* tmp = this; + while (tmp->prev_tab) tmp = tmp->prev_tab; + return *tmp; + } + + + void setActive() + { + active = true; + for (Dock* tmp = prev_tab; tmp; tmp = tmp->prev_tab) tmp->active = false; + for (Dock* tmp = next_tab; tmp; tmp = tmp->next_tab) tmp->active = false; + } + + + bool isContainer() const { return children[0] != NULL; } + + + void setChildrenPosSize(const ImVec2& _pos, const ImVec2& _size) + { + ImVec2 s = children[0]->size; + if (isHorizontal()) + { + s.y = _size.y; + s.x = (float)int( + _size.x * children[0]->size.x / (children[0]->size.x + children[1]->size.x)); + if (s.x < children[0]->getMinSize().x) + { + s.x = children[0]->getMinSize().x; + } + else if (_size.x - s.x < children[1]->getMinSize().x) + { + s.x = _size.x - children[1]->getMinSize().x; + } + children[0]->setPosSize(_pos, s); + + s.x = _size.x - children[0]->size.x; + ImVec2 p = _pos; + p.x += children[0]->size.x; + children[1]->setPosSize(p, s); + } + else + { + s.x = _size.x; + s.y = (float)int( + _size.y * children[0]->size.y / (children[0]->size.y + children[1]->size.y)); + if (s.y < children[0]->getMinSize().y) + { + s.y = children[0]->getMinSize().y; + } + else if (_size.y - s.y < children[1]->getMinSize().y) + { + s.y = _size.y - children[1]->getMinSize().y; + } + children[0]->setPosSize(_pos, s); + + s.y = _size.y - children[0]->size.y; + ImVec2 p = _pos; + p.y += children[0]->size.y; + children[1]->setPosSize(p, s); + } + } + + void setPosSize(const ImVec2& _pos, const ImVec2& _size) + { + size = _size; + pos = _pos; + for (Dock* tmp = prev_tab; tmp; tmp = tmp->prev_tab) + { + tmp->size = _size; + tmp->pos = _pos; + } + for (Dock* tmp = next_tab; tmp; tmp = tmp->next_tab) + { + tmp->size = _size; + tmp->pos = _pos; + } + + if (!isContainer()) return; + setChildrenPosSize(_pos, _size); + } + + + ImU32 id; + char* label; + Dock* next_tab; + Dock* prev_tab; + Dock* parent; + ImVec2 pos; + ImVec2 size; + bool active; + Status_ status; + bool opened; + + Dock* children[2]; + char location[16]; + int last_frame; + int invalid_frames; + bool first; + }; + + + ImVector m_docks; + ImVec2 m_drag_offset; + Dock* m_current = NULL; + int m_last_frame = 0; + EndAction_ m_end_action; + + + ~DockContext() {} + + + Dock& getDock(const char* label, bool opened) + { + ImU32 id = ImHash(label, 0); + for (int i = 0; i < m_docks.size(); ++i) + { + if (m_docks[i]->id == id) return *m_docks[i]; + } + + Dock* new_dock = (Dock*)MemAlloc(sizeof(Dock)); + IM_PLACEMENT_NEW(new_dock) Dock(); + m_docks.push_back(new_dock); + new_dock->label = ImStrdup(label); + IM_ASSERT(new_dock->label); + new_dock->id = id; + new_dock->setActive(); + new_dock->status = Status_Float; + new_dock->pos = ImVec2(0, 0); + new_dock->size = GetIO().DisplaySize; + new_dock->opened = opened; + new_dock->first = true; + new_dock->last_frame = 0; + new_dock->invalid_frames = 0; + new_dock->location[0] = 0; + return *new_dock; + } + + + void putInBackground() + { + ImGuiWindow* win = GetCurrentWindow(); + ImGuiContext& g = *GImGui; + if (g.Windows[0] == win) return; + + for (int i = 0; i < g.Windows.Size; i++) + { + if (g.Windows[i] == win) + { + for (int j = i - 1; j >= 0; --j) + { + g.Windows[j + 1] = g.Windows[j]; + } + g.Windows[0] = win; + break; + } + } + } + + + void splits() + { + if (GetFrameCount() == m_last_frame) + { + return; + } + + m_last_frame = GetFrameCount(); + + putInBackground(); + + ImU32 color = GetColorU32(ImGuiCol_Button); + ImU32 color_hovered = GetColorU32(ImGuiCol_ButtonHovered); + ImDrawList* draw_list = GetWindowDrawList(); + ImGuiIO& io = GetIO(); + for (int i = 0; i < m_docks.size(); ++i) + { + Dock& dock = *m_docks[i]; + if (!dock.isContainer()) + { + continue; + } + + PushID(i); + if (!IsMouseDown(0)) + { + dock.status = Status_Docked; + } + + ImVec2 dsize(0, 0); + SetCursorScreenPos(dock.children[1]->pos); + ImVec2 min_size0 = dock.children[0]->getMinSize(); + ImVec2 min_size1 = dock.children[1]->getMinSize(); + if (dock.isHorizontal()) + { + InvisibleButton("split", ImVec2(3, dock.size.y)); + if (dock.status == Status_Dragged) dsize.x = io.MouseDelta.x; + dsize.x = -ImMin(-dsize.x, dock.children[0]->size.x - min_size0.x); + dsize.x = ImMin(dsize.x, dock.children[1]->size.x - min_size1.x); + } + else + { + InvisibleButton("split", ImVec2(dock.size.x, 3)); + if (dock.status == Status_Dragged) dsize.y = io.MouseDelta.y; + dsize.y = -ImMin(-dsize.y, dock.children[0]->size.y - min_size0.y); + dsize.y = ImMin(dsize.y, dock.children[1]->size.y - min_size1.y); + } + ImVec2 new_size0 = dock.children[0]->size + dsize; + ImVec2 new_size1 = dock.children[1]->size - dsize; + ImVec2 new_pos1 = dock.children[1]->pos + dsize; + dock.children[0]->setPosSize(dock.children[0]->pos, new_size0); + dock.children[1]->setPosSize(new_pos1, new_size1); + + if (IsItemHovered() && IsMouseClicked(0)) + { + dock.status = Status_Dragged; + } + + draw_list->AddRectFilled( + GetItemRectMin(), GetItemRectMax(), IsItemHovered() ? color_hovered : color); + PopID(); + } + } + + + void checkNonexistent() + { + int frame_limit = ImMax(0, ImGui::GetFrameCount() - 2); + for (Dock* dock : m_docks) + { + if (dock->isContainer()) continue; + if (dock->status == Status_Float) continue; + if (dock->last_frame < frame_limit) + { + ++dock->invalid_frames; + if (dock->invalid_frames > 2) + { + doUndock(*dock); + dock->status = Status_Float; + } + return; + } + dock->invalid_frames = 0; + } + } + + + void beginPanel() + { + ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | + ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_ShowBorders | + ImGuiWindowFlags_NoBringToFrontOnFocus; + Dock* root = getRootDock(); + if (root) + { + SetNextWindowPos(root->pos); + SetNextWindowSize(root->size); + } + else + { + SetNextWindowPos(ImVec2(0, 0)); + SetNextWindowSize(GetIO().DisplaySize); + } + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0); + Begin("###DockPanel", NULL, flags); + splits(); + + checkNonexistent(); + } + + + void endPanel() + { + End(); + ImGui::PopStyleVar(); + } + + // Doesn't use input?? + Dock* getDockAt(const ImVec2& /*pos*/) const + { + for (int i = 0; i < m_docks.size(); ++i) + { + Dock& dock = *m_docks[i]; + if (dock.isContainer()) continue; + if (dock.status != Status_Docked) continue; + if (IsMouseHoveringRect(dock.pos, dock.pos + dock.size, false)) + { + return &dock; + } + } + + return NULL; + } + + + static ImRect getDockedRect(const ImRect& rect, Slot_ dock_slot) + { + ImVec2 half_size = rect.GetSize() * 0.5f; + switch (dock_slot) + { + default: return rect; + case Slot_Top: return ImRect(rect.Min, rect.Min + ImVec2(rect.Max.x, half_size.y)); + case Slot_Right: return ImRect(rect.Min + ImVec2(half_size.x, 0), rect.Max); + case Slot_Bottom: return ImRect(rect.Min + ImVec2(0, half_size.y), rect.Max); + case Slot_Left: return ImRect(rect.Min, rect.Min + ImVec2(half_size.x, rect.Max.y)); + } + } + + + static ImRect getSlotRect(ImRect parent_rect, Slot_ dock_slot) + { + ImVec2 size = parent_rect.Max - parent_rect.Min; + ImVec2 center = parent_rect.Min + size * 0.5f; + switch (dock_slot) + { + default: return ImRect(center - ImVec2(20, 20), center + ImVec2(20, 20)); + case Slot_Top: return ImRect(center + ImVec2(-20, -50), center + ImVec2(20, -30)); + case Slot_Right: return ImRect(center + ImVec2(30, -20), center + ImVec2(50, 20)); + case Slot_Bottom: return ImRect(center + ImVec2(-20, +30), center + ImVec2(20, 50)); + case Slot_Left: return ImRect(center + ImVec2(-50, -20), center + ImVec2(-30, 20)); + } + } + + + static ImRect getSlotRectOnBorder(ImRect parent_rect, Slot_ dock_slot) + { + ImVec2 size = parent_rect.Max - parent_rect.Min; + ImVec2 center = parent_rect.Min + size * 0.5f; + switch (dock_slot) + { + case Slot_Top: + return ImRect(ImVec2(center.x - 20, parent_rect.Min.y + 10), + ImVec2(center.x + 20, parent_rect.Min.y + 30)); + case Slot_Left: + return ImRect(ImVec2(parent_rect.Min.x + 10, center.y - 20), + ImVec2(parent_rect.Min.x + 30, center.y + 20)); + case Slot_Bottom: + return ImRect(ImVec2(center.x - 20, parent_rect.Max.y - 30), + ImVec2(center.x + 20, parent_rect.Max.y - 10)); + case Slot_Right: + return ImRect(ImVec2(parent_rect.Max.x - 30, center.y - 20), + ImVec2(parent_rect.Max.x - 10, center.y + 20)); + default: IM_ASSERT(false); + } + IM_ASSERT(false); + return ImRect(); + } + + + Dock* getRootDock() + { + for (int i = 0; i < m_docks.size(); ++i) + { + if (!m_docks[i]->parent && + (m_docks[i]->status == Status_Docked || m_docks[i]->children[0])) + { + return m_docks[i]; + } + } + return NULL; + } + + + bool dockSlots(Dock& dock, Dock* dest_dock, const ImRect& rect, bool on_border) + { + ImDrawList* canvas = GetWindowDrawList(); + ImU32 color = GetColorU32(ImGuiCol_Button); + ImU32 color_hovered = GetColorU32(ImGuiCol_ButtonHovered); + ImVec2 mouse_pos = GetIO().MousePos; + for (int i = 0; i < (on_border ? 4 : 5); ++i) + { + ImRect r = + on_border ? getSlotRectOnBorder(rect, (Slot_)i) : getSlotRect(rect, (Slot_)i); + bool hovered = r.Contains(mouse_pos); + + canvas->AddRectFilled(r.Min, r.Max, hovered ? color_hovered : color); + if (!hovered) continue; + + if (!IsMouseDown(0)) + { + doDock(dock, dest_dock ? dest_dock : getRootDock(), (Slot_)i); + return true; + } + ImRect docked_rect = getDockedRect(rect, (Slot_)i); + canvas->AddRectFilled(docked_rect.Min, docked_rect.Max, GetColorU32(ImGuiCol_Button)); + } + return false; + } + + + void handleDrag(Dock& dock) + { + Dock* dest_dock = getDockAt(GetIO().MousePos); + + Begin("##Overlay", + NULL, + ImVec2(0, 0), + 0.f, + ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | + ImGuiWindowFlags_AlwaysAutoResize); + ImDrawList* canvas = GetWindowDrawList(); + + canvas->PushClipRectFullScreen(); + + ImU32 docked_color = GetColorU32(ImGuiCol_FrameBg); + docked_color = (docked_color & 0x00ffFFFF) | 0x80000000; + dock.pos = GetIO().MousePos - m_drag_offset; + if (dest_dock) + { + if (dockSlots(dock, + dest_dock, + ImRect(dest_dock->pos, dest_dock->pos + dest_dock->size), + false)) + { + canvas->PopClipRect(); + End(); + return; + } + } + if (dockSlots(dock, NULL, ImRect(ImVec2(0, 0), GetIO().DisplaySize), true)) + { + canvas->PopClipRect(); + End(); + return; + } + canvas->AddRectFilled(dock.pos, dock.pos + dock.size, docked_color); + canvas->PopClipRect(); + + if (!IsMouseDown(0)) + { + dock.status = Status_Float; + dock.location[0] = 0; + dock.setActive(); + } + + End(); + } + + + void fillLocation(Dock& dock) + { + if (dock.status == Status_Float) return; + char* c = dock.location; + Dock* tmp = &dock; + while (tmp->parent) + { + *c = getLocationCode(tmp); + tmp = tmp->parent; + ++c; + } + *c = 0; + } + + + void doUndock(Dock& dock) + { + if (dock.prev_tab) + dock.prev_tab->setActive(); + else if (dock.next_tab) + dock.next_tab->setActive(); + else + dock.active = false; + Dock* container = dock.parent; + + if (container) + { + Dock& sibling = dock.getSibling(); + if (container->children[0] == &dock) + { + container->children[0] = dock.next_tab; + } + else if (container->children[1] == &dock) + { + container->children[1] = dock.next_tab; + } + + bool remove_container = !container->children[0] || !container->children[1]; + if (remove_container) + { + if (container->parent) + { + Dock*& child = container->parent->children[0] == container + ? container->parent->children[0] + : container->parent->children[1]; + child = &sibling; + child->setPosSize(container->pos, container->size); + child->setParent(container->parent); + } + else + { + if (container->children[0]) + { + container->children[0]->setParent(NULL); + container->children[0]->setPosSize(container->pos, container->size); + } + if (container->children[1]) + { + container->children[1]->setParent(NULL); + container->children[1]->setPosSize(container->pos, container->size); + } + } + for (int i = 0; i < m_docks.size(); ++i) + { + if (m_docks[i] == container) + { + m_docks.erase(m_docks.begin() + i); + break; + } + } + container->~Dock(); + MemFree(container); + } + } + if (dock.prev_tab) dock.prev_tab->next_tab = dock.next_tab; + if (dock.next_tab) dock.next_tab->prev_tab = dock.prev_tab; + dock.parent = NULL; + dock.prev_tab = dock.next_tab = NULL; + } + + + void drawTabbarListButton(Dock& dock) + { + if (!dock.next_tab) return; + + ImDrawList* draw_list = GetWindowDrawList(); + if (InvisibleButton("list", ImVec2(16, 16))) + { + OpenPopup("tab_list_popup"); + } + if (BeginPopup("tab_list_popup")) + { + Dock* tmp = &dock; + while (tmp) + { + bool dummy = false; + if (Selectable(tmp->label, &dummy)) + { + tmp->setActive(); + } + tmp = tmp->next_tab; + } + EndPopup(); + } + + bool hovered = IsItemHovered(); + ImVec2 min = GetItemRectMin(); + ImVec2 max = GetItemRectMax(); + ImVec2 center = (min + max) * 0.5f; + ImU32 text_color = GetColorU32(ImGuiCol_Text); + ImU32 color_active = GetColorU32(ImGuiCol_FrameBgActive); + draw_list->AddRectFilled(ImVec2(center.x - 4, min.y + 3), + ImVec2(center.x + 4, min.y + 5), + hovered ? color_active : text_color); + draw_list->AddTriangleFilled(ImVec2(center.x - 4, min.y + 7), + ImVec2(center.x + 4, min.y + 7), + ImVec2(center.x, min.y + 12), + hovered ? color_active : text_color); + } + + + bool tabbar(Dock& dock, bool close_button) + { + float tabbar_height = 2 * GetTextLineHeightWithSpacing(); + ImVec2 size0(dock.size.x, tabbar_height); + bool tab_closed = false; + + SetCursorScreenPos(dock.pos); + char tmp[20]; + ImFormatString(tmp, IM_ARRAYSIZE(tmp), "tabs%d", (int)dock.id); + if (BeginChild(tmp, size0, true)) + { + Dock* dock_tab = &dock; + + ImDrawList* draw_list = GetWindowDrawList(); + ImU32 color = GetColorU32(ImGuiCol_FrameBg); + ImU32 color_active = GetColorU32(ImGuiCol_FrameBgActive); + ImU32 color_hovered = GetColorU32(ImGuiCol_FrameBgHovered); + ImU32 text_color = GetColorU32(ImGuiCol_Text); + ImU32 text_color_disabled = GetColorU32(ImGuiCol_TextDisabled); + float line_height = GetTextLineHeightWithSpacing(); + float tab_base; + + drawTabbarListButton(dock); + + while (dock_tab) + { + SameLine(0, 15); + + const char* text_end = FindRenderedTextEnd(dock_tab->label); + ImVec2 size1(CalcTextSize(dock_tab->label, text_end).x, line_height); + if (InvisibleButton(dock_tab->label, size1)) + { + dock_tab->setActive(); + } + + if (IsItemActive() && IsMouseDragging()) + { + m_drag_offset = GetMousePos() - dock_tab->pos; + doUndock(*dock_tab); + dock_tab->status = Status_Dragged; + } + + bool hovered = IsItemHovered(); + ImVec2 pos = GetItemRectMin(); + size1.x += 20 + GetStyle().ItemSpacing.x; + + tab_base = pos.y; + + draw_list->AddRectFilled(pos+ImVec2(-8.0f, 0.0), + pos+size1, + hovered ? color_hovered : (dock_tab->active ? color_active : color)); + draw_list->AddText(pos, text_color, dock_tab->label, text_end); + + if (dock_tab->active && close_button) + { + SameLine(); + tab_closed = InvisibleButton("close", ImVec2(16, 16)); + + ImVec2 center = ((GetItemRectMin() + GetItemRectMax()) * 0.5f); + draw_list->AddLine( center + ImVec2(-3.5f, -3.5f), center + ImVec2(3.5f, 3.5f), text_color); + draw_list->AddLine( center + ImVec2(3.5f, -3.5f), center + ImVec2(-3.5f, 3.5f), text_color); + } else { + if(!dock_tab->active && close_button) { + SameLine(); + InvisibleButton("close", ImVec2(16, 16)); + + ImVec2 center = ((GetItemRectMin() + GetItemRectMax()) * 0.5f); + draw_list->AddLine( center + ImVec2(-3.5f, -3.5f), center + ImVec2(3.5f, 3.5f), text_color_disabled); + draw_list->AddLine( center + ImVec2(3.5f, -3.5f), center + ImVec2(-3.5f, 3.5f), text_color_disabled); + } + } + + dock_tab = dock_tab->next_tab; + } + ImVec2 cp(dock.pos.x, tab_base + line_height); + draw_list->AddLine(cp, cp + ImVec2(dock.size.x, 0), color); + } + EndChild(); + return tab_closed; + } + + + static void setDockPosSize(Dock& dest, Dock& dock, Slot_ dock_slot, Dock& container) + { + IM_ASSERT(!dock.prev_tab && !dock.next_tab && !dock.children[0] && !dock.children[1]); + + dest.pos = container.pos; + dest.size = container.size; + dock.pos = container.pos; + dock.size = container.size; + + switch (dock_slot) + { + case Slot_Bottom: + dest.size.y *= 0.5f; + dock.size.y *= 0.5f; + dock.pos.y += dest.size.y; + break; + case Slot_Right: + dest.size.x *= 0.5f; + dock.size.x *= 0.5f; + dock.pos.x += dest.size.x; + break; + case Slot_Left: + dest.size.x *= 0.5f; + dock.size.x *= 0.5f; + dest.pos.x += dock.size.x; + break; + case Slot_Top: + dest.size.y *= 0.5f; + dock.size.y *= 0.5f; + dest.pos.y += dock.size.y; + break; + default: IM_ASSERT(false); break; + } + dest.setPosSize(dest.pos, dest.size); + + if (container.children[1]->pos.x < container.children[0]->pos.x || + container.children[1]->pos.y < container.children[0]->pos.y) + { + Dock* tmp = container.children[0]; + container.children[0] = container.children[1]; + container.children[1] = tmp; + } + } + + + void doDock(Dock& dock, Dock* dest, Slot_ dock_slot) + { + IM_ASSERT(!dock.parent); + if (!dest) + { + dock.status = Status_Docked; + dock.setPosSize(ImVec2(0, 0), GetIO().DisplaySize); + } + else if (dock_slot == Slot_Tab) + { + Dock* tmp = dest; + while (tmp->next_tab) + { + tmp = tmp->next_tab; + } + + tmp->next_tab = &dock; + dock.prev_tab = tmp; + dock.size = tmp->size; + dock.pos = tmp->pos; + dock.parent = dest->parent; + dock.status = Status_Docked; + } + else if (dock_slot == Slot_None) + { + dock.status = Status_Float; + } + else + { + Dock* container = (Dock*)MemAlloc(sizeof(Dock)); + IM_PLACEMENT_NEW(container) Dock(); + m_docks.push_back(container); + container->children[0] = &dest->getFirstTab(); + container->children[1] = &dock; + container->next_tab = NULL; + container->prev_tab = NULL; + container->parent = dest->parent; + container->size = dest->size; + container->pos = dest->pos; + container->status = Status_Docked; + container->label = ImStrdup(""); + + if (!dest->parent) + { + } + else if (&dest->getFirstTab() == dest->parent->children[0]) + { + dest->parent->children[0] = container; + } + else + { + dest->parent->children[1] = container; + } + + dest->setParent(container); + dock.parent = container; + dock.status = Status_Docked; + + setDockPosSize(*dest, dock, dock_slot, *container); + } + dock.setActive(); + } + + + void rootDock(const ImVec2& pos, const ImVec2& size) + { + Dock* root = getRootDock(); + if (!root) return; + + ImVec2 min_size = root->getMinSize(); + ImVec2 requested_size = size; + root->setPosSize(pos, ImMax(min_size, requested_size)); + } + + + void setDockActive() + { + IM_ASSERT(m_current); + if (m_current) m_current->setActive(); + } + + + static Slot_ getSlotFromLocationCode(char code) + { + switch (code) + { + case '1': return Slot_Left; + case '2': return Slot_Top; + case '3': return Slot_Bottom; + default: return Slot_Right; + } + } + + + static char getLocationCode(Dock* dock) + { + if (!dock) return '0'; + + if (dock->parent->isHorizontal()) + { + if (dock->pos.x < dock->parent->children[0]->pos.x) return '1'; + if (dock->pos.x < dock->parent->children[1]->pos.x) return '1'; + return '0'; + } + else + { + if (dock->pos.y < dock->parent->children[0]->pos.y) return '2'; + if (dock->pos.y < dock->parent->children[1]->pos.y) return '2'; + return '3'; + } + } + + + void tryDockToStoredLocation(Dock& dock) + { + if (dock.status == Status_Docked) return; + if (dock.location[0] == 0) return; + + Dock* tmp = getRootDock(); + if (!tmp) return; + + Dock* prev = NULL; + char* c = dock.location + strlen(dock.location) - 1; + while (c >= dock.location && tmp) + { + prev = tmp; + tmp = *c == getLocationCode(tmp->children[0]) ? tmp->children[0] : tmp->children[1]; + if(tmp) --c; + } + if (tmp && tmp->children[0]) tmp = tmp->parent; + doDock(dock, tmp ? tmp : prev, tmp && !tmp->children[0] ? Slot_Tab : getSlotFromLocationCode(*c)); + } + + + bool begin(const char* label, bool* opened, ImGuiWindowFlags extra_flags) + { + Dock& dock = getDock(label, !opened || *opened); + if (!dock.opened && (!opened || *opened)) tryDockToStoredLocation(dock); + dock.last_frame = ImGui::GetFrameCount(); + if (strcmp(dock.label, label) != 0) + { + MemFree(dock.label); + dock.label = ImStrdup(label); + } + + m_end_action = EndAction_None; + + if (dock.first && opened) *opened = dock.opened; + dock.first = false; + if (opened && !*opened) + { + if (dock.status != Status_Float) + { + fillLocation(dock); + doUndock(dock); + dock.status = Status_Float; + } + dock.opened = false; + return false; + } + dock.opened = true; + + m_end_action = EndAction_Panel; + beginPanel(); + + m_current = &dock; + if (dock.status == Status_Dragged) handleDrag(dock); + + bool is_float = dock.status == Status_Float; + + if (is_float) + { + SetNextWindowPos(dock.pos); + SetNextWindowSize(dock.size); + bool ret = Begin(label, + opened, + dock.size, + -1.0f, + ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_ShowBorders | extra_flags); + m_end_action = EndAction_End; + dock.pos = GetWindowPos(); + dock.size = GetWindowSize(); + + ImGuiContext& g = *GImGui; + + if (g.ActiveId == GetCurrentWindow()->MoveId && g.IO.MouseDown[0]) + { + m_drag_offset = GetMousePos() - dock.pos; + doUndock(dock); + dock.status = Status_Dragged; + } + return ret; + } + + if (!dock.active && dock.status != Status_Dragged) return false; + + m_end_action = EndAction_EndChild; + + PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); + PushStyleColor(ImGuiCol_BorderShadow, ImVec4(0, 0, 0, 0)); + float tabbar_height = GetTextLineHeightWithSpacing(); + if (tabbar(dock.getFirstTab(), opened != NULL)) + { + fillLocation(dock); + *opened = false; + } + ImVec2 pos = dock.pos; + ImVec2 size = dock.size; + pos.y += tabbar_height + GetStyle().WindowPadding.y; + size.y -= tabbar_height + GetStyle().WindowPadding.y; + + SetCursorScreenPos(pos); + ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | + ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoBringToFrontOnFocus | + extra_flags; + char tmp[256]; + strcpy(tmp, label); + strcat(tmp, "_docked"); // to avoid https://github.com/ocornut/imgui/issues/713 + bool ret = BeginChild(tmp, size, true, flags); + PopStyleColor(); + PopStyleColor(); + return ret; + } + + + void end() + { + if (m_end_action == EndAction_End) + { + End(); + } + else if (m_end_action == EndAction_EndChild) + { + PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); + PushStyleColor(ImGuiCol_BorderShadow, ImVec4(0, 0, 0, 0)); + EndChild(); + PopStyleColor(); + PopStyleColor(); + } + m_current = NULL; + if (m_end_action > EndAction_None) endPanel(); + } + + int getDockIndex(Dock* dock) + { + if (!dock) return -1; + + for (int i = 0; i < m_docks.size(); ++i) + { + if (dock == m_docks[i]) return i; + } + + IM_ASSERT(false); + return -1; + } + + Dock* getDockByIndex(int idx) + { + return idx < 0 ? NULL : m_docks[(int)idx]; + } + }; + + static DockContext* s_dock = NULL; + + IMGUI_API void InitDockContext() + { + void* ptr = ImGui::MemAlloc(sizeof(DockContext) ); + s_dock = new(ptr) DockContext; + } + + IMGUI_API void ShutdownDockContext() + { + s_dock->~DockContext(); + ImGui::MemFree(s_dock); + s_dock = NULL; + } + + IMGUI_API void RootDock(const ImVec2& pos, const ImVec2& size) + { + s_dock->rootDock(pos, size); + } + + IMGUI_API bool BeginDock(const char* label, bool* opened, ImGuiWindowFlags extra_flags) + { + return s_dock->begin(label, opened, extra_flags); + } + + IMGUI_API void EndDock() + { + s_dock->end(); + } + + IMGUI_API void SetDockActive() + { + s_dock->setDockActive(); + } + +} // namespace ImGui diff --git a/examples/common/imgui/imgui.h b/examples/common/imgui/imgui.h index 3b0fc54f8..d6602d135 100644 --- a/examples/common/imgui/imgui.h +++ b/examples/common/imgui/imgui.h @@ -28,7 +28,6 @@ #include #include -#include #include #include diff --git a/examples/common/imgui/ocornut_imgui.cpp b/examples/common/imgui/ocornut_imgui.cpp index f95ab4ef7..0fee4cdbc 100644 --- a/examples/common/imgui/ocornut_imgui.cpp +++ b/examples/common/imgui/ocornut_imgui.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include "imgui.h" #include "ocornut_imgui.h" @@ -50,181 +49,6 @@ static FontRangeMerge s_fontRangeMerge[] = { s_iconsFontAwesomeTtf, sizeof(s_iconsFontAwesomeTtf), { ICON_MIN_FA, ICON_MAX_FA, 0 } }, }; -class PlatformWindow : public ImGuiWM::PlatformWindow -{ - typedef ImGuiWM::PlatformWindow Super; - -public: - PlatformWindow(bool _mainWindow, bool _isDragWindow) - : ImGuiWM::PlatformWindow(_mainWindow, _isDragWindow) - , m_pos(0.0f, 0.0f) - , m_size(0.0f, 0.0f) - , m_drag(false) - { -#if USE_ENTRY - if (!_mainWindow - && !_isDragWindow) - { - m_window = entry::createWindow(0, 0, 640, 380); - extern void pwToWindow(entry::WindowHandle _handle, class PlatformWindow* _pw); - pwToWindow(m_window, this); - } - else - { - m_window.idx = 0; - } -#endif // USE_ENTRY - } - - virtual ~PlatformWindow() - { -#if USE_ENTRY - if (0 != m_window.idx) - { - entry::destroyWindow(m_window); - } -#endif // USE_ENTRY - } - - virtual bool Init(ImGuiWM::PlatformWindow* /*_parent*/) BX_OVERRIDE - { - return true; - } - - virtual const ImVec2& GetPosition() const BX_OVERRIDE - { - return m_pos; - } - - virtual const ImVec2& GetSize() const BX_OVERRIDE - { - return m_size; - } - - virtual void Show() BX_OVERRIDE - { - } - - virtual void Hide() BX_OVERRIDE - { - } - - virtual void SetSize(const ImVec2& _size) BX_OVERRIDE - { -#if USE_ENTRY - if (0 != m_window.idx - && m_size.x != _size.x - && m_size.y != _size.y) - { - entry::setWindowSize(m_window, int32_t(_size.x), int32_t(_size.y) ); - } -#endif // USE_ENTRY - - m_size = _size; - } - - virtual void SetPosition(const ImVec2& _pos) BX_OVERRIDE - { -#if USE_ENTRY - if (0 != m_window.idx - && m_pos.x != _pos.x - && m_pos.y != _pos.y) - { - entry::setWindowPos(m_window, int32_t(_pos.x), int32_t(_pos.y) ); - } -#endif // USE_ENTRY - - m_pos = _pos; - } - - virtual void SetTitle(const char* _title) BX_OVERRIDE - { -#if USE_ENTRY - entry::setWindowTitle(m_window, _title); -#else - BX_UNUSED(_title); -#endif // USE_ENTRY - } - - virtual void PreUpdate() BX_OVERRIDE - { - } - - virtual void PaintBegin() BX_OVERRIDE; - virtual void Paint() BX_OVERRIDE; - virtual void PaintEnd() BX_OVERRIDE; - - virtual void Destroy() BX_OVERRIDE - { - } - - virtual void StartDrag() BX_OVERRIDE - { - m_drag = true; - } - - virtual void StopDrag() BX_OVERRIDE - { - m_drag = false; - } - - virtual bool IsDraging() BX_OVERRIDE - { - return m_drag; - } - -private: - ImVec2 m_pos; - ImVec2 m_size; - bool m_drag; - -#if USE_ENTRY - entry::WindowHandle m_window; -#endif // USE_ENTRY -}; - -class WindowManager : public ImGuiWM::WindowManager -{ - typedef ImGuiWM::WindowManager Super; - -public: - WindowManager() - { - } - - virtual ~WindowManager() - { - } - -protected: - virtual ImGuiWM::PlatformWindow* CreatePlatformWindow(bool _main, ImGuiWM::PlatformWindow* _parent, bool _isDragWindow) BX_OVERRIDE - { -#if USE_ENTRY -#else - if (!_main - && !_isDragWindow) - { - return NULL; - } -#endif // USE_ENTRY - - PlatformWindow* window = new (ImGui::MemAlloc(sizeof(PlatformWindow) ) ) PlatformWindow(_main, _isDragWindow); - window->Init(_parent); - return static_cast(window); - } - - virtual void LogFormatted(const char* _str) BX_OVERRIDE - { - BX_TRACE("%s", _str); BX_UNUSED(_str); - } - - virtual void InternalRun() BX_OVERRIDE - { - PreUpdate(); - Update(); - } -}; - struct OcornutImguiContext { static void* memAlloc(size_t _size); @@ -483,60 +307,12 @@ struct OcornutImguiContext , bgfx::copy(data, width*height*4) ); - m_wm = BX_NEW(m_allocator, WindowManager); - m_wm->Init(); - -#if 0 - { - class Window : public ImGuiWM::Window - { - public: - Window(const char* _title) - : ImGuiWM::Window() - { - SetTitle(_title); - } - - virtual void OnGui() BX_OVERRIDE - { - } - }; - - class WindowX : public ImGuiWM::Window - { - public: - WindowX(const char* _title) - : ImGuiWM::Window() - { - SetTitle(_title); - } - - virtual void OnGui() BX_OVERRIDE - { -#if defined(SCI_NAMESPACE) && 0 - bool opened = true; - ImGuiScintilla("Scintilla Editor", &opened, ImVec2(640.0f, 480.0f) ); -#endif // 0 - } - }; - - Window* w0 = new Window("test"); - WindowX* w1 = new WindowX("Scintilla"); - Window* w2 = new Window("xyzw"); - Window* w3 = new Window("0123"); - - m_wm->Dock(w0); - m_wm->DockWith(w1, w0, ImGuiWM::E_DOCK_ORIENTATION_RIGHT); - m_wm->DockWith(w2, w1, ImGuiWM::E_DOCK_ORIENTATION_BOTTOM); - m_wm->DockWith(w3, w0, ImGuiWM::E_DOCK_ORIENTATION_BOTTOM); - } -#endif // 0 + ImGui::InitDockContext(); } void destroy() { - m_wm->Exit(); - BX_DELETE(m_allocator, m_wm); + ImGui::ShutdownDockContext(); ImGui::Shutdown(); bgfx::destroyUniform(s_tex); @@ -656,36 +432,10 @@ struct OcornutImguiContext ImGui::NewFrame(); ImGuizmo::BeginFrame(); ImGui::PushStyleVar(ImGuiStyleVar_ViewId, (float)_viewId); - -#if 0 - ImGui::ShowTestWindow(); //Debug only. -#endif // 0 - -#if 0 - { - static ImGui::MemoryEditor me; - bool open = true; - if (ImGui::Begin("HexII", &open)) - { - me.Draw(s_iconsKenneyTtf, sizeof(s_iconsKenneyTtf) ); - - ImGui::End(); - } - } -#endif // 0 - -#if 0 - { - extern void ShowExampleAppCustomNodeGraph(bool* opened); - bool opened = true; - ShowExampleAppCustomNodeGraph(&opened); - } -#endif // 0 } void endFrame() { - m_wm->Run(); ImGui::PopStyleVar(1); ImGui::Render(); } @@ -696,114 +446,13 @@ struct OcornutImguiContext bgfx::TextureHandle m_texture; bgfx::UniformHandle s_tex; ImFont* m_font[ImGui::Font::Count]; - WindowManager* m_wm; int64_t m_last; int32_t m_lastScroll; uint8_t m_viewId; - -#if USE_ENTRY - struct Window - { - Window() - { - m_fbh.idx = bgfx::invalidHandle; - } - - entry::WindowState m_state; - PlatformWindow* m_pw; - bgfx::FrameBufferHandle m_fbh; - uint8_t m_viewId; - }; - - Window m_window[16]; -#endif // USE_ENTRY }; static OcornutImguiContext s_ctx; -void PlatformWindow::PaintBegin() -{ -#if USE_ENTRY - if (!m_bIsDragWindow) - { - OcornutImguiContext::Window& win = s_ctx.m_window[m_window.idx]; - entry::WindowState& state = win.m_state; - ImGuiIO& io = ImGui::GetIO(); - io.MousePos = ImVec2((float)state.m_mouse.m_mx, (float)state.m_mouse.m_my); - io.MouseDown[0] = !!state.m_mouse.m_buttons[entry::MouseButton::Left]; - io.MouseDown[1] = !!state.m_mouse.m_buttons[entry::MouseButton::Right]; - io.MouseDown[2] = !!state.m_mouse.m_buttons[entry::MouseButton::Middle]; - io.MouseWheel = float(state.m_mouse.m_mz); - - ImGui::PushStyleVar(ImGuiStyleVar_ViewId, (float)win.m_viewId); - } -#endif // USE_ENTRY -} - -void PlatformWindow::Paint() -{ - if (!m_bIsDragWindow) - { - Super::Paint(); - } -} - -void PlatformWindow::PaintEnd() -{ -#if USE_ENTRY - if (!m_bIsDragWindow) - { - ImGui::PopStyleVar(1); - - entry::WindowState& state = s_ctx.m_window[0].m_state; - ImGuiIO& io = ImGui::GetIO(); - io.MousePos = ImVec2((float)state.m_mouse.m_mx, (float)state.m_mouse.m_my); - io.MouseDown[0] = !!state.m_mouse.m_buttons[entry::MouseButton::Left]; - io.MouseDown[1] = !!state.m_mouse.m_buttons[entry::MouseButton::Right]; - io.MouseDown[2] = !!state.m_mouse.m_buttons[entry::MouseButton::Middle]; - io.MouseWheel = float(state.m_mouse.m_mz); - } -#endif // USE_ENTRY -} - -#if USE_ENTRY - -void pwToWindow(entry::WindowHandle _handle, PlatformWindow* _pw) -{ - s_ctx.m_window[_handle.idx].m_pw = _pw; -} - -void imguiUpdateWindow(const entry::WindowState& _state) -{ - OcornutImguiContext::Window& window = s_ctx.m_window[_state.m_handle.idx]; - - if (window.m_state.m_nwh != _state.m_nwh - || (window.m_state.m_width != _state.m_width - || window.m_state.m_height != _state.m_height) ) - { - // When window changes size or native window handle changed - // frame buffer must be recreated. - if (bgfx::isValid(window.m_fbh) ) - { - bgfx::destroyFrameBuffer(window.m_fbh); - window.m_fbh.idx = bgfx::invalidHandle; - } - - if (NULL != _state.m_nwh) - { - window.m_fbh = bgfx::createFrameBuffer(_state.m_nwh, _state.m_width, _state.m_height); - window.m_viewId = 200 + _state.m_handle.idx; - } - else - { - window.m_viewId = s_ctx.m_viewId; - } - } - - memcpy(&window.m_state, &_state, sizeof(entry::WindowState) ); -} -#endif // USE_ENTRY - void* OcornutImguiContext::memAlloc(size_t _size) { return BX_ALLOC(s_ctx.m_allocator, _size);