Added material editor to main tabs.

This commit is contained in:
Justin Marshall
2026-05-18 15:54:16 -07:00
parent eb7ffe2cdc
commit 4686349b62
14 changed files with 1300 additions and 126 deletions
@@ -36,6 +36,10 @@ If you have questions concerning this license or the applicable additional terms
#define EDIT_HEIGHT 25
extern void MaterialEditorDark_ApplyToWindow(HWND hWnd);
extern COLORREF MaterialEditorDark_PanelColor(void);
extern COLORREF MaterialEditorDark_TextColor(void);
IMPLEMENT_DYNCREATE(ConsoleView, CFormView)
@@ -257,6 +261,14 @@ void ConsoleView::OnInitialUpdate() {
if(editInput.m_hWnd)
editInput.MoveWindow(0, rect.Height()-EDIT_HEIGHT, rect.Width(), EDIT_HEIGHT);
MaterialEditorDark_ApplyToWindow(GetSafeHwnd());
if (editConsole.GetSafeHwnd()) {
editConsole.SendMessage(EM_SETBKGNDCOLOR, 0, (LPARAM)MaterialEditorDark_PanelColor());
}
if (editInput.GetSafeHwnd()) {
editInput.SendMessage(EM_SETBKGNDCOLOR, 0, (LPARAM)MaterialEditorDark_PanelColor());
}
}
/**
@@ -33,6 +33,8 @@ If you have questions concerning this license or the applicable additional terms
#include "MEMainFrame.h"
extern void MaterialEditorDark_ApplyToWindow(HWND hWnd);
IMPLEMENT_DYNAMIC(FindDialog, CDialog)
BEGIN_MESSAGE_MAP(FindDialog, CDialog)
@@ -84,6 +86,8 @@ BOOL FindDialog::OnInitDialog() {
LoadFindSettings();
MaterialEditorDark_ApplyToWindow(GetSafeHwnd());
GetDlgItem(IDC_EDIT_FINDTEXT)->SetFocus();
return FALSE;
+393 -77
View File
@@ -38,6 +38,14 @@ If you have questions concerning this license or the applicable additional terms
#define TAB_CONTROL 0x1006
extern bool MaterialEditorIsEmbedded(void);
extern void MaterialEditorDark_ApplyToWindow(HWND hWnd);
extern COLORREF MaterialEditorDark_BackgroundColor(void);
extern COLORREF MaterialEditorDark_PanelColor(void);
extern COLORREF MaterialEditorDark_TextColor(void);
extern COLORREF MaterialEditorDark_AccentColor(void);
extern COLORREF MaterialEditorDark_BorderColor(void);
IMPLEMENT_DYNAMIC(MEMainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP(MEMainFrame, CFrameWnd)
@@ -95,6 +103,301 @@ static UINT indicators[] =
ID_INDICATOR_SCRL,
};
#define ME_EMBEDDED_MENUBAR_ID 0x6E10
static HWND s_meEmbeddedMenuBar = NULL;
static HMENU s_meEmbeddedMenu = NULL;
static CRect s_meEmbeddedMenuRects[64];
static int s_meEmbeddedMenuRectCount = 0;
static int s_meEmbeddedMenuHotItem = -1;
static int MEEmbeddedMenuBar_PreferredHeight() {
int h = ::GetSystemMetrics(SM_CYMENU) + 4;
return (h < 22) ? 22 : h;
}
static COLORREF MEEmbeddedMenuBar_MenuColor() {
return RGB(28, 31, 36);
}
static COLORREF MEEmbeddedMenuBar_HotColor() {
return RGB(45, 50, 58);
}
static void MEEmbeddedMenuBar_FillRect(HDC hDC, const RECT& rc, COLORREF color) {
HBRUSH brush = ::CreateSolidBrush(color);
::FillRect(hDC, &rc, brush);
::DeleteObject(brush);
}
static void MEEmbeddedMenuBar_RebuildRects(HWND hWnd, HDC hDC) {
s_meEmbeddedMenuRectCount = 0;
if (!s_meEmbeddedMenu) {
return;
}
int x = 4;
const int y = 1;
const int h = MEEmbeddedMenuBar_PreferredHeight() - 2;
const int count = ::GetMenuItemCount(s_meEmbeddedMenu);
for (int i = 0; i < count && s_meEmbeddedMenuRectCount < 64; i++) {
char text[128];
text[0] = '\0';
::GetMenuStringA(s_meEmbeddedMenu, i, text, sizeof(text), MF_BYPOSITION);
SIZE size;
size.cx = 0;
size.cy = 0;
::GetTextExtentPoint32A(hDC, text, strlen(text), &size);
CRect rect(x, y, x + size.cx + 22, y + h);
s_meEmbeddedMenuRects[s_meEmbeddedMenuRectCount++] = rect;
x = rect.right + 1;
}
}
static int MEEmbeddedMenuBar_HitTest(const CPoint& point) {
for (int i = 0; i < s_meEmbeddedMenuRectCount; i++) {
if (s_meEmbeddedMenuRects[i].PtInRect(point)) {
return i;
}
}
return -1;
}
static void MEEmbeddedMenuBar_Draw(HWND hWnd, HDC hDC) {
RECT client;
::GetClientRect(hWnd, &client);
MEEmbeddedMenuBar_FillRect(hDC, client, MEEmbeddedMenuBar_MenuColor());
HFONT font = (HFONT)::SendMessage(hWnd, WM_GETFONT, 0, 0);
HFONT oldFont = font ? (HFONT)::SelectObject(hDC, font) : NULL;
::SetBkMode(hDC, TRANSPARENT);
MEEmbeddedMenuBar_RebuildRects(hWnd, hDC);
if (s_meEmbeddedMenu) {
const int count = ::GetMenuItemCount(s_meEmbeddedMenu);
for (int i = 0; i < count && i < s_meEmbeddedMenuRectCount; i++) {
char text[128];
text[0] = '\0';
::GetMenuStringA(s_meEmbeddedMenu, i, text, sizeof(text), MF_BYPOSITION);
CRect itemRect = s_meEmbeddedMenuRects[i];
if (i == s_meEmbeddedMenuHotItem) {
MEEmbeddedMenuBar_FillRect(hDC, itemRect, MEEmbeddedMenuBar_HotColor());
HPEN pen = ::CreatePen(PS_SOLID, 1, MaterialEditorDark_AccentColor());
HPEN oldPen = (HPEN)::SelectObject(hDC, pen);
HBRUSH oldBrush = (HBRUSH)::SelectObject(hDC, GetStockObject(NULL_BRUSH));
::Rectangle(hDC, itemRect.left, itemRect.top, itemRect.right, itemRect.bottom);
::SelectObject(hDC, oldBrush);
::SelectObject(hDC, oldPen);
::DeleteObject(pen);
}
::SetTextColor(hDC, MaterialEditorDark_TextColor());
::DrawTextA(hDC, text, -1, &itemRect, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
}
}
HPEN linePen = ::CreatePen(PS_SOLID, 1, MaterialEditorDark_BorderColor());
HPEN oldPen = (HPEN)::SelectObject(hDC, linePen);
::MoveToEx(hDC, client.left, client.bottom - 1, NULL);
::LineTo(hDC, client.right, client.bottom - 1);
::SelectObject(hDC, oldPen);
::DeleteObject(linePen);
if (oldFont) {
::SelectObject(hDC, oldFont);
}
}
static CWnd *MEEmbeddedMenuBar_GetCommandTarget(HWND hWnd) {
HWND hFrame = ::GetParent(hWnd);
if (!hFrame) {
return NULL;
}
CWnd *target = CWnd::FromHandlePermanent(hFrame);
if (!target) {
target = CWnd::FromHandle(hFrame);
}
return target;
}
static void MEEmbeddedMenuBar_Track(HWND hWnd, int menuIndex) {
if (!s_meEmbeddedMenu || menuIndex < 0 || menuIndex >= ::GetMenuItemCount(s_meEmbeddedMenu)) {
return;
}
HMENU hPopup = ::GetSubMenu(s_meEmbeddedMenu, menuIndex);
if (!hPopup) {
return;
}
CRect itemRect;
if (menuIndex < s_meEmbeddedMenuRectCount) {
itemRect = s_meEmbeddedMenuRects[menuIndex];
} else {
::GetClientRect(hWnd, &itemRect);
}
POINT pt;
pt.x = itemRect.left;
pt.y = itemRect.bottom;
::ClientToScreen(hWnd, &pt);
s_meEmbeddedMenuHotItem = menuIndex;
::InvalidateRect(hWnd, NULL, FALSE);
::UpdateWindow(hWnd);
CWnd *target = MEEmbeddedMenuBar_GetCommandTarget(hWnd);
HWND hTarget = target ? target->GetSafeHwnd() : ::GetParent(hWnd);
if (hTarget) {
::SetForegroundWindow(hTarget);
::SendMessage(hTarget, WM_INITMENUPOPUP, (WPARAM)hPopup, MAKELPARAM(menuIndex, FALSE));
}
UINT command = ::TrackPopupMenu(
hPopup,
TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD,
pt.x,
pt.y,
0,
hTarget ? hTarget : hWnd,
NULL
);
if (command != 0 && hTarget) {
::SendMessage(hTarget, WM_COMMAND, MAKEWPARAM(command, 0), 0);
}
s_meEmbeddedMenuHotItem = -1;
::InvalidateRect(hWnd, NULL, FALSE);
if (hTarget) {
::PostMessage(hTarget, WM_NULL, 0, 0);
}
}
static LRESULT CALLBACK MEEmbeddedMenuBar_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_ERASEBKGND:
return 1;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC = ::BeginPaint(hWnd, &ps);
MEEmbeddedMenuBar_Draw(hWnd, hDC);
::EndPaint(hWnd, &ps);
return 0;
}
case WM_LBUTTONDOWN:
{
HDC hDC = ::GetDC(hWnd);
MEEmbeddedMenuBar_RebuildRects(hWnd, hDC);
::ReleaseDC(hWnd, hDC);
CPoint pt((short)LOWORD(lParam), (short)HIWORD(lParam));
MEEmbeddedMenuBar_Track(hWnd, MEEmbeddedMenuBar_HitTest(pt));
return 0;
}
case WM_MOUSEMOVE:
{
HDC hDC = ::GetDC(hWnd);
MEEmbeddedMenuBar_RebuildRects(hWnd, hDC);
::ReleaseDC(hWnd, hDC);
CPoint pt((short)LOWORD(lParam), (short)HIWORD(lParam));
int hot = MEEmbeddedMenuBar_HitTest(pt);
if (hot != s_meEmbeddedMenuHotItem) {
s_meEmbeddedMenuHotItem = hot;
::InvalidateRect(hWnd, NULL, FALSE);
}
break;
}
case WM_SETFONT:
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
case WM_NCDESTROY:
if (hWnd == s_meEmbeddedMenuBar) {
s_meEmbeddedMenuBar = NULL;
s_meEmbeddedMenuHotItem = -1;
s_meEmbeddedMenuRectCount = 0;
}
break;
}
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
static BOOL MEEmbeddedMenuBar_Create(CWnd *parent) {
if (!parent || !parent->GetSafeHwnd()) {
return FALSE;
}
if (s_meEmbeddedMenuBar && ::IsWindow(s_meEmbeddedMenuBar)) {
::SetParent(s_meEmbeddedMenuBar, parent->GetSafeHwnd());
::ShowWindow(s_meEmbeddedMenuBar, SW_SHOW);
return TRUE;
}
if (!s_meEmbeddedMenu) {
s_meEmbeddedMenu = ::LoadMenu(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ME_MAINFRAME));
}
CString className = AfxRegisterWndClass(
CS_HREDRAW | CS_VREDRAW,
::LoadCursor(NULL, IDC_ARROW),
(HBRUSH)::GetStockObject(BLACK_BRUSH),
NULL
);
s_meEmbeddedMenuBar = ::CreateWindowEx(
0,
className,
_T("MaterialEditorEmbeddedMenuBar"),
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
0,
0,
0,
MEEmbeddedMenuBar_PreferredHeight(),
parent->GetSafeHwnd(),
(HMENU)ME_EMBEDDED_MENUBAR_ID,
AfxGetInstanceHandle(),
NULL
);
if (!s_meEmbeddedMenuBar) {
return FALSE;
}
::SetWindowLongPtr(s_meEmbeddedMenuBar, GWLP_WNDPROC, (LONG_PTR)MEEmbeddedMenuBar_WndProc);
if (materialEditorFont && materialEditorFont->GetSafeHandle()) {
::SendMessage(s_meEmbeddedMenuBar, WM_SETFONT, (WPARAM)materialEditorFont->GetSafeHandle(), TRUE);
}
return TRUE;
}
static void MEEmbeddedMenuBar_DestroyForParent(HWND hParent) {
if (s_meEmbeddedMenuBar && ::IsWindow(s_meEmbeddedMenuBar) && ::GetParent(s_meEmbeddedMenuBar) == hParent) {
::DestroyWindow(s_meEmbeddedMenuBar);
s_meEmbeddedMenuBar = NULL;
}
if (s_meEmbeddedMenu) {
::DestroyMenu(s_meEmbeddedMenu);
s_meEmbeddedMenu = NULL;
}
}
static HWND MEEmbeddedMenuBar_GetSafeHwnd() {
return (s_meEmbeddedMenuBar && ::IsWindow(s_meEmbeddedMenuBar)) ? s_meEmbeddedMenuBar : NULL;
}
static CMenu *MEEmbeddedMenuBar_GetMenu() {
return s_meEmbeddedMenu ? CMenu::FromHandle(s_meEmbeddedMenu) : NULL;
}
/**
* Constructor for MEMainFrame. Initialize some member data and load the options.
*/
@@ -102,6 +405,14 @@ MEMainFrame::MEMainFrame() {
currentDoc = NULL;
m_find = NULL;
m_consoleView = NULL;
m_materialTreeView = NULL;
m_previewPropertyView = NULL;
m_materialPreviewView = NULL;
m_materialEditView = NULL;
m_stageView = NULL;
m_materialPropertyView = NULL;
m_materialEditSplitter = NULL;
searchData.searched = false;
@@ -119,7 +430,9 @@ MEMainFrame::~MEMainFrame() {
* @param msg The text that is to be added to the console.
*/
void MEMainFrame::PrintConsoleMessage(const char *msg) {
m_consoleView->AddText(msg);
if (m_consoleView && m_consoleView->GetSafeHwnd()) {
m_consoleView->AddText(msg);
}
}
/**
@@ -130,7 +443,14 @@ BOOL MEMainFrame::PreCreateWindow(CREATESTRUCT& cs) {
return FALSE;
cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
cs.lpszClass = AfxRegisterWndClass(0);
cs.lpszClass = AfxRegisterWndClass(0, ::LoadCursor(NULL, IDC_ARROW), (HBRUSH)::GetStockObject(BLACK_BRUSH), NULL);
if (MaterialEditorIsEmbedded()) {
cs.style &= ~(WS_POPUP | WS_CAPTION | WS_THICKFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
cs.style |= WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
cs.dwExStyle &= ~(WS_EX_APPWINDOW | WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE);
cs.dwExStyle |= WS_EX_CONTROLPARENT;
}
return TRUE;
}
@@ -140,17 +460,9 @@ BOOL MEMainFrame::PreCreateWindow(CREATESTRUCT& cs) {
* creates all of the spliter windows and registers all of the views with the document manager.
*/
BOOL MEMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) {
CCreateContext consoleContext;
consoleContext.m_pNewViewClass = RUNTIME_CLASS(ConsoleView);
m_consoleView = (ConsoleView*)CreateView(&consoleContext);
m_consoleView->ShowWindow(SW_HIDE);
m_tabs.Create(TCS_BOTTOM | TCS_FLATBUTTONS | WS_CHILD | WS_VISIBLE, CRect(0, 0, 0, 0), this, TAB_CONTROL);
m_tabs.InsertItem(0, "Editor");
m_tabs.InsertItem(1, "Console");
m_tabs.SetFont(materialEditorFont);
// The Material Editor now lives inside the Radiant tab host, so the old
// internal Editor/Console tab strip is gone. Console output remains routed
// through Doom's main console instead of a second nested console tab.
m_splitterWnd.CreateStatic(this, 2, 1);
@@ -249,6 +561,8 @@ BOOL MEMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
SetActiveView(m_materialTreeView);
MaterialEditorDark_ApplyToWindow(GetSafeHwnd());
return CFrameWnd::OnCreateClient(lpcs, pContext);
}
@@ -260,28 +574,20 @@ BOOL MEMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
int MEMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_ME_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
// Toolbars and status bars belong to the old standalone Material Editor.
// Keep only a compact menu strip when this frame is embedded in Radiant.
if (MaterialEditorIsEmbedded()) {
MEEmbeddedMenuBar_Create(this);
}
MaterialEditorDark_ApplyToWindow(GetSafeHwnd());
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
//Load the window placement from the options only for the legacy standalone frame.
if (!MaterialEditorIsEmbedded()) {
options.GetWindowPlacement ( "mainframe", m_hWnd );
}
//Load the window placement from the options
options.GetWindowPlacement ( "mainframe", m_hWnd );
return 0;
}
@@ -295,33 +601,49 @@ void MEMainFrame::OnDestroy() {
int cur;
int min;
m_splitterWnd.GetRowInfo(0, cur, min);
options.SetMaterialEditHeight(cur);
if (m_splitterWnd.GetSafeHwnd()) {
m_splitterWnd.GetRowInfo(0, cur, min);
options.SetMaterialEditHeight(cur);
}
m_editSplitter.GetColumnInfo(0, cur, min);
options.SetMaterialTreeWidth(cur);
if (m_editSplitter.GetSafeHwnd()) {
m_editSplitter.GetColumnInfo(0, cur, min);
options.SetMaterialTreeWidth(cur);
}
m_materialEditSplitter->GetColumnInfo(0, cur, min);
options.SetStageWidth(cur);
if (m_materialEditSplitter && m_materialEditSplitter->GetSafeHwnd()) {
m_materialEditSplitter->GetColumnInfo(0, cur, min);
options.SetStageWidth(cur);
}
m_previewSplitter.GetColumnInfo(0, cur, min);
options.SetPreviewPropertiesWidth(cur);
if (m_previewSplitter.GetSafeHwnd()) {
m_previewSplitter.GetColumnInfo(0, cur, min);
options.SetPreviewPropertiesWidth(cur);
}
if (m_materialPropertyView && m_materialPropertyView->GetSafeHwnd()) {
cur = m_materialPropertyView->GetPropertyTreeCtrl().GetColumn();
options.SetMaterialPropHeadingWidth(cur);
m_materialPropertyView->SaveSettings();
}
cur = m_materialPropertyView->GetPropertyTreeCtrl().GetColumn();
options.SetMaterialPropHeadingWidth(cur);
if (m_previewPropertyView && m_previewPropertyView->GetSafeHwnd()) {
cur = m_previewPropertyView->GetPropertyTreeCtrl().GetColumn();
options.SetPreviewPropHeadingWidth(cur);
}
cur = m_previewPropertyView->GetPropertyTreeCtrl().GetColumn();
options.SetPreviewPropHeadingWidth(cur);
options.SetWindowPlacement ( "mainframe", m_hWnd );
if (!MaterialEditorIsEmbedded()) {
options.SetWindowPlacement ( "mainframe", m_hWnd );
}
options.Save();
m_materialPropertyView->SaveSettings();
MEEmbeddedMenuBar_DestroyForParent(GetSafeHwnd());
MaterialDefManager::DestroyMaterialDefLists();
AfxGetApp()->ExitInstance();
if (!MaterialEditorIsEmbedded()) {
AfxGetApp()->ExitInstance();
}
}
/**
@@ -333,22 +655,22 @@ void MEMainFrame::OnSize(UINT nType, int cx, int cy)
{
CFrameWnd::OnSize(nType, cx, cy);
CRect statusRect;
m_wndStatusBar.GetWindowRect(statusRect);
if (!m_splitterWnd.GetSafeHwnd()) {
return;
}
CRect toolbarRect;
m_wndToolBar.GetWindowRect(toolbarRect);
int menuHeight = 0;
HWND hMenuBar = MEEmbeddedMenuBar_GetSafeHwnd();
if (MaterialEditorIsEmbedded() && hMenuBar) {
menuHeight = MEEmbeddedMenuBar_PreferredHeight();
::MoveWindow(hMenuBar, 0, 0, cx, menuHeight, TRUE);
}
CRect tabRect;
m_tabs.GetItemRect(0, tabRect);
int tabHeight = tabRect.Height()+5;
m_splitterWnd.MoveWindow(0, toolbarRect.Height(), cx, cy-statusRect.Height()-toolbarRect.Height()-tabHeight);
m_tabs.MoveWindow(0, cy-statusRect.Height()-tabHeight, cx, tabHeight);
m_consoleView->MoveWindow(0, toolbarRect.Height(), cx, cy-statusRect.Height()-toolbarRect.Height()-tabHeight);
int contentHeight = cy - menuHeight;
if (contentHeight < 0) {
contentHeight = 0;
}
m_splitterWnd.MoveWindow(0, menuHeight, cx, contentHeight);
}
/**
@@ -356,23 +678,9 @@ void MEMainFrame::OnSize(UINT nType, int cx, int cy)
* the appropriate windows.
*/
void MEMainFrame::OnTcnSelChange(NMHDR *pNMHDR, LRESULT *pResult) {
int sel = m_tabs.GetCurSel();
switch(sel) {
case 0:
m_splitterWnd.ShowWindow(SW_SHOW);
m_consoleView->ShowWindow(SW_HIDE);
break;
case 1:
m_splitterWnd.ShowWindow(SW_HIDE);
m_consoleView->ShowWindow(SW_SHOW);
CRect rect;
GetWindowRect(rect);
MoveWindow(rect);
break;
// The old nested Editor/Console tabs were removed for the integrated layout.
if (pResult) {
*pResult = 0;
}
}
@@ -381,6 +689,10 @@ void MEMainFrame::OnTcnSelChange(NMHDR *pNMHDR, LRESULT *pResult) {
* /todo BMatt Nerve: Need to warn the user if a file is modified.
*/
void MEMainFrame::OnFileExit() {
if (MaterialEditorIsEmbedded()) {
ShowWindow(SW_HIDE);
return;
}
PostMessage(WM_DESTROY, 0, 0);
}
@@ -871,7 +1183,11 @@ void MEMainFrame::OnEditRedoUpdate(CCmdUI *pCmdUI) {
*/
void MEMainFrame::OnViewIncludeFile() {
CMenu* mmenu = GetMenu();
CMenu* mmenu = MaterialEditorIsEmbedded() ? MEEmbeddedMenuBar_GetMenu() : GetMenu();
if (!mmenu) {
m_materialTreeView->InitializeMaterialList(true);
return;
}
UINT state = mmenu->GetMenuState(ID_VIEW_INCLUDEFILENAME, MF_BYCOMMAND);
ASSERT(state != 0xFFFFFFFF);
@@ -850,7 +850,7 @@ const char* MaterialDoc::GenerateSourceText() {
f.WriteFloatString("\n\n/*\n"
"\tGenerated by the Material Editor.\n"
"\tType 'materialeditor' at the console to launch the material editor.\n"
"\tGenerated from the embedded Material Editor tab.\n"
"*/\n" );
f.WriteFloatString("%s\n", name.c_str());
@@ -39,6 +39,9 @@ If you have questions concerning this license or the applicable additional terms
#define EDIT_TAB_CONTROL 0x2006
#define NAME_CONTROL 0x2007
extern void MaterialEditorDark_ApplyToWindow(HWND hWnd);
extern COLORREF MaterialEditorDark_PanelColor(void);
IMPLEMENT_DYNCREATE(MaterialEditView, CFormView)
BEGIN_MESSAGE_MAP(MaterialEditView, CFormView)
@@ -192,6 +195,10 @@ void MaterialEditView::OnInitialUpdate() {
m_textView.SetText("");
m_textView.SetReadOnly(true);
MaterialEditorDark_ApplyToWindow(GetSafeHwnd());
if (m_textView.GetSafeHwnd()) {
m_textView.SendMessage(EM_SETBKGNDCOLOR, 0, (LPARAM)MaterialEditorDark_PanelColor());
}
}
}
@@ -228,6 +235,8 @@ int MaterialEditView::OnCreate(LPCREATESTRUCT lpCreateStruct)
m_tabs.SetFont(materialEditorFont);
MaterialEditorDark_ApplyToWindow(GetSafeHwnd());
return 0;
}
@@ -31,85 +31,795 @@ If you have questions concerning this license or the applicable additional terms
#include "../../sys/win32/win_local.h"
#include "MaterialEditor.h"
#ifndef TVM_SETLINECOLOR
#define TVM_SETLINECOLOR (TV_FIRST + 40)
#endif
#include "MEMainFrame.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
MEMainFrame* meMainFrame = NULL;
CFont* materialEditorFont = NULL;
/**
* Initializes the material editor tool.
*/
void MaterialEditorInit( void ) {
static bool materialEditorInitialized = false;
static bool materialEditorEmbedded = false;
static CWnd* materialEditorEmbeddedParent = NULL;
static const COLORREF ME_DARK_BG = RGB(17, 19, 23);
static const COLORREF ME_DARK_PANEL = RGB(23, 26, 31);
static const COLORREF ME_DARK_MENU = RGB(28, 31, 36);
static const COLORREF ME_DARK_MENU_HOT = RGB(45, 50, 58);
static const COLORREF ME_DARK_BORDER = RGB(58, 64, 72);
static const COLORREF ME_DARK_TEXT = RGB(226, 232, 240);
static const COLORREF ME_DARK_TEXT_DISABLED = RGB(101, 110, 126);
static const COLORREF ME_DARK_ACCENT = RGB(87, 166, 255);
#ifndef BS_TYPEMASK
#define BS_TYPEMASK 0x0000000F
#endif
#ifndef TCM_GETITEMA
#define TCM_GETITEMA TCM_GETITEM
#endif
#ifndef TCITEMA
#define TCITEMA TCITEM
#endif
#ifndef TCM_INSERTITEMA
#define TCM_INSERTITEMA TCM_INSERTITEM
#endif
static const char* ME_DARK_BUTTON_OLDPROC = "IceTech.MaterialEditor.DarkButtonOldProc";
static const char* ME_DARK_STATIC_OLDPROC = "IceTech.MaterialEditor.DarkStaticOldProc";
static const char* ME_DARK_TAB_OLDPROC = "IceTech.MaterialEditor.DarkTabOldProc";
static const char* ME_DARK_RECOLOR_OLDPROC = "IceTech.MaterialEditor.DarkRecolorOldProc";
bool MaterialEditorOpenDockTab();
static HBRUSH MaterialEditorDarkPanelBrush() {
static HBRUSH hBrush = ::CreateSolidBrush(ME_DARK_PANEL);
return hBrush;
}
static void MaterialEditorDark_FillRect(HDC hDC, const RECT& rc, COLORREF color) {
HBRUSH brush = ::CreateSolidBrush(color);
::FillRect(hDC, &rc, brush);
::DeleteObject(brush);
}
static void MaterialEditorDark_FrameRect(HDC hDC, const RECT& rc, COLORREF color) {
HBRUSH brush = ::CreateSolidBrush(color);
::FrameRect(hDC, &rc, brush);
::DeleteObject(brush);
}
static void MaterialEditorDark_ApplyNativeTheme(HWND hWnd) {
if (!hWnd) {
return;
}
typedef HRESULT (WINAPI *SetWindowThemeProc)(HWND, LPCWSTR, LPCWSTR);
typedef BOOL (WINAPI *AllowDarkModeForWindowProc)(HWND, BOOL);
static HMODULE hUxTheme = ::LoadLibraryA("uxtheme.dll");
static SetWindowThemeProc pSetWindowTheme = hUxTheme ? (SetWindowThemeProc)::GetProcAddress(hUxTheme, "SetWindowTheme") : NULL;
static AllowDarkModeForWindowProc pAllowDarkModeForWindow = hUxTheme ? (AllowDarkModeForWindowProc)::GetProcAddress(hUxTheme, MAKEINTRESOURCEA(133)) : NULL;
if (pAllowDarkModeForWindow) {
pAllowDarkModeForWindow(hWnd, TRUE);
}
if (pSetWindowTheme) {
pSetWindowTheme(hWnd, L"DarkMode_Explorer", NULL);
}
::SendMessage(hWnd, WM_THEMECHANGED, 0, 0);
}
static void MaterialEditorDark_DrawButton(HWND hWnd, HDC hDC) {
RECT rc;
::GetClientRect(hWnd, &rc);
const UINT style = (UINT)::GetWindowLong(hWnd, GWL_STYLE);
const UINT type = style & BS_TYPEMASK;
const bool isCheck = (type == BS_CHECKBOX || type == BS_AUTOCHECKBOX || type == BS_3STATE || type == BS_AUTO3STATE);
const bool enabled = ::IsWindowEnabled(hWnd) ? true : false;
const bool pushed = (::SendMessage(hWnd, BM_GETSTATE, 0, 0) & BST_PUSHED) != 0;
const bool checked = (::SendMessage(hWnd, BM_GETCHECK, 0, 0) == BST_CHECKED);
char text[256];
text[0] = '\0';
::GetWindowTextA(hWnd, text, sizeof(text));
HFONT font = (HFONT)::SendMessage(hWnd, WM_GETFONT, 0, 0);
HFONT oldFont = font ? (HFONT)::SelectObject(hDC, font) : NULL;
::SetBkMode(hDC, TRANSPARENT);
::SetTextColor(hDC, enabled ? ME_DARK_TEXT : ME_DARK_TEXT_DISABLED);
if (isCheck) {
MaterialEditorDark_FillRect(hDC, rc, ME_DARK_PANEL);
RECT box = rc;
box.left += 3;
box.right = box.left + 14;
box.top += max(0, (rc.bottom - rc.top - 14) / 2);
box.bottom = box.top + 14;
MaterialEditorDark_FillRect(hDC, box, RGB(14, 16, 20));
MaterialEditorDark_FrameRect(hDC, box, checked ? ME_DARK_ACCENT : ME_DARK_BORDER);
if (checked) {
HPEN pen = ::CreatePen(PS_SOLID, 2, ME_DARK_ACCENT);
HPEN oldPen = (HPEN)::SelectObject(hDC, pen);
::MoveToEx(hDC, box.left + 3, box.top + 7, NULL);
::LineTo(hDC, box.left + 6, box.top + 10);
::LineTo(hDC, box.right - 3, box.top + 3);
::SelectObject(hDC, oldPen);
::DeleteObject(pen);
}
RECT textRect = rc;
textRect.left = box.right + 7;
::DrawTextA(hDC, text, -1, &textRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
}
else {
COLORREF face = pushed ? RGB(22, 25, 30) : RGB(31, 35, 41);
MaterialEditorDark_FillRect(hDC, rc, face);
MaterialEditorDark_FrameRect(hDC, rc, enabled ? ME_DARK_BORDER : RGB(39, 44, 52));
RECT textRect = rc;
if (pushed) {
::OffsetRect(&textRect, 1, 1);
}
::DrawTextA(hDC, text, -1, &textRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
}
if (oldFont) {
::SelectObject(hDC, oldFont);
}
}
static LRESULT CALLBACK MaterialEditorDarkButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
WNDPROC oldProc = (WNDPROC)::GetPropA(hWnd, ME_DARK_BUTTON_OLDPROC);
if (!oldProc) {
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
switch (uMsg) {
case WM_ERASEBKGND:
return 1;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC = ::BeginPaint(hWnd, &ps);
MaterialEditorDark_DrawButton(hWnd, hDC);
::EndPaint(hWnd, &ps);
return 0;
}
case WM_PRINTCLIENT:
MaterialEditorDark_DrawButton(hWnd, (HDC)wParam);
return 0;
case WM_MOUSEMOVE:
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_ENABLE:
case WM_SETTEXT:
case BM_SETCHECK:
case BM_SETSTATE:
{
LRESULT result = ::CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam);
::InvalidateRect(hWnd, NULL, FALSE);
return result;
}
case WM_NCDESTROY:
{
::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)oldProc);
::RemovePropA(hWnd, ME_DARK_BUTTON_OLDPROC);
return ::CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam);
}
}
return ::CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam);
}
static void MaterialEditorDark_SubclassButton(HWND hWnd) {
if (!hWnd || ::GetPropA(hWnd, ME_DARK_BUTTON_OLDPROC)) {
return;
}
WNDPROC oldProc = (WNDPROC)::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
::SetPropA(hWnd, ME_DARK_BUTTON_OLDPROC, (HANDLE)oldProc);
::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)MaterialEditorDarkButtonProc);
::InvalidateRect(hWnd, NULL, TRUE);
}
static void MaterialEditorDark_DrawStatic(HWND hWnd, HDC hDC) {
RECT rc;
::GetClientRect(hWnd, &rc);
MaterialEditorDark_FillRect(hDC, rc, ME_DARK_PANEL);
char text[256];
text[0] = '\0';
::GetWindowTextA(hWnd, text, sizeof(text));
HFONT font = (HFONT)::SendMessage(hWnd, WM_GETFONT, 0, 0);
HFONT oldFont = font ? (HFONT)::SelectObject(hDC, font) : NULL;
::SetBkMode(hDC, TRANSPARENT);
::SetTextColor(hDC, ME_DARK_TEXT);
::DrawTextA(hDC, text, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
if (oldFont) {
::SelectObject(hDC, oldFont);
}
}
static LRESULT CALLBACK MaterialEditorDarkStaticProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
WNDPROC oldProc = (WNDPROC)::GetPropA(hWnd, ME_DARK_STATIC_OLDPROC);
if (!oldProc) {
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
if (uMsg == WM_PAINT) {
PAINTSTRUCT ps;
HDC hDC = ::BeginPaint(hWnd, &ps);
MaterialEditorDark_DrawStatic(hWnd, hDC);
::EndPaint(hWnd, &ps);
return 0;
}
if (uMsg == WM_ERASEBKGND) {
return 1;
}
if (uMsg == WM_NCDESTROY) {
::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)oldProc);
::RemovePropA(hWnd, ME_DARK_STATIC_OLDPROC);
return ::CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam);
}
return ::CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam);
}
static void MaterialEditorDark_SubclassStatic(HWND hWnd) {
if (!hWnd || ::GetPropA(hWnd, ME_DARK_STATIC_OLDPROC)) {
return;
}
WNDPROC oldProc = (WNDPROC)::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
::SetPropA(hWnd, ME_DARK_STATIC_OLDPROC, (HANDLE)oldProc);
::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)MaterialEditorDarkStaticProc);
}
static void MaterialEditorDark_DrawTabControl(HWND hWnd, HDC hDC) {
RECT client;
::GetClientRect(hWnd, &client);
MaterialEditorDark_FillRect(hDC, client, ME_DARK_BG);
HFONT font = (HFONT)::SendMessage(hWnd, WM_GETFONT, 0, 0);
HFONT oldFont = font ? (HFONT)::SelectObject(hDC, font) : NULL;
::SetBkMode(hDC, TRANSPARENT);
const int count = (int)::SendMessage(hWnd, TCM_GETITEMCOUNT, 0, 0);
const int sel = (int)::SendMessage(hWnd, TCM_GETCURSEL, 0, 0);
for (int i = 0; i < count; i++) {
RECT item;
if (!::SendMessage(hWnd, TCM_GETITEMRECT, (WPARAM)i, (LPARAM)&item)) {
continue;
}
const bool active = (i == sel);
RECT fill = item;
fill.bottom += active ? 2 : 0;
MaterialEditorDark_FillRect(hDC, fill, active ? ME_DARK_PANEL : ME_DARK_MENU);
MaterialEditorDark_FrameRect(hDC, fill, active ? ME_DARK_ACCENT : ME_DARK_BORDER);
char text[128];
text[0] = '\0';
TCITEMA ti;
memset(&ti, 0, sizeof(ti));
ti.mask = TCIF_TEXT;
ti.pszText = text;
ti.cchTextMax = sizeof(text);
::SendMessageA(hWnd, TCM_GETITEMA, (WPARAM)i, (LPARAM)&ti);
::SetTextColor(hDC, active ? RGB(245, 249, 255) : ME_DARK_TEXT);
::DrawTextA(hDC, text, -1, &item, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
}
RECT line = client;
line.top = client.bottom - 1;
MaterialEditorDark_FillRect(hDC, line, ME_DARK_BORDER);
if (oldFont) {
::SelectObject(hDC, oldFont);
}
}
static LRESULT CALLBACK MaterialEditorDarkTabProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
WNDPROC oldProc = (WNDPROC)::GetPropA(hWnd, ME_DARK_TAB_OLDPROC);
if (!oldProc) {
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
switch (uMsg) {
case WM_ERASEBKGND:
return 1;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC = ::BeginPaint(hWnd, &ps);
MaterialEditorDark_DrawTabControl(hWnd, hDC);
::EndPaint(hWnd, &ps);
return 0;
}
case WM_PRINTCLIENT:
MaterialEditorDark_DrawTabControl(hWnd, (HDC)wParam);
return 0;
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case TCM_INSERTITEMA:
case TCM_DELETEITEM:
case TCM_DELETEALLITEMS:
case TCM_SETCURSEL:
{
LRESULT result = ::CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam);
::InvalidateRect(hWnd, NULL, FALSE);
return result;
}
case WM_NCDESTROY:
{
::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)oldProc);
::RemovePropA(hWnd, ME_DARK_TAB_OLDPROC);
return ::CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam);
}
}
return ::CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam);
}
static void MaterialEditorDark_SubclassTab(HWND hWnd) {
if (!hWnd || ::GetPropA(hWnd, ME_DARK_TAB_OLDPROC)) {
return;
}
WNDPROC oldProc = (WNDPROC)::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
::SetPropA(hWnd, ME_DARK_TAB_OLDPROC, (HANDLE)oldProc);
::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)MaterialEditorDarkTabProc);
::InvalidateRect(hWnd, NULL, TRUE);
}
static void MaterialEditorDark_SetDIBPixel(BYTE *pixel, COLORREF color) {
pixel[0] = GetBValue(color);
pixel[1] = GetGValue(color);
pixel[2] = GetRValue(color);
}
static void MaterialEditorDark_RecolorPropTreeWindow(HWND hWnd) {
RECT rc;
::GetClientRect(hWnd, &rc);
const int width = rc.right - rc.left;
const int height = rc.bottom - rc.top;
if (width <= 0 || height <= 0) {
return;
}
HDC hDC = ::GetDC(hWnd);
if (!hDC) {
return;
}
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = -height;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
void *bits = NULL;
HBITMAP hBitmap = ::CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, &bits, NULL, 0);
if (!hBitmap || !bits) {
if (hBitmap) {
::DeleteObject(hBitmap);
}
::ReleaseDC(hWnd, hDC);
return;
}
HDC memDC = ::CreateCompatibleDC(hDC);
HBITMAP oldBitmap = (HBITMAP)::SelectObject(memDC, hBitmap);
::BitBlt(memDC, 0, 0, width, height, hDC, 0, 0, SRCCOPY);
BYTE *data = (BYTE *)bits;
const int pixelCount = width * height;
for (int i = 0; i < pixelCount; i++) {
BYTE *pixel = data + i * 4;
const int b = pixel[0];
const int g = pixel[1];
const int r = pixel[2];
const int maxColor = max(r, max(g, b));
const int minColor = min(r, min(g, b));
// Only remap neutral system-color pixels. Non-gray pixels such as the
// preview light color swatch are left alone as much as possible.
if (maxColor - minColor <= 18) {
if (maxColor >= 245) {
MaterialEditorDark_SetDIBPixel(pixel, ME_DARK_PANEL);
} else if (maxColor >= 215) {
MaterialEditorDark_SetDIBPixel(pixel, RGB(31, 35, 41));
} else if (maxColor >= 165) {
MaterialEditorDark_SetDIBPixel(pixel, ME_DARK_MENU_HOT);
} else if (maxColor <= 35) {
MaterialEditorDark_SetDIBPixel(pixel, ME_DARK_TEXT);
} else if (maxColor <= 110) {
MaterialEditorDark_SetDIBPixel(pixel, ME_DARK_TEXT_DISABLED);
}
} else if (b > 130 && g > 70 && r < 120) {
MaterialEditorDark_SetDIBPixel(pixel, ME_DARK_ACCENT);
}
}
::BitBlt(hDC, 0, 0, width, height, memDC, 0, 0, SRCCOPY);
::SelectObject(memDC, oldBitmap);
::DeleteDC(memDC);
::DeleteObject(hBitmap);
::ReleaseDC(hWnd, hDC);
}
static bool MaterialEditorDark_IsPropTreePart(HWND hWnd) {
if (!hWnd) {
return false;
}
if (::GetDlgCtrlID(hWnd) == IDC_PROPERTYTREE) {
return true;
}
HWND parent = ::GetParent(hWnd);
if (parent && ::GetDlgCtrlID(parent) == IDC_PROPERTYTREE) {
return true;
}
HWND grandParent = parent ? ::GetParent(parent) : NULL;
if (grandParent && ::GetDlgCtrlID(grandParent) == IDC_PROPERTYTREE) {
return true;
}
return false;
}
static bool MaterialEditorDark_ShouldRecolorClass(const char *className) {
if (!className || !className[0]) {
return true;
}
if (!_stricmp(className, "Edit") || !_stricmp(className, "RICHEDIT") || !_stricmp(className, "RichEdit20A") || !_stricmp(className, "RichEdit20W")) {
return false;
}
if (!_stricmp(className, "Button") || !_stricmp(className, "Static") || !_stricmp(className, "ComboBox")) {
return false;
}
if (!_stricmp(className, "SysTreeView32") || !_stricmp(className, "SysListView32") || !_stricmp(className, "SysTabControl32")) {
return false;
}
return true;
}
static LRESULT CALLBACK MaterialEditorDarkRecolorProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
WNDPROC oldProc = (WNDPROC)::GetPropA(hWnd, ME_DARK_RECOLOR_OLDPROC);
if (!oldProc) {
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
switch (uMsg) {
case WM_ERASEBKGND:
{
RECT rc;
::GetClientRect(hWnd, &rc);
MaterialEditorDark_FillRect((HDC)wParam, rc, ME_DARK_PANEL);
return 1;
}
case WM_PAINT:
{
LRESULT result = ::CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam);
MaterialEditorDark_RecolorPropTreeWindow(hWnd);
return result;
}
case WM_PRINTCLIENT:
{
LRESULT result = ::CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam);
return result;
}
case WM_SIZE:
case WM_ENABLE:
case WM_SETTEXT:
{
LRESULT result = ::CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam);
::InvalidateRect(hWnd, NULL, TRUE);
return result;
}
case WM_NCDESTROY:
{
::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)oldProc);
::RemovePropA(hWnd, ME_DARK_RECOLOR_OLDPROC);
return ::CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam);
}
}
return ::CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam);
}
static void MaterialEditorDark_SubclassRecolor(HWND hWnd) {
if (!hWnd || ::GetPropA(hWnd, ME_DARK_RECOLOR_OLDPROC)) {
return;
}
WNDPROC oldProc = (WNDPROC)::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
::SetPropA(hWnd, ME_DARK_RECOLOR_OLDPROC, (HANDLE)oldProc);
::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)MaterialEditorDarkRecolorProc);
::InvalidateRect(hWnd, NULL, TRUE);
}
static void MaterialEditorDark_ApplySingleWindow(HWND hWnd) {
if (!hWnd || !::IsWindow(hWnd)) {
return;
}
MaterialEditorDark_ApplyNativeTheme(hWnd);
char className[128];
className[0] = '\0';
::GetClassNameA(hWnd, className, sizeof(className));
if (MaterialEditorDark_IsPropTreePart(hWnd) && MaterialEditorDark_ShouldRecolorClass(className)) {
MaterialEditorDark_SubclassRecolor(hWnd);
}
if (!_stricmp(className, "SysTreeView32")) {
::SendMessage(hWnd, TVM_SETBKCOLOR, 0, (LPARAM)ME_DARK_PANEL);
::SendMessage(hWnd, TVM_SETTEXTCOLOR, 0, (LPARAM)ME_DARK_TEXT);
::SendMessage(hWnd, TVM_SETLINECOLOR, 0, (LPARAM)ME_DARK_BORDER);
}
else if (!_stricmp(className, "SysListView32")) {
::SendMessage(hWnd, LVM_SETBKCOLOR, 0, (LPARAM)ME_DARK_PANEL);
::SendMessage(hWnd, LVM_SETTEXTBKCOLOR, 0, (LPARAM)ME_DARK_PANEL);
::SendMessage(hWnd, LVM_SETTEXTCOLOR, 0, (LPARAM)ME_DARK_TEXT);
::SendMessage(hWnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
}
else if (!_stricmp(className, "SysTabControl32")) {
MaterialEditorDark_SubclassTab(hWnd);
}
else if (!_stricmp(className, "Button")) {
MaterialEditorDark_SubclassButton(hWnd);
}
else if (!_stricmp(className, "Static")) {
MaterialEditorDark_SubclassStatic(hWnd);
}
else if (!_stricmp(className, "Edit") || !_stricmp(className, "RICHEDIT") || !_stricmp(className, "RichEdit20A") || !_stricmp(className, "RichEdit20W")) {
::SendMessage(hWnd, EM_SETBKGNDCOLOR, 0, (LPARAM)ME_DARK_PANEL);
CHARFORMAT cf;
memset(&cf, 0, sizeof(cf));
cf.cbSize = sizeof(cf);
cf.dwMask = CFM_COLOR;
cf.crTextColor = ME_DARK_TEXT;
::SendMessage(hWnd, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);
}
else if (!_stricmp(className, "ComboBox")) {
::SendMessage(hWnd, CB_SETDROPPEDWIDTH, 260, 0);
}
}
static BOOL CALLBACK MaterialEditorDark_EnumChildProc(HWND hWnd, LPARAM lParam) {
MaterialEditorDark_ApplySingleWindow(hWnd);
return TRUE;
}
void MaterialEditorDark_ApplyToWindow(HWND hWnd) {
if (!hWnd || !::IsWindow(hWnd)) {
return;
}
MaterialEditorDark_ApplySingleWindow(hWnd);
::EnumChildWindows(hWnd, MaterialEditorDark_EnumChildProc, 0);
::InvalidateRect(hWnd, NULL, TRUE);
}
COLORREF MaterialEditorDark_BackgroundColor() {
return ME_DARK_BG;
}
COLORREF MaterialEditorDark_PanelColor() {
return ME_DARK_PANEL;
}
COLORREF MaterialEditorDark_TextColor() {
return ME_DARK_TEXT;
}
COLORREF MaterialEditorDark_AccentColor() {
return ME_DARK_ACCENT;
}
COLORREF MaterialEditorDark_BorderColor() {
return ME_DARK_BORDER;
}
static bool MaterialEditorInitCommon( void ) {
if (materialEditorInitialized) {
return true;
}
InitPropTree(win32.hInstance);
com_editors = EDITOR_MATERIAL;
com_editors |= EDITOR_MATERIAL;
Sys_GrabMouseCursor( false );
Sys_GrabMouseCursor(false);
InitAfx();
InitCommonControls();
// Initialize OLE libraries
if (!AfxOleInit())
{
return;
// Initialize OLE libraries once for the embedded editor controls.
if (!AfxOleInit()) {
return false;
}
AfxEnableControlContainer();
NONCLIENTMETRICS info;
info.cbSize = sizeof(info);
::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
LOGFONT lf;
memset(&lf, 0, sizeof (LOGFONT));
memset(&lf, 0, sizeof(LOGFONT));
CWindowDC dc(NULL);
lf.lfCharSet = (BYTE)GetTextCharsetInfo(dc.GetSafeHdc(), NULL, 0);
lf.lfHeight = info.lfMenuFont.lfHeight;
lf.lfWeight = info.lfMenuFont.lfWeight;
lf.lfItalic = info.lfMenuFont.lfItalic;
// check if we should use system font
_tcscpy(lf.lfFaceName, info.lfMenuFont.lfFaceName);
materialEditorFont = new CFont;
materialEditorFont->CreateFontIndirect(&lf);
materialEditorInitialized = true;
return true;
}
// To create the main window, this code creates a new frame window
// object and then sets it as the application's main window object
meMainFrame = new MEMainFrame;
// create and load the frame with its resources
meMainFrame->LoadFrame(IDR_ME_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, NULL);
static void MaterialEditorNormalizeEmbeddedFrameStyle( void ) {
if (!meMainFrame || !meMainFrame->GetSafeHwnd()) {
return;
}
HWND hWnd = meMainFrame->GetSafeHwnd();
LONG style = ::GetWindowLong(hWnd, 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(hWnd, GWL_STYLE, style);
// hide the doom window by default
::ShowWindow ( win32.hWnd, SW_HIDE );
// The one and only window has been initialized, so show and update it
LONG exStyle = ::GetWindowLong(hWnd, GWL_EXSTYLE);
exStyle &= ~(WS_EX_APPWINDOW | WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE);
exStyle |= WS_EX_CONTROLPARENT;
::SetWindowLong(hWnd, GWL_EXSTYLE, exStyle);
::SetWindowPos(hWnd, NULL, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
}
/**
* Creates or returns the embedded material editor frame hosted by the Radiant tab control.
*/
HWND MaterialEditorCreateEmbeddedWindow(CWnd *parent, const RECT& rect) {
if (!parent || !parent->GetSafeHwnd()) {
return NULL;
}
if (!MaterialEditorInitCommon()) {
return NULL;
}
materialEditorEmbedded = true;
materialEditorEmbeddedParent = parent;
if (!meMainFrame) {
meMainFrame = new MEMainFrame;
if (!meMainFrame->LoadFrame(IDR_ME_MAINFRAME, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, parent, NULL)) {
delete meMainFrame;
meMainFrame = NULL;
return NULL;
}
} else if (meMainFrame->GetSafeHwnd() && ::GetParent(meMainFrame->GetSafeHwnd()) != parent->GetSafeHwnd()) {
meMainFrame->SetParent(parent);
}
MaterialEditorNormalizeEmbeddedFrameStyle();
meMainFrame->MoveWindow(&rect, TRUE);
meMainFrame->ShowWindow(SW_HIDE);
MaterialEditorDark_ApplyToWindow(meMainFrame->GetSafeHwnd());
return meMainFrame->GetSafeHwnd();
}
void MaterialEditorMoveEmbeddedWindow(const RECT& rect) {
if (meMainFrame && meMainFrame->GetSafeHwnd()) {
meMainFrame->MoveWindow(&rect, TRUE);
}
}
void MaterialEditorShowEmbeddedWindow(BOOL show) {
if (!meMainFrame || !meMainFrame->GetSafeHwnd()) {
return;
}
meMainFrame->ShowWindow(show ? SW_SHOW : SW_HIDE);
if (show) {
com_editors |= EDITOR_MATERIAL;
MaterialEditorDark_ApplyToWindow(meMainFrame->GetSafeHwnd());
meMainFrame->SetActiveWindow();
meMainFrame->SetFocus();
} else if (materialEditorEmbedded) {
com_editors &= ~EDITOR_MATERIAL;
}
}
void MaterialEditorFocusEmbeddedWindow( void ) {
if (meMainFrame && meMainFrame->GetSafeHwnd()) {
meMainFrame->SetFocus();
}
}
BOOL MaterialEditorPreTranslateEmbeddedMessage(MSG *pMsg) {
if (meMainFrame && meMainFrame->GetSafeHwnd()) {
return meMainFrame->PreTranslateMessage(pMsg);
}
return FALSE;
}
BOOL MaterialEditorEmbeddedOnCommand(WPARAM wParam, LPARAM lParam) {
if (meMainFrame && meMainFrame->GetSafeHwnd()) {
return (BOOL)meMainFrame->SendMessage(WM_COMMAND, wParam, lParam);
}
return FALSE;
}
BOOL MaterialEditorEmbeddedOnNotify(WPARAM wParam, LPARAM lParam, LRESULT *pResult) {
if (meMainFrame && meMainFrame->GetSafeHwnd()) {
LRESULT result = meMainFrame->SendMessage(WM_NOTIFY, wParam, lParam);
if (pResult) {
*pResult = result;
}
return result != 0;
}
return FALSE;
}
BOOL MaterialEditorEmbeddedOnCmdMsg(UINT nID, int nCode, void *pExtra, AFX_CMDHANDLERINFO *pHandlerInfo) {
if (meMainFrame && meMainFrame->GetSafeHwnd()) {
return meMainFrame->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
return FALSE;
}
bool MaterialEditorIsEmbedded( void ) {
return materialEditorEmbedded;
}
/**
* Initializes the material editor tool. In the integrated editor this selects the
* Material Editor tab instead of creating a separate top-level tool window.
*/
void MaterialEditorInit( void ) {
if (MaterialEditorOpenDockTab()) {
return;
}
if (!MaterialEditorInitCommon()) {
return;
}
materialEditorEmbedded = false;
if (!meMainFrame) {
meMainFrame = new MEMainFrame;
meMainFrame->LoadFrame(IDR_ME_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, NULL);
}
// Standalone fallback is kept for tools launched before the Radiant tab host exists.
meMainFrame->ShowWindow(SW_SHOW);
meMainFrame->UpdateWindow();
MaterialEditorDark_ApplyToWindow(meMainFrame->GetSafeHwnd());
}
/**
* Called every frame by the doom engine to allow the material editor to process messages.
*/
void MaterialEditorRun( void ) {
MSG *msg = AfxGetCurrentMessage();
while( ::PeekMessage(msg, NULL, NULL, NULL, PM_NOREMOVE) ) {
// pump message
if ( !AfxGetApp()->PumpMessage() ) {
}
}
@@ -119,27 +829,32 @@ void MaterialEditorRun( void ) {
* Called by the doom engine when the material editor needs to be destroyed.
*/
void MaterialEditorShutdown( void ) {
delete meMainFrame;
meMainFrame = NULL;
delete materialEditorFont;
materialEditorFont = NULL;
meMainFrame = NULL;
materialEditorInitialized = false;
materialEditorEmbedded = false;
materialEditorEmbeddedParent = NULL;
com_editors &= ~EDITOR_MATERIAL;
}
/**
* Allows the doom engine to reflect console output to the material editors console.
*/
void MaterialEditorPrintConsole( const char *msg ) {
if(com_editors & EDITOR_MATERIAL)
if ((com_editors & EDITOR_MATERIAL) && meMainFrame) {
meMainFrame->PrintConsoleMessage(msg);
}
}
/**
* Returns the handle to the main Material Editor Window
*/
HWND GetMaterialEditorWindow() {
return meMainFrame->GetSafeHwnd();
return meMainFrame ? meMainFrame->GetSafeHwnd() : NULL;
}
/**
@@ -31,6 +31,8 @@ If you have questions concerning this license or the applicable additional terms
#include "MaterialPreviewPropView.h"
extern void MaterialEditorDark_ApplyToWindow(HWND hWnd);
// MaterialPropTreeView
@@ -115,6 +117,7 @@ void MaterialPreviewPropView::AddLight( void ) {
if ( materialPreview ) {
materialPreview->OnAddLight();
}
MaterialEditorDark_ApplyToWindow(GetSafeHwnd());
}
//Create sample data for the preview properties
@@ -223,6 +226,7 @@ void MaterialPreviewPropView::InitializePropTree( void ) {
pRoot->SetInfoText(_T(""));
AddLight();
MaterialEditorDark_ApplyToWindow(GetSafeHwnd());
}
// MaterialPreviewPropView drawing
@@ -33,6 +33,8 @@ If you have questions concerning this license or the applicable additional terms
#include "../radiant/QE3.H"
#include "MaterialPreviewView.h"
extern void MaterialEditorDark_ApplyToWindow(HWND hWnd);
// MaterialPreviewView
IMPLEMENT_DYNCREATE(MaterialPreviewView, CView)
@@ -88,6 +90,7 @@ int MaterialPreviewView::OnCreate(LPCREATESTRUCT lpCreateStruct)
renderWindow.setDrawable( &renderedView );
renderWindow.SetWindowPos(NULL, 0, 0, rc.Width(), rc.Height(), SWP_SHOWWINDOW);
MaterialEditorDark_ApplyToWindow(GetSafeHwnd());
return 0;
}
@@ -536,7 +539,7 @@ void idGLDrawableView::draw(int x, int y, int w, int h) {
drawLights( &refdef );
}
renderSystem->EndFrame( NULL, NULL );
renderSystem->EndFrame( NULL, NULL, false );
world->DebugClearLines( refdef.time );
@@ -32,6 +32,8 @@ If you have questions concerning this license or the applicable additional terms
#define PROP_TREE_VIEW "PropTreeView"
extern void MaterialEditorDark_ApplyToWindow(HWND hWnd);
IMPLEMENT_DYNCREATE(MaterialPropTreeView, CPropTreeView)
@@ -113,6 +115,7 @@ void MaterialPropTreeView::SetPropertyListType(int listType, int stageNum) {
}
RefreshProperties();
MaterialEditorDark_ApplyToWindow(GetSafeHwnd());
}
/**
@@ -239,6 +242,7 @@ void MaterialPropTreeView::RefreshProperties() {
}
}
MaterialEditorDark_ApplyToWindow(GetSafeHwnd());
Invalidate();
}
@@ -30,6 +30,10 @@ If you have questions concerning this license or the applicable additional terms
#include "MaterialTreeView.h"
#ifndef TVM_SETLINECOLOR
#define TVM_SETLINECOLOR (TV_FIRST + 40)
#endif
#define IMAGE_FOLDER 0
#define IMAGE_FILE 1
#define IMAGE_MATERIAL 2
@@ -43,6 +47,11 @@ If you have questions concerning this license or the applicable additional terms
#define MSG_RENAME_FOLDER_COMPLETE (WM_USER + 1000)
#define MSG_RENAME_MATERIAL_COMPLETE (WM_USER + 1001)
extern void MaterialEditorDark_ApplyToWindow(HWND hWnd);
extern COLORREF MaterialEditorDark_PanelColor(void);
extern COLORREF MaterialEditorDark_TextColor(void);
extern COLORREF MaterialEditorDark_BorderColor(void);
IMPLEMENT_DYNCREATE(MaterialTreeView, CTreeView)
BEGIN_MESSAGE_MAP(MaterialTreeView, CTreeView)
@@ -706,6 +715,10 @@ int MaterialTreeView::OnCreate(LPCREATESTRUCT lpCreateStruct) {
CTreeCtrl& tree = GetTreeCtrl();
m_image.Create(IDB_ME_TREEBITMAP, 16, 1, RGB(255, 255, 255));
tree.SetImageList(&m_image, TVSIL_NORMAL);
tree.SetBkColor(MaterialEditorDark_PanelColor());
tree.SetTextColor(MaterialEditorDark_TextColor());
tree.SendMessage(TVM_SETLINECOLOR, 0, (LPARAM)MaterialEditorDark_BorderColor());
MaterialEditorDark_ApplyToWindow(GetSafeHwnd());
return 0;
}
@@ -30,6 +30,8 @@ If you have questions concerning this license or the applicable additional terms
#include "StageView.h"
extern void MaterialEditorDark_ApplyToWindow(HWND hWnd);
IMPLEMENT_DYNCREATE(StageView, ToggleListView)
BEGIN_MESSAGE_MAP(StageView, ToggleListView)
@@ -312,6 +314,7 @@ int StageView::OnCreate(LPCREATESTRUCT lpCreateStruct) {
return -1;
SetToggleIcons(MAKEINTRESOURCE(IDI_ME_DISABLED_ICON), MAKEINTRESOURCE(IDI_ME_ON_ICON), MAKEINTRESOURCE(IDI_ME_OFF_ICON));
MaterialEditorDark_ApplyToWindow(GetSafeHwnd());
return 0;
}
@@ -33,6 +33,12 @@ If you have questions concerning this license or the applicable additional terms
#define TOGGLELIST_ITEMHEIGHT 22
#define TEXT_OFFSET 6
extern COLORREF MaterialEditorDark_BackgroundColor(void);
extern COLORREF MaterialEditorDark_PanelColor(void);
extern COLORREF MaterialEditorDark_TextColor(void);
extern COLORREF MaterialEditorDark_AccentColor(void);
extern COLORREF MaterialEditorDark_BorderColor(void);
IMPLEMENT_DYNCREATE(ToggleListView, CListView)
@@ -130,6 +136,9 @@ int ToggleListView::OnCreate(LPCREATESTRUCT lpCreateStruct) {
CListCtrl& list = GetListCtrl();
list.SetExtendedStyle(LVS_EX_FULLROWSELECT);
list.SetBkColor(MaterialEditorDark_PanelColor());
list.SetTextBkColor(MaterialEditorDark_PanelColor());
list.SetTextColor(MaterialEditorDark_TextColor());
//Turn off the horizontal scroll bar
//Todo: Figure out why the damn scroll bar pops up
@@ -238,12 +247,15 @@ void ToggleListView::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) {
FrameRect ( lpDrawItemStruct->hDC, &rDraw, (HBRUSH)GetStockObject ( BLACK_BRUSH ) );
rDraw.right --;
FillRect ( lpDrawItemStruct->hDC, &rDraw, GetSysColorBrush ( COLOR_3DFACE ) );
HBRUSH panelBrush = ::CreateSolidBrush(MaterialEditorDark_PanelColor());
HBRUSH borderBrush = ::CreateSolidBrush(MaterialEditorDark_BorderColor());
HBRUSH accentBrush = ::CreateSolidBrush(MaterialEditorDark_AccentColor());
FillRect ( lpDrawItemStruct->hDC, &rDraw, panelBrush );
Draw3dRect ( lpDrawItemStruct->hDC, &rDraw, GetSysColorBrush ( COLOR_3DHILIGHT ), GetSysColorBrush ( COLOR_3DSHADOW ) );
Draw3dRect ( lpDrawItemStruct->hDC, &rDraw, accentBrush, borderBrush );
InflateRect ( &rDraw, -3, -3 );
Draw3dRect ( lpDrawItemStruct->hDC, &rDraw, GetSysColorBrush ( COLOR_3DSHADOW ), GetSysColorBrush ( COLOR_3DHILIGHT ) );
Draw3dRect ( lpDrawItemStruct->hDC, &rDraw, borderBrush, accentBrush );
switch(GetToggleState(lvi.iItem)) {
case TOGGLE_STATE_DISABLED:
@@ -267,18 +279,20 @@ void ToggleListView::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) {
rDraw.left += TOGGLELIST_ITEMHEIGHT;
rDraw.left += 1;
if ( lpDrawItemStruct->itemState & ODS_SELECTED ) {
FillRect ( lpDrawItemStruct->hDC, &rDraw, GetSysColorBrush ( COLOR_HIGHLIGHT ) );
} else {
FillRect ( lpDrawItemStruct->hDC, &rDraw, GetSysColorBrush ( COLOR_WINDOW ) );
}
HBRUSH itemBrush = ::CreateSolidBrush((lpDrawItemStruct->itemState & ODS_SELECTED) ? RGB(37, 99, 160) : MaterialEditorDark_PanelColor());
FillRect ( lpDrawItemStruct->hDC, &rDraw, itemBrush );
::DeleteObject(itemBrush);
rDraw.left += TEXT_OFFSET;
int colorIndex = ( (lpDrawItemStruct->itemState & ODS_SELECTED ) ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT );
SetTextColor ( lpDrawItemStruct->hDC, GetSysColor ( colorIndex ) );
SetBkMode(lpDrawItemStruct->hDC, TRANSPARENT);
SetTextColor ( lpDrawItemStruct->hDC, MaterialEditorDark_TextColor() );
DrawText ( lpDrawItemStruct->hDC, szBuff, strlen(szBuff), &rDraw, DT_LEFT|DT_VCENTER|DT_SINGLELINE );
::DeleteObject(panelBrush);
::DeleteObject(borderBrush);
::DeleteObject(accentBrush);
}
+78 -1
View File
@@ -48,6 +48,18 @@ If you have questions concerning this license or the applicable additional terms
#define ID_XYDOCK_GAMEPAGE 0x7A04
#define ID_XYDOCK_MODELVIEWPAGE 0x7A05
#define ID_XYDOCK_SCRIPTEDITORPAGE 0x7A06
#define ID_XYDOCK_MATERIALEDITORPAGE 0x7A07
static const int XYDOCK_TAB_MATERIALEDITOR = 4;
HWND MaterialEditorCreateEmbeddedWindow(CWnd *parent, const RECT& rect);
void MaterialEditorMoveEmbeddedWindow(const RECT& rect);
void MaterialEditorShowEmbeddedWindow(BOOL show);
void MaterialEditorFocusEmbeddedWindow(void);
BOOL MaterialEditorPreTranslateEmbeddedMessage(MSG *pMsg);
BOOL MaterialEditorEmbeddedOnCommand(WPARAM wParam, LPARAM lParam);
BOOL MaterialEditorEmbeddedOnNotify(WPARAM wParam, LPARAM lParam, LRESULT *pResult);
BOOL MaterialEditorEmbeddedOnCmdMsg(UINT nID, int nCode, void *pExtra, AFX_CMDHANDLERINFO *pHandlerInfo);
#define ID_GAME_HOST 0x7A30
#define ID_GAME_FILL_FIT 0x7A40
@@ -1538,6 +1550,8 @@ void CGameDockWnd::OnFill50() {
FocusGameWindow();
}
static CXYDockWnd *g_materialEditorDockWnd = NULL;
//=============================================================================
// CXYDockWnd
//=============================================================================
@@ -1555,9 +1569,14 @@ CXYDockWnd::CXYDockWnd() {
m_pToolBar = NULL;
m_bInLayout = false;
m_nActiveTab = XYDOCK_TAB_XY;
g_materialEditorDockWnd = this;
}
CXYDockWnd::~CXYDockWnd() {
if (g_materialEditorDockWnd == this) {
MaterialEditorShowEmbeddedWindow(FALSE);
g_materialEditorDockWnd = NULL;
}
}
BOOL CXYDockWnd::Create(CWnd *pParent, UINT nID) {
@@ -1613,6 +1632,9 @@ int CXYDockWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) {
item.pszText = "Script Editor";
m_wndTabs.InsertItem(XYDOCK_TAB_SCRIPTEDITOR, &item);
item.pszText = "Material Editor";
m_wndTabs.InsertItem(XYDOCK_TAB_MATERIALEDITOR, &item);
CString pageClass = AfxRegisterWndClass(
CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS,
::LoadCursor(NULL, IDC_ARROW),
@@ -1647,6 +1669,10 @@ int CXYDockWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) {
}
m_wndScriptPage.ShowWindow(SW_HIDE);
CRect materialEditorInitialRect(0, 0, 0, 0);
MaterialEditorCreateEmbeddedWindow(&m_wndTabs, materialEditorInitialRect);
MaterialEditorShowEmbeddedWindow(FALSE);
if (!m_wndMenuBar.Create(&m_wndXYPage, 0x7A01)) {
return -1;
}
@@ -1787,6 +1813,7 @@ void CXYDockWnd::ShowActiveTab() {
const BOOL gameActive = (m_nActiveTab == XYDOCK_TAB_GAME);
const BOOL modelActive = (m_nActiveTab == XYDOCK_TAB_MODELVIEW);
const BOOL scriptActive = (m_nActiveTab == XYDOCK_TAB_SCRIPTEDITOR);
const BOOL materialActive = (m_nActiveTab == XYDOCK_TAB_MATERIALEDITOR);
if (m_wndXYPage.GetSafeHwnd()) {
m_wndXYPage.ShowWindow(xyActive ? SW_SHOW : SW_HIDE);
@@ -1822,10 +1849,12 @@ void CXYDockWnd::ShowActiveTab() {
}
m_wndScriptPage.SetActive(scriptActive);
}
MaterialEditorShowEmbeddedWindow(materialActive);
}
void CXYDockWnd::SetActiveTab(int nTab) {
if (nTab != XYDOCK_TAB_XY && nTab != XYDOCK_TAB_GAME && nTab != XYDOCK_TAB_MODELVIEW && nTab != XYDOCK_TAB_SCRIPTEDITOR) {
if (nTab != XYDOCK_TAB_XY && nTab != XYDOCK_TAB_GAME && nTab != XYDOCK_TAB_MODELVIEW && nTab != XYDOCK_TAB_SCRIPTEDITOR && nTab != XYDOCK_TAB_MATERIALEDITOR) {
nTab = XYDOCK_TAB_XY;
}
@@ -1900,6 +1929,27 @@ void CXYDockWnd::SetActiveTab(int nTab) {
common->ActivateTool(true);
FocusScriptEditor();
}
else if (m_nActiveTab == XYDOCK_TAB_MATERIALEDITOR) {
//
// Material Editor tab selected:
// - game HWND is deactivated
// - editor/tool input stays active
// - focus moves to the embedded material editor frame
//
if (m_wndGamePage.GetSafeHwnd()) {
m_wndGamePage.SetActive(FALSE);
}
if (m_wndModelPage.GetSafeHwnd()) {
m_wndModelPage.SetActive(FALSE);
}
if (m_wndScriptPage.GetSafeHwnd()) {
m_wndScriptPage.SetActive(FALSE);
}
common->ActivateTool(true);
MaterialEditorShowEmbeddedWindow(TRUE);
MaterialEditorFocusEmbeddedWindow();
}
else {
//
// XY tab selected:
@@ -1916,6 +1966,7 @@ void CXYDockWnd::SetActiveTab(int nTab) {
if (m_wndScriptPage.GetSafeHwnd()) {
m_wndScriptPage.SetActive(FALSE);
}
MaterialEditorShowEmbeddedWindow(FALSE);
common->ActivateTool(true);
FocusXYWindow();
@@ -2002,6 +2053,14 @@ void CXYDockWnd::FocusXYWindow() {
m_wndMDIContainer.FocusXYWindow();
}
bool MaterialEditorOpenDockTab() {
if (g_materialEditorDockWnd && g_materialEditorDockWnd->GetSafeHwnd()) {
g_materialEditorDockWnd->SetActiveTab(XYDOCK_TAB_MATERIALEDITOR);
return true;
}
return false;
}
void CXYDockWnd::LayoutChildren() {
if (!GetSafeHwnd() || m_bInLayout) {
return;
@@ -2050,6 +2109,8 @@ void CXYDockWnd::LayoutChildren() {
m_wndScriptPage.LayoutChildren();
}
MaterialEditorMoveEmbeddedWindow(pageRect);
ShowActiveTab();
if (m_pToolBar && m_pToolBar->GetSafeHwnd() && m_wndXYPage.GetSafeHwnd()) {
@@ -2119,6 +2180,11 @@ BOOL CXYDockWnd::PreTranslateMessage(MSG *pMsg) {
return TRUE;
}
}
if (m_nActiveTab == XYDOCK_TAB_MATERIALEDITOR) {
if (MaterialEditorPreTranslateEmbeddedMessage(pMsg)) {
return TRUE;
}
}
return CWnd::PreTranslateMessage(pMsg);
}
@@ -2144,6 +2210,9 @@ BOOL CXYDockWnd::OnCommand(WPARAM wParam, LPARAM lParam) {
m_wndScriptPage.SendMessage(WM_COMMAND, wParam, lParam);
return TRUE;
}
if (m_nActiveTab == XYDOCK_TAB_MATERIALEDITOR) {
return MaterialEditorEmbeddedOnCommand(wParam, lParam);
}
if (m_nActiveTab != XYDOCK_TAB_XY) {
return CWnd::OnCommand(wParam, lParam);
@@ -2160,6 +2229,11 @@ BOOL CXYDockWnd::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT *pResult) {
if (wParam == ID_XYDOCK_TABS) {
return CWnd::OnNotify(wParam, lParam, pResult);
}
if (m_nActiveTab == XYDOCK_TAB_MATERIALEDITOR) {
if (MaterialEditorEmbeddedOnNotify(wParam, lParam, pResult)) {
return TRUE;
}
}
CWnd *commandTarget = GetCommandTarget();
if (commandTarget && commandTarget->GetSafeHwnd() && commandTarget != this) {
@@ -2183,6 +2257,9 @@ BOOL CXYDockWnd::OnCmdMsg(UINT nID, int nCode, void *pExtra, AFX_CMDHANDLERINFO
if (m_nActiveTab == XYDOCK_TAB_SCRIPTEDITOR && m_wndScriptPage.GetSafeHwnd()) {
return m_wndScriptPage.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
if (m_nActiveTab == XYDOCK_TAB_MATERIALEDITOR) {
return MaterialEditorEmbeddedOnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
if (m_nActiveTab != XYDOCK_TAB_XY) {
return FALSE;
+2 -2
View File
@@ -300,11 +300,11 @@ protected:
CToolBar *m_pToolBar;
bool m_bInLayout;
int m_nActiveTab;
public:
void SetActiveTab(int nTab);
void ShowActiveTab();
CWnd *GetXYPageParent() const;
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg BOOL OnEraseBkgnd(CDC *pDC);