Added new editor layout similar to idTech 5.

Cleaned up the entity inspector.
Fixed numerous radiant bugs.
This commit is contained in:
Justin Marshall
2026-05-06 12:47:20 -07:00
parent baeae00185
commit 1a08d4af90
11 changed files with 3883 additions and 723 deletions
+932 -2
View File
@@ -32,11 +32,16 @@ If you have questions concerning this license or the applicable additional terms
#include "qe3.h"
#include "Radiant.h"
#include "XYWnd.h"
#include "ZWnd.h"
#include "DialogInfo.h"
#include "splines.h"
#include "../../renderer/tr_local.h"
#include "../../renderer/model_local.h" // for idRenderModelLiquid
#ifndef WM_IDLEUPDATECMDUI
#define WM_IDLEUPDATECMDUI 0x0363
#endif
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
@@ -110,6 +115,926 @@ CMemFile g_PatchClipboard(4096);
extern int pressx;
extern int pressy;
//=============================================================================
// CXYMenuBar
//=============================================================================
IMPLEMENT_DYNAMIC(CXYMenuBar, CWnd)
BEGIN_MESSAGE_MAP(CXYMenuBar, CWnd)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
ON_WM_ERASEBKGND()
END_MESSAGE_MAP()
CXYMenuBar::CXYMenuBar() {
m_nItemRects = 0;
m_nHotItem = -1;
}
CXYMenuBar::~CXYMenuBar() {
if (m_menu.GetSafeHmenu()) {
m_menu.DestroyMenu();
}
}
BOOL CXYMenuBar::Create(CWnd *pParent, UINT nID) {
CString className = AfxRegisterWndClass(
CS_HREDRAW | CS_VREDRAW,
::LoadCursor(NULL, IDC_ARROW),
(HBRUSH)(COLOR_MENU + 1),
NULL
);
return CWnd::CreateEx(
0,
className,
"RadiantEmbeddedMenuBar",
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
CRect(0, 0, 0, 0),
pParent,
nID
);
}
BOOL CXYMenuBar::AttachMenu(HMENU hMenu) {
if (!hMenu) {
return FALSE;
}
if (m_menu.GetSafeHmenu()) {
m_menu.DestroyMenu();
}
m_menu.Attach(hMenu);
Invalidate(FALSE);
return TRUE;
}
BOOL CXYMenuBar::LoadMenu(UINT nID) {
if (m_menu.GetSafeHmenu()) {
m_menu.DestroyMenu();
}
BOOL result = m_menu.LoadMenu(nID);
Invalidate(FALSE);
return result;
}
CMenu *CXYMenuBar::GetMenu() {
return m_menu.GetSafeHmenu() ? &m_menu : NULL;
}
HMENU CXYMenuBar::GetMenuHandle() const {
return m_menu.GetSafeHmenu();
}
int CXYMenuBar::PreferredHeight() const {
int h = ::GetSystemMetrics(SM_CYMENU) + 4;
return (h < 22) ? 22 : h;
}
void CXYMenuBar::RebuildItemRects(CDC &dc) {
m_nItemRects = 0;
if (!m_menu.GetSafeHmenu()) {
return;
}
int x = 4;
const int y = 1;
const int h = PreferredHeight() - 2;
const int count = m_menu.GetMenuItemCount();
for (int i = 0; i < count; i++) {
CString text;
m_menu.GetMenuString(i, text, MF_BYPOSITION);
if (m_nItemRects >= 64) {
break;
}
if (text.IsEmpty()) {
m_itemRects[m_nItemRects++] = CRect(x, y, x + 8, y + h);
x += 8;
continue;
}
CSize size = dc.GetTextExtent(text);
CRect rect(x, y, x + size.cx + 20, y + h);
m_itemRects[m_nItemRects++] = rect;
x = rect.right + 1;
}
}
int CXYMenuBar::HitTest(const CPoint &point) const {
for (int i = 0; i < m_nItemRects; i++) {
if (m_itemRects[i].PtInRect(point)) {
return i;
}
}
return -1;
}
void CXYMenuBar::TrackTopLevelMenu(int nIndex) {
if (!m_menu.GetSafeHmenu() || nIndex < 0 || nIndex >= m_menu.GetMenuItemCount()) {
return;
}
CMenu *subMenu = m_menu.GetSubMenu(nIndex);
if (!subMenu || !subMenu->GetSafeHmenu()) {
return;
}
CRect rect;
if (nIndex < m_nItemRects) {
rect = m_itemRects[nIndex];
} else {
GetClientRect(rect);
}
CPoint pt(rect.left, rect.bottom);
ClientToScreen(&pt);
m_nHotItem = nIndex;
Invalidate(FALSE);
UpdateWindow();
CWnd *commandTarget = GetCommandTarget();
CWnd *popupOwner = (commandTarget && commandTarget->GetSafeHwnd()) ? commandTarget : static_cast<CWnd *>(this);
if (popupOwner && popupOwner->GetSafeHwnd()) {
CWnd *topLevelOwner = popupOwner->GetTopLevelParent();
if (topLevelOwner && topLevelOwner->GetSafeHwnd()) {
topLevelOwner->SetForegroundWindow();
} else {
popupOwner->SetForegroundWindow();
}
}
// The popup owner must be the frame, not this embedded menu-bar window.
// That keeps WM_INITMENUPOPUP, WM_MENUSELECT, command routing, MRU updates,
// and ON_UPDATE_COMMAND_UI handling in CMainFrame where the old menu used them.
UINT command = subMenu->TrackPopupMenu(
TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD,
pt.x,
pt.y,
popupOwner
);
if (command != 0 && commandTarget && commandTarget->GetSafeHwnd()) {
commandTarget->SendMessage(WM_COMMAND, MAKEWPARAM(command, 0), 0);
}
m_nHotItem = -1;
Invalidate(FALSE);
if (popupOwner && popupOwner->GetSafeHwnd()) {
popupOwner->PostMessage(WM_NULL, 0, 0);
} else {
PostMessage(WM_NULL, 0, 0);
}
}
CWnd *CXYMenuBar::GetCommandTarget() const {
CWnd *commandTarget = AfxGetMainWnd();
if (commandTarget && commandTarget->GetSafeHwnd() && commandTarget != this) {
return commandTarget;
}
for (CWnd *parent = GetParent(); parent && parent->GetSafeHwnd(); parent = parent->GetParent()) {
if (parent != this && parent->IsKindOf(RUNTIME_CLASS(CFrameWnd))) {
return parent;
}
}
return NULL;
}
static int XYMenuBarUpper(int ch) {
if (ch >= 'a' && ch <= 'z') {
return ch - 'a' + 'A';
}
return ch;
}
BOOL CXYMenuBar::TrackMnemonic(UINT nChar) {
if (!m_menu.GetSafeHmenu()) {
return FALSE;
}
if (nChar == VK_F10) {
TrackTopLevelMenu(0);
return TRUE;
}
if (nChar > 255) {
return FALSE;
}
const int wanted = XYMenuBarUpper(static_cast<int>(nChar));
const int count = m_menu.GetMenuItemCount();
for (int i = 0; i < count; i++) {
CString text;
m_menu.GetMenuString(i, text, MF_BYPOSITION);
const int len = text.GetLength();
for (int j = 0; j < len; j++) {
if (text[j] != '&') {
continue;
}
if (j + 1 >= len) {
break;
}
if (text[j + 1] == '&') {
j++;
continue;
}
if (XYMenuBarUpper(static_cast<unsigned char>(text[j + 1])) == wanted) {
TrackTopLevelMenu(i);
return TRUE;
}
}
}
return FALSE;
}
void CXYMenuBar::OnPaint() {
CPaintDC dc(this);
CRect client;
GetClientRect(client);
CBrush backBrush(::GetSysColor(COLOR_MENU));
dc.FillRect(client, &backBrush);
RebuildItemRects(dc);
if (m_menu.GetSafeHmenu()) {
const int count = m_menu.GetMenuItemCount();
for (int i = 0; i < count && i < m_nItemRects; i++) {
CString text;
m_menu.GetMenuString(i, text, MF_BYPOSITION);
CRect itemRect = m_itemRects[i];
if (i == m_nHotItem) {
dc.Draw3dRect(itemRect, ::GetSysColor(COLOR_3DHILIGHT), ::GetSysColor(COLOR_3DSHADOW));
itemRect.DeflateRect(1, 1);
}
dc.SetBkMode(TRANSPARENT);
dc.SetTextColor(::GetSysColor(COLOR_MENUTEXT));
dc.DrawText(text, itemRect, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
}
}
CPen shadowPen(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW));
CPen *oldPen = dc.SelectObject(&shadowPen);
dc.MoveTo(client.left, client.bottom - 1);
dc.LineTo(client.right, client.bottom - 1);
dc.SelectObject(oldPen);
}
void CXYMenuBar::OnLButtonDown(UINT nFlags, CPoint point) {
CClientDC dc(this);
RebuildItemRects(dc);
TrackTopLevelMenu(HitTest(point));
}
void CXYMenuBar::OnMouseMove(UINT nFlags, CPoint point) {
CClientDC dc(this);
RebuildItemRects(dc);
int hotItem = HitTest(point);
if (hotItem != m_nHotItem) {
m_nHotItem = hotItem;
Invalidate(FALSE);
}
CWnd::OnMouseMove(nFlags, point);
}
BOOL CXYMenuBar::OnEraseBkgnd(CDC *pDC) {
return TRUE;
}
BOOL CXYMenuBar::OnCommand(WPARAM wParam, LPARAM lParam) {
CWnd *commandTarget = GetCommandTarget();
if (commandTarget && commandTarget->GetSafeHwnd() && commandTarget != this) {
return static_cast<BOOL>(commandTarget->SendMessage(WM_COMMAND, wParam, lParam));
}
return CWnd::OnCommand(wParam, lParam);
}
BOOL CXYMenuBar::OnCmdMsg(UINT nID, int nCode, void *pExtra, AFX_CMDHANDLERINFO *pHandlerInfo) {
if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)) {
return TRUE;
}
CWnd *commandTarget = GetCommandTarget();
if (commandTarget && commandTarget->GetSafeHwnd() && commandTarget != this) {
return commandTarget->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
return FALSE;
}
//=============================================================================
// CXYMDIContainerWnd
//=============================================================================
IMPLEMENT_DYNAMIC(CXYMDIContainerWnd, CWnd)
BEGIN_MESSAGE_MAP(CXYMDIContainerWnd, CWnd)
ON_WM_SIZE()
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_SETCURSOR()
ON_WM_ERASEBKGND()
END_MESSAGE_MAP()
CXYMDIContainerWnd::CXYMDIContainerWnd() {
m_pXYWnd = NULL;
m_pZWnd = NULL;
m_nZDockPercent = 5;
m_nZWidth = 0;
m_nSplitterWidth = 5;
m_bZStartupSized = false;
m_bInLayout = false;
m_bTrackingSplitter = false;
m_nDragStartX = 0;
m_nDragStartZWidth = 0;
m_rcSplitter.SetRectEmpty();
}
CXYMDIContainerWnd::~CXYMDIContainerWnd() {
}
BOOL CXYMDIContainerWnd::Create(CWnd *pParent, UINT nID) {
CLIENTCREATESTRUCT clientCreate;
memset(&clientCreate, 0, sizeof(clientCreate));
clientCreate.hWindowMenu = NULL;
clientCreate.idFirstChild = 0x7B00;
return CWnd::CreateEx(
0,
"MDICLIENT",
"RadiantXYMDIContainer",
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
CRect(0, 0, 0, 0),
pParent,
nID,
&clientCreate
);
}
void CXYMDIContainerWnd::AttachChild(CWnd *pWnd) {
if (!pWnd || !pWnd->GetSafeHwnd() || !GetSafeHwnd()) {
return;
}
if (::GetParent(pWnd->GetSafeHwnd()) != GetSafeHwnd()) {
pWnd->SetParent(this);
}
LONG style = ::GetWindowLong(pWnd->GetSafeHwnd(), GWL_STYLE);
style &= ~(WS_POPUP | WS_CAPTION | WS_THICKFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
style |= WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
::SetWindowLong(pWnd->GetSafeHwnd(), GWL_STYLE, style);
::SetWindowPos(
pWnd->GetSafeHwnd(),
NULL,
0,
0,
0,
0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED
);
}
void CXYMDIContainerWnd::SetChildWindows(CXYWnd *pXYWnd, CZWnd *pZWnd) {
m_pXYWnd = pXYWnd;
m_pZWnd = pZWnd;
AttachChild(m_pZWnd);
AttachChild(m_pXYWnd);
LayoutChildren();
}
void CXYMDIContainerWnd::SetEmbeddedWindows(CWnd *pZWnd, CWnd *pXYWnd) {
m_pZWnd = pZWnd;
m_pXYWnd = pXYWnd;
AttachChild(m_pZWnd);
AttachChild(m_pXYWnd);
LayoutChildren();
}
bool CXYMDIContainerWnd::IsZVisible() const {
return m_pZWnd && m_pZWnd->GetSafeHwnd() && m_pZWnd->IsWindowVisible();
}
int CXYMDIContainerWnd::ClampZWidth(int zWidth, const CRect &client) const {
const int width = client.Width();
if (width <= m_nSplitterWidth + 1) {
return 0;
}
const int minZ = 1;
const int minXY = 64;
const int available = width - m_nSplitterWidth;
int maxZ = available - minXY;
if (maxZ < minZ) {
maxZ = available - 1;
}
if (maxZ < minZ) {
return 0;
}
if (zWidth < minZ) {
zWidth = minZ;
}
if (zWidth > maxZ) {
zWidth = maxZ;
}
return zWidth;
}
int CXYMDIContainerWnd::ComputeInitialZWidth(const CRect &client) const {
const int width = client.Width();
if (width <= 1) {
return 0;
}
int zWidth = (width * m_nZDockPercent) / 100;
if (zWidth < 1) {
zWidth = 1;
}
return ClampZWidth(zWidth, client);
}
void CXYMDIContainerWnd::SetZDockPercent(int percent) {
// Keep legacy MainFrm calls such as SetZDockPercent(20) from changing the
// required startup size. The embedded Z pane starts at 5%, then the user can
// drag the splitter to any practical width.
m_nZDockPercent = 5;
if (!m_bZStartupSized) {
LayoutChildren();
}
}
int CXYMDIContainerWnd::GetZDockPercent() const {
return m_nZDockPercent;
}
int CXYMDIContainerWnd::GetZWidth() const {
return m_nZWidth;
}
int CXYMDIContainerWnd::GetFixedZWidth() const {
return GetZWidth();
}
bool CXYMDIContainerWnd::HitTestSplitter(const CPoint &point) const {
return !m_rcSplitter.IsRectEmpty() && m_rcSplitter.PtInRect(point);
}
void CXYMDIContainerWnd::DrawSplitter(CDC *pDC) {
if (!pDC || m_rcSplitter.IsRectEmpty()) {
return;
}
CRect rc = m_rcSplitter;
CBrush brush(::GetSysColor(COLOR_BTNFACE));
pDC->FillRect(rc, &brush);
pDC->Draw3dRect(rc, ::GetSysColor(COLOR_3DHILIGHT), ::GetSysColor(COLOR_3DSHADOW));
int x = rc.left + rc.Width() / 2;
CPen pen(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW));
CPen *oldPen = pDC->SelectObject(&pen);
pDC->MoveTo(x, rc.top + 3);
pDC->LineTo(x, rc.bottom - 3);
pDC->SelectObject(oldPen);
}
void CXYMDIContainerWnd::LayoutChildren() {
if (!GetSafeHwnd() || m_bInLayout) {
return;
}
m_bInLayout = true;
CRect client;
GetClientRect(client);
if (client.Width() < 1 || client.Height() < 1) {
m_rcSplitter.SetRectEmpty();
m_bInLayout = false;
return;
}
bool zVisible = IsZVisible();
int zWidth = 0;
int splitterWidth = 0;
if (zVisible) {
if (!m_bZStartupSized) {
m_nZWidth = ComputeInitialZWidth(client);
m_bZStartupSized = true;
}
zWidth = ClampZWidth(m_nZWidth, client);
m_nZWidth = zWidth;
if (zWidth > 0 && client.Width() > zWidth + m_nSplitterWidth) {
splitterWidth = m_nSplitterWidth;
}
}
if (m_pZWnd && m_pZWnd->GetSafeHwnd()) {
if (zVisible && zWidth > 0) {
m_pZWnd->MoveWindow(client.left, client.top, zWidth, client.Height(), TRUE);
m_pZWnd->Invalidate(FALSE);
}
}
if (zVisible && zWidth > 0 && splitterWidth > 0) {
m_rcSplitter.SetRect(client.left + zWidth, client.top, client.left + zWidth + splitterWidth, client.bottom);
} else {
m_rcSplitter.SetRectEmpty();
}
if (m_pXYWnd && m_pXYWnd->GetSafeHwnd()) {
int xyLeft = client.left + zWidth + splitterWidth;
if (xyLeft > client.right - 1) {
xyLeft = client.left;
}
CRect xyRect(xyLeft, client.top, client.right, client.bottom);
m_pXYWnd->MoveWindow(xyRect, TRUE);
m_pXYWnd->Invalidate(FALSE);
}
Invalidate(FALSE);
m_bInLayout = false;
}
void CXYMDIContainerWnd::OnSize(UINT nType, int cx, int cy) {
CWnd::OnSize(nType, cx, cy);
LayoutChildren();
}
void CXYMDIContainerWnd::OnPaint() {
CPaintDC dc(this);
DrawSplitter(&dc);
}
void CXYMDIContainerWnd::OnLButtonDown(UINT nFlags, CPoint point) {
if (HitTestSplitter(point)) {
m_bTrackingSplitter = true;
m_nDragStartX = point.x;
m_nDragStartZWidth = m_nZWidth;
SetCapture();
::SetCursor(::LoadCursor(NULL, IDC_SIZEWE));
return;
}
CWnd::OnLButtonDown(nFlags, point);
}
void CXYMDIContainerWnd::OnLButtonUp(UINT nFlags, CPoint point) {
if (m_bTrackingSplitter) {
m_bTrackingSplitter = false;
if (GetCapture() == this) {
ReleaseCapture();
}
LayoutChildren();
return;
}
CWnd::OnLButtonUp(nFlags, point);
}
void CXYMDIContainerWnd::OnMouseMove(UINT nFlags, CPoint point) {
if (m_bTrackingSplitter) {
CRect client;
GetClientRect(client);
m_nZWidth = ClampZWidth(m_nDragStartZWidth + point.x - m_nDragStartX, client);
LayoutChildren();
::SetCursor(::LoadCursor(NULL, IDC_SIZEWE));
return;
}
if (HitTestSplitter(point)) {
::SetCursor(::LoadCursor(NULL, IDC_SIZEWE));
}
CWnd::OnMouseMove(nFlags, point);
}
BOOL CXYMDIContainerWnd::OnSetCursor(CWnd *pWnd, UINT nHitTest, UINT message) {
CPoint point;
GetCursorPos(&point);
ScreenToClient(&point);
if (m_bTrackingSplitter || HitTestSplitter(point)) {
::SetCursor(::LoadCursor(NULL, IDC_SIZEWE));
return TRUE;
}
return CWnd::OnSetCursor(pWnd, nHitTest, message);
}
BOOL CXYMDIContainerWnd::OnEraseBkgnd(CDC *pDC) {
DrawSplitter(pDC);
return TRUE;
}
BOOL CXYMDIContainerWnd::OnCommand(WPARAM wParam, LPARAM lParam) {
CWnd *commandTarget = AfxGetMainWnd();
if (commandTarget && commandTarget->GetSafeHwnd() && commandTarget != this) {
return static_cast<BOOL>(commandTarget->SendMessage(WM_COMMAND, wParam, lParam));
}
return CWnd::OnCommand(wParam, lParam);
}
BOOL CXYMDIContainerWnd::OnCmdMsg(UINT nID, int nCode, void *pExtra, AFX_CMDHANDLERINFO *pHandlerInfo) {
if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)) {
return TRUE;
}
CWnd *commandTarget = AfxGetMainWnd();
if (commandTarget && commandTarget->GetSafeHwnd() && commandTarget != this) {
return commandTarget->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
return FALSE;
}
//=============================================================================
// CXYDockWnd
//=============================================================================
IMPLEMENT_DYNAMIC(CXYDockWnd, CWnd)
BEGIN_MESSAGE_MAP(CXYDockWnd, CWnd)
ON_WM_CREATE()
ON_WM_SIZE()
ON_WM_ERASEBKGND()
ON_MESSAGE(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI)
END_MESSAGE_MAP()
CXYDockWnd::CXYDockWnd() {
m_pToolBar = NULL;
m_bInLayout = false;
}
CXYDockWnd::~CXYDockWnd() {
}
BOOL CXYDockWnd::Create(CWnd *pParent, UINT nID) {
CRect rect(0, 0, 0, 0);
return Create(rect, pParent, nID);
}
BOOL CXYDockWnd::Create(const RECT &rect, CWnd *pParent, UINT nID) {
CString className = AfxRegisterWndClass(
CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS,
::LoadCursor(NULL, IDC_ARROW),
(HBRUSH)(COLOR_BTNFACE + 1),
NULL
);
return CWnd::CreateEx(
0,
className,
"RadiantXYDockWnd",
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
rect,
pParent,
nID
);
}
int CXYDockWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) {
if (CWnd::OnCreate(lpCreateStruct) == -1) {
return -1;
}
if (!m_wndMenuBar.Create(this, 0x7A01)) {
return -1;
}
if (!m_wndMDIContainer.Create(this, 0x7A02)) {
return -1;
}
return 0;
}
void CXYDockWnd::SetChildWindows(CXYWnd *pXYWnd, CZWnd *pZWnd) {
m_wndMDIContainer.SetChildWindows(pXYWnd, pZWnd);
LayoutChildren();
}
void CXYDockWnd::SetEmbeddedWindows(CWnd *pZWnd, CWnd *pXYWnd) {
m_wndMDIContainer.SetEmbeddedWindows(pZWnd, pXYWnd);
LayoutChildren();
}
void CXYDockWnd::SetToolBar(CToolBar *pToolBar) {
m_pToolBar = pToolBar;
if (m_pToolBar && m_pToolBar->GetSafeHwnd()) {
CWnd *commandTarget = GetCommandTarget();
if (!commandTarget || !commandTarget->GetSafeHwnd()) {
commandTarget = this;
}
m_pToolBar->SetParent(this);
m_pToolBar->SetOwner(this);
m_pToolBar->SetDlgCtrlID(AFX_IDW_TOOLBAR);
m_pToolBar->ModifyStyle(WS_POPUP | WS_CAPTION | WS_THICKFRAME | WS_SYSMENU, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
}
LayoutChildren();
}
void CXYDockWnd::SetEmbeddedToolBar(CToolBar *pToolBar) {
SetToolBar(pToolBar);
}
CWnd *CXYDockWnd::GetCommandTarget() const {
CWnd *commandTarget = AfxGetMainWnd();
if (commandTarget && commandTarget->GetSafeHwnd() && commandTarget != this) {
return commandTarget;
}
for (CWnd *parent = GetParent(); parent && parent->GetSafeHwnd(); parent = parent->GetParent()) {
if (parent != this && parent->IsKindOf(RUNTIME_CLASS(CFrameWnd))) {
return parent;
}
}
return NULL;
}
void CXYDockWnd::UpdateToolBarCmdUI(BOOL bDisableIfNoHndler) {
if (!m_pToolBar || !m_pToolBar->GetSafeHwnd() || !m_pToolBar->IsWindowVisible()) {
return;
}
CWnd *commandTarget = GetCommandTarget();
if (!commandTarget || !commandTarget->GetSafeHwnd()) {
return;
}
if (commandTarget->IsKindOf(RUNTIME_CLASS(CFrameWnd))) {
m_pToolBar->OnUpdateCmdUI(static_cast<CFrameWnd *>(commandTarget), bDisableIfNoHndler);
}
}
void CXYDockWnd::ShowEmbeddedToolBar(BOOL bShow) {
if (m_pToolBar && m_pToolBar->GetSafeHwnd()) {
m_pToolBar->ShowWindow(bShow ? SW_SHOW : SW_HIDE);
}
LayoutChildren();
}
BOOL CXYDockWnd::AttachMenu(HMENU hMenu) {
BOOL result = m_wndMenuBar.AttachMenu(hMenu);
LayoutChildren();
return result;
}
void CXYDockWnd::SetMenuHandle(HMENU hMenu) {
AttachMenu(hMenu);
}
BOOL CXYDockWnd::LoadMenu(UINT nID) {
BOOL result = m_wndMenuBar.LoadMenu(nID);
LayoutChildren();
return result;
}
CMenu *CXYDockWnd::GetEmbeddedMenu() {
return m_wndMenuBar.GetMenu();
}
HMENU CXYDockWnd::GetEmbeddedMenuHandle() const {
return m_wndMenuBar.GetMenuHandle();
}
HMENU CXYDockWnd::GetMenuHandle() const {
return GetEmbeddedMenuHandle();
}
void CXYDockWnd::SetZDockPercent(int percent) {
m_wndMDIContainer.SetZDockPercent(percent);
}
void CXYDockWnd::SetZPercent(int percent) {
SetZDockPercent(percent);
}
int CXYDockWnd::GetZDockPercent() const {
return m_wndMDIContainer.GetZDockPercent();
}
int CXYDockWnd::GetZPercent() const {
return GetZDockPercent();
}
void CXYDockWnd::LayoutChildren() {
if (!GetSafeHwnd() || m_bInLayout) {
return;
}
m_bInLayout = true;
CRect client;
GetClientRect(client);
int y = client.top;
const int width = client.Width();
if (m_wndMenuBar.GetSafeHwnd()) {
if (m_wndMenuBar.GetMenuHandle()) {
m_wndMenuBar.ShowWindow(SW_SHOW);
const int menuHeight = m_wndMenuBar.PreferredHeight();
m_wndMenuBar.MoveWindow(client.left, y, width, menuHeight, TRUE);
y += menuHeight;
} else {
m_wndMenuBar.ShowWindow(SW_HIDE);
}
}
if (m_pToolBar && m_pToolBar->GetSafeHwnd()) {
if (m_pToolBar->IsWindowVisible()) {
CSize toolbarSize = m_pToolBar->CalcFixedLayout(FALSE, TRUE);
int toolbarHeight = toolbarSize.cy;
if (toolbarHeight < 24) {
toolbarHeight = 24;
}
m_pToolBar->MoveWindow(client.left, y, width, toolbarHeight, TRUE);
y += toolbarHeight;
}
}
CRect content(client.left, y, client.right, client.bottom);
if (content.Width() < 1 || content.Height() < 1) {
m_bInLayout = false;
return;
}
if (m_wndMDIContainer.GetSafeHwnd()) {
m_wndMDIContainer.MoveWindow(content, TRUE);
m_wndMDIContainer.LayoutChildren();
}
m_bInLayout = false;
}
void CXYDockWnd::RecalcLayout() {
LayoutChildren();
}
BOOL CXYDockWnd::TrackMenuMnemonic(UINT nChar) {
if (m_wndMenuBar.GetSafeHwnd()) {
return m_wndMenuBar.TrackMnemonic(nChar);
}
return FALSE;
}
void CXYDockWnd::OnSize(UINT nType, int cx, int cy) {
CWnd::OnSize(nType, cx, cy);
LayoutChildren();
}
BOOL CXYDockWnd::OnEraseBkgnd(CDC *pDC) {
return TRUE;
}
LRESULT CXYDockWnd::OnIdleUpdateCmdUI(WPARAM wParam, LPARAM lParam) {
UpdateToolBarCmdUI(static_cast<BOOL>(wParam));
return 0L;
}
BOOL CXYDockWnd::OnCommand(WPARAM wParam, LPARAM lParam) {
CWnd *commandTarget = GetCommandTarget();
if (commandTarget && commandTarget->GetSafeHwnd() && commandTarget != this) {
return static_cast<BOOL>(commandTarget->SendMessage(WM_COMMAND, wParam, lParam));
}
return CWnd::OnCommand(wParam, lParam);
}
BOOL CXYDockWnd::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT *pResult) {
CWnd *commandTarget = GetCommandTarget();
if (commandTarget && commandTarget->GetSafeHwnd() && commandTarget != this) {
LRESULT result = commandTarget->SendMessage(WM_NOTIFY, wParam, lParam);
if (pResult) {
*pResult = result;
}
if (result != 0) {
return TRUE;
}
}
return CWnd::OnNotify(wParam, lParam, pResult);
}
BOOL CXYDockWnd::OnCmdMsg(UINT nID, int nCode, void *pExtra, AFX_CMDHANDLERINFO *pHandlerInfo) {
if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)) {
return TRUE;
}
CWnd *commandTarget = GetCommandTarget();
if (commandTarget && commandTarget->GetSafeHwnd() && commandTarget != this) {
return commandTarget->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
return FALSE;
}
/*
=======================================================================================================================
=======================================================================================================================
@@ -594,6 +1519,7 @@ BOOL CXYWnd::PreCreateWindow(CREATESTRUCT &cs) {
if (cs.style != QE3_CHILDSTYLE) {
cs.style = QE3_SPLITTER_STYLE;
}
cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
return CWnd::PreCreateWindow(cs);
}
@@ -2732,7 +3658,7 @@ bool CXYWnd::XY_MouseMoved(int x, int y, int buttons) {
/*
=======================================================================================================================
DRAWING £
DRAWING £
XY_DrawGrid
=======================================================================================================================
*/
@@ -3304,7 +4230,7 @@ bool FilterBrush(brush_t *pb) {
/*
=======================================================================================================================
PATH LINES £
PATH LINES £
DrawPathLines Draws connections between entities. Needs to consider all entities, not just ones on screen, because
the lines can be visible when neither end is. Called for both camera view and xy view.
=======================================================================================================================
@@ -3535,6 +4461,10 @@ extern void DrawBrushEntityName(brush_t *b);
=======================================================================================================================
*/
void CXYWnd::XY_Draw() {
if (m_nWidth <= 0 || m_nHeight <= 0) {
return;
}
brush_t *brush;
float w, h;
entity_t *e;