mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-12 08:11:10 +02:00
New editor tabs.
This commit is contained in:
@@ -15,9 +15,9 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LocalDebuggerCommand>D:\projects\Doom3\Doom3.exe</LocalDebuggerCommand>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerCommandArguments>+set r_fullscreen 1 +set r_mode 9</LocalDebuggerCommandArguments>
|
||||
<LocalDebuggerCommandArguments>+set r_fullscreen 0 +set r_mode 9</LocalDebuggerCommandArguments>
|
||||
<LocalDebuggerWorkingDirectory>D:\projects\Doom3</LocalDebuggerWorkingDirectory>
|
||||
<LocalDebuggerCommandArgumentsHistory>+set r_fullscreen 1 +set r_mode 1|+set r_fullscreen 0 +set r_mode 1|+set r_fullscreen 1 +set r_mode 0|+set r_fullscreen 1 +set r_mode 10|+set r_fullscreen 1 +set r_mode 9|</LocalDebuggerCommandArgumentsHistory>
|
||||
<LocalDebuggerCommandArgumentsHistory>+set r_fullscreen 0 +set r_mode 1|+set r_fullscreen 1 +set r_mode 0|+set r_fullscreen 1 +set r_mode 10|+set r_fullscreen 1 +set r_mode 9|+set r_fullscreen 0 +set r_mode 9|</LocalDebuggerCommandArgumentsHistory>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Q4 Debug|x64'">
|
||||
<LocalDebuggerCommand>D:\projects\Doom3\Quake4.exe</LocalDebuggerCommand>
|
||||
|
||||
@@ -63,6 +63,8 @@ If you have questions concerning this license or the applicable additional terms
|
||||
|
||||
#ifdef PREY
|
||||
#define CONFIG_FILE "PreyConfig.cfg"
|
||||
#elif defined(QUAKE4)
|
||||
#define CONFIG_FILE "Q4Config.cfg"
|
||||
#else
|
||||
#define CONFIG_FILE "DoomConfig.cfg"
|
||||
#endif
|
||||
|
||||
@@ -96,7 +96,8 @@ const float MAX_BOUND_SIZE = 65536.0f;
|
||||
#define DIRECTSOUND_VERSION 0x0800
|
||||
|
||||
#include <dsound.h>
|
||||
#include <dinput.h>
|
||||
// #include <dinput.h>
|
||||
#include "../opengl/DirectInputShim.h"
|
||||
|
||||
#endif /* !GAME_DLL */
|
||||
#endif /* !_D3SDK */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <dinput.h>
|
||||
|
||||
#ifndef DIRECTINPUT_VERSION
|
||||
#define DIRECTINPUT_VERSION 0x0800
|
||||
#endif
|
||||
|
||||
// Call this instead of DirectInput8Create.
|
||||
HRESULT WINAPI IceDirectInput8Create(
|
||||
HINSTANCE hinst,
|
||||
DWORD dwVersion,
|
||||
REFIID riidltf,
|
||||
LPVOID* ppvOut,
|
||||
LPUNKNOWN punkOuter
|
||||
);
|
||||
|
||||
// Call from your main window proc on WM_INPUT.
|
||||
bool IceDirectInputShim_HandleRawInput(LPARAM lParam);
|
||||
|
||||
// Optional: call when your hwnd changes/recreates.
|
||||
bool IceDirectInputShim_RegisterRawInput(HWND hwnd);
|
||||
|
||||
// Optional shutdown helper.
|
||||
void IceDirectInputShim_Shutdown();
|
||||
|
||||
void IceDI_ForceOverrideSkipCenter(bool shouldSkip);
|
||||
@@ -188,6 +188,12 @@ using Microsoft::WRL::ComPtr;
|
||||
#ifndef GL_QD3D12_TONEMAP_BRIGHTNESS
|
||||
#define GL_QD3D12_TONEMAP_BRIGHTNESS 0x600A
|
||||
#endif
|
||||
#ifndef GL_QD3D12_TAA_ENABLED
|
||||
#define GL_QD3D12_TAA_ENABLED 0x600B
|
||||
#endif
|
||||
#ifndef GL_QD3D12_TAA
|
||||
#define GL_QD3D12_TAA GL_QD3D12_TAA_ENABLED
|
||||
#endif
|
||||
#ifndef GL_QD3D12_TONE_MAP_BRIGHTNESS
|
||||
#define GL_QD3D12_TONE_MAP_BRIGHTNESS GL_QD3D12_TONEMAP_BRIGHTNESS
|
||||
#endif
|
||||
@@ -314,6 +320,12 @@ void QD3D12_EnableDLAA(int enabled);
|
||||
int QD3D12_IsDLAAEnabled(void);
|
||||
void APIENTRY glDLAAQD3D12(GLboolean enable);
|
||||
void APIENTRY glEnableDLAAQD3D12(GLboolean enable);
|
||||
void QD3D12_EnableTAA(int enabled);
|
||||
int QD3D12_IsTAAEnabled(void);
|
||||
void APIENTRY glTAAQD3D12(GLboolean enable);
|
||||
void APIENTRY glEnableTAAQD3D12(GLboolean enable);
|
||||
void APIENTRY glTemporalAAQD3D12(GLboolean enable);
|
||||
void APIENTRY glEnableTemporalAAQD3D12(GLboolean enable);
|
||||
void QD3D12_SetPathTracingQuality(uint32_t samplesPerPixel, uint32_t maxBounces);
|
||||
void QD3D12_SetPathTracingFallbackSamples(uint32_t samplesPerPixel);
|
||||
void QD3D12_SetCameraInfo(
|
||||
@@ -661,7 +673,7 @@ struct GLBufferObject
|
||||
const char* vendor = "Justin Marshall";
|
||||
const char* renderer = "Quake D3D12 Wrapper";
|
||||
const char* version = "1.1-quake-d3d12";
|
||||
const char* extensions = "GL_SGIS_multitexture GL_ARB_multitexture GL_EXT_texture_env_add GL_ARB_texture_env_combine GL_ARB_texture_compression GL_EXT_texture_compression_s3tc GL_ARB_vertex_program GL_ARB_fragment_program GL_EXT_texture_cube_map GL_EXT_depth_bounds_test GL_EXT_stencil_two_side GL_ATI_separate_stencil GL_QD3D12_normal_map GL_QD3D12_glow_map GL_QD3D12_specular_map GL_QD3D12_glass_material GL_QD3D12_volumetric_light GL_QD3D12_dlaa GL_QD3D12_tonemap_brightness";
|
||||
const char* extensions = "GL_SGIS_multitexture GL_ARB_multitexture GL_EXT_texture_env_add GL_ARB_texture_env_combine GL_ARB_texture_compression GL_EXT_texture_compression_s3tc GL_ARB_vertex_program GL_ARB_fragment_program GL_EXT_texture_cube_map GL_EXT_depth_bounds_test GL_EXT_stencil_two_side GL_ATI_separate_stencil GL_QD3D12_normal_map GL_QD3D12_glow_map GL_QD3D12_specular_map GL_QD3D12_glass_material GL_QD3D12_volumetric_light GL_QD3D12_dlaa GL_QD3D12_taa GL_QD3D12_tonemap_brightness";
|
||||
|
||||
enum TexEnvModeShader
|
||||
{
|
||||
@@ -1207,6 +1219,7 @@ struct GLState
|
||||
|
||||
QD3D12UpscalerBackend upscalerBackend = QD3D12_UPSCALER_DLSS;
|
||||
QD3D12UpscalerQuality upscalerQuality = QD3D12_QUALITY_PERFORMANCE;
|
||||
bool enableInternalTAA = true;
|
||||
bool enableRayAIDenoise = false;
|
||||
bool enableDLSSRayReconstruction = true;
|
||||
bool enableFSRRayRegeneration = false;
|
||||
@@ -5874,7 +5887,9 @@ static bool QD3D12_ShouldRunInternalTAA(const QD3D12Window& w)
|
||||
{
|
||||
// DLSS/DLSS-RR/FSR are already temporal. The internal TAA pass replaces MSAA
|
||||
// for the native/no-upscaler path and runs after lighting but before 2D.
|
||||
return !w.isPbuffer && !QD3D12_ExternalTemporalUpscalerActive(w);
|
||||
return g_gl.enableInternalTAA &&
|
||||
!w.isPbuffer &&
|
||||
!QD3D12_ExternalTemporalUpscalerActive(w);
|
||||
}
|
||||
|
||||
static bool QD3D12_FinalBlitToBackBuffer(
|
||||
@@ -10348,6 +10363,9 @@ void APIENTRY glEnable(GLenum cap)
|
||||
case GL_FRAGMENT_PROGRAM_ARB:
|
||||
QD3D12ARB_SetEnabled(cap, true);
|
||||
break;
|
||||
case GL_QD3D12_TAA:
|
||||
QD3D12_EnableTAA(1);
|
||||
break;
|
||||
case GL_TEXTURE_2D:
|
||||
#ifdef GL_TEXTURE_RECTANGLE_ARB
|
||||
case GL_TEXTURE_RECTANGLE_ARB:
|
||||
@@ -10385,6 +10403,9 @@ void APIENTRY glDisable(GLenum cap)
|
||||
case GL_FRAGMENT_PROGRAM_ARB:
|
||||
QD3D12ARB_SetEnabled(cap, false);
|
||||
break;
|
||||
case GL_QD3D12_TAA:
|
||||
QD3D12_EnableTAA(0);
|
||||
break;
|
||||
case GL_TEXTURE_2D:
|
||||
#ifdef GL_TEXTURE_RECTANGLE_ARB
|
||||
case GL_TEXTURE_RECTANGLE_ARB:
|
||||
@@ -10954,6 +10975,10 @@ void APIENTRY glGetIntegerv(GLenum pname, GLint* params)
|
||||
*params = (GLint)QD3D12_IsDLAAEnabled();
|
||||
break;
|
||||
|
||||
case GL_QD3D12_TAA_ENABLED:
|
||||
*params = (GLint)QD3D12_IsTAAEnabled();
|
||||
break;
|
||||
|
||||
#ifdef GL_ACTIVE_STENCIL_FACE_EXT
|
||||
case GL_ACTIVE_STENCIL_FACE_EXT:
|
||||
*params = (GLint)g_gl.activeStencilFace;
|
||||
@@ -13561,6 +13586,12 @@ PROC WINAPI qd3d12_wglGetProcAddress(LPCSTR name) {
|
||||
{ "QD3D12_IsDLAAEnabled", (PROC)QD3D12_IsDLAAEnabled },
|
||||
{ "glDLAAQD3D12", (PROC)glDLAAQD3D12 },
|
||||
{ "glEnableDLAAQD3D12", (PROC)glEnableDLAAQD3D12 },
|
||||
{ "QD3D12_EnableTAA", (PROC)QD3D12_EnableTAA },
|
||||
{ "QD3D12_IsTAAEnabled", (PROC)QD3D12_IsTAAEnabled },
|
||||
{ "glTAAQD3D12", (PROC)glTAAQD3D12 },
|
||||
{ "glEnableTAAQD3D12", (PROC)glEnableTAAQD3D12 },
|
||||
{ "glTemporalAAQD3D12", (PROC)glTemporalAAQD3D12 },
|
||||
{ "glEnableTemporalAAQD3D12", (PROC)glEnableTemporalAAQD3D12 },
|
||||
{ "QD3D12_SetPathTracingQuality", (PROC)QD3D12_SetPathTracingQuality },
|
||||
{ "QD3D12_SetPathTracingFallbackSamples", (PROC)QD3D12_SetPathTracingFallbackSamples },
|
||||
{ "glSetTopLevelAccelStructureVisible", (PROC)glSetTopLevelAccelStructureVisible },
|
||||
@@ -14503,6 +14534,56 @@ void APIENTRY glEnableDLAAQD3D12(GLboolean enable)
|
||||
glDLAAQD3D12(enable);
|
||||
}
|
||||
|
||||
static void QD3D12_ResetInternalTAAHistoryForWindow(QD3D12Window* window)
|
||||
{
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
for (UINT i = 0; i < QD3D12_FrameCount; ++i)
|
||||
window->taaHistoryValid[i] = false;
|
||||
}
|
||||
|
||||
void QD3D12_EnableTAA(int enabled)
|
||||
{
|
||||
const bool newValue = enabled ? true : false;
|
||||
if (g_gl.enableInternalTAA == newValue)
|
||||
return;
|
||||
|
||||
g_gl.enableInternalTAA = newValue;
|
||||
g_gl.motionHistoryReset = true;
|
||||
|
||||
// TAA history is only valid for the previous TAA mode. Drop it so re-enabling
|
||||
// starts from the current frame instead of blending against stale history.
|
||||
QD3D12_ResetInternalTAAHistoryForWindow(g_currentWindow);
|
||||
for (auto& kv : g_windows)
|
||||
QD3D12_ResetInternalTAAHistoryForWindow(&kv.second);
|
||||
}
|
||||
|
||||
int QD3D12_IsTAAEnabled(void)
|
||||
{
|
||||
return g_gl.enableInternalTAA ? 1 : 0;
|
||||
}
|
||||
|
||||
void APIENTRY glTAAQD3D12(GLboolean enable)
|
||||
{
|
||||
QD3D12_EnableTAA(enable != GL_FALSE ? 1 : 0);
|
||||
}
|
||||
|
||||
void APIENTRY glEnableTAAQD3D12(GLboolean enable)
|
||||
{
|
||||
glTAAQD3D12(enable);
|
||||
}
|
||||
|
||||
void APIENTRY glTemporalAAQD3D12(GLboolean enable)
|
||||
{
|
||||
glTAAQD3D12(enable);
|
||||
}
|
||||
|
||||
void APIENTRY glEnableTemporalAAQD3D12(GLboolean enable)
|
||||
{
|
||||
glTAAQD3D12(enable);
|
||||
}
|
||||
|
||||
void QD3D12_SetUpscalerSharpness(float sharpness)
|
||||
{
|
||||
g_gl.upscalerSharpness = ClampValue<float>(sharpness, 0.0f, 1.0f);
|
||||
@@ -15679,6 +15760,7 @@ GLboolean APIENTRY glIsEnabled(GLenum cap)
|
||||
case GL_STENCIL_TEST_TWO_SIDE_EXT: return g_gl.stencilTwoSide ? GL_TRUE : GL_FALSE;
|
||||
#endif
|
||||
case GL_TEXTURE_2D: return g_gl.texture2D[g_gl.activeTextureUnit] ? GL_TRUE : GL_FALSE;
|
||||
case GL_QD3D12_TAA: return QD3D12_IsTAAEnabled() ? GL_TRUE : GL_FALSE;
|
||||
|
||||
case GL_LIGHTING:
|
||||
return g_glState.lightingEnabled;
|
||||
|
||||
@@ -2325,4 +2325,6 @@ void APIENTRY glShowAllTopLevelAccelStructures(
|
||||
glRaytracingSceneHandle_t scene);
|
||||
|
||||
void QD3D12_SetUpscalerSharpness(float sharpness);
|
||||
void QD3D12_SetToneMapBrightness(float brightness);
|
||||
void QD3D12_SetToneMapBrightness(float brightness);
|
||||
|
||||
void QD3D12_EnableTAA(int enabled);
|
||||
@@ -35,6 +35,7 @@
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="DirectInputShim.cpp" />
|
||||
<ClCompile Include="gl_d3d12arb.cpp" />
|
||||
<ClCompile Include="gl_d3d12raylight.cpp">
|
||||
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Disabled</Optimization>
|
||||
@@ -178,6 +179,7 @@
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="DirectInputShim.h" />
|
||||
<ClInclude Include="gl_d3d12arb.h" />
|
||||
<ClInclude Include="opengl.h" />
|
||||
<ClInclude Include="tess\dict-list.h" />
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
<Filter>tess</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl_d3d12arb.cpp" />
|
||||
<ClCompile Include="DirectInputShim.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="opengl.h" />
|
||||
@@ -94,6 +95,7 @@
|
||||
<Filter>tess</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl_d3d12arb.h" />
|
||||
<ClInclude Include="DirectInputShim.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="tess">
|
||||
|
||||
@@ -512,7 +512,7 @@ void IN_InitDirectInput( void ) {
|
||||
// Register with the DirectInput subsystem and get a pointer
|
||||
// to a IDirectInput interface we can use.
|
||||
// Create the base DirectInput object
|
||||
if ( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&win32.g_pdi, NULL ) ) ) {
|
||||
if ( FAILED( hr = IceDirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&win32.g_pdi, NULL ) ) ) {
|
||||
common->Printf ("DirectInputCreate failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,6 +276,10 @@ main window procedure
|
||||
LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
|
||||
int key;
|
||||
switch( uMsg ) {
|
||||
case WM_INPUT:
|
||||
IceDirectInputShim_HandleRawInput(lParam);
|
||||
return 0;
|
||||
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
if (glConfig.isInitialized) {
|
||||
RECT rect;
|
||||
@@ -334,6 +338,8 @@ LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
|
||||
|
||||
if ( fActive == WA_INACTIVE ) {
|
||||
win32.movingWindow = false;
|
||||
Sys_GrabMouseCursor(false);
|
||||
idKeyInput::ClearStates();
|
||||
}
|
||||
|
||||
// start playing the game sound world
|
||||
|
||||
@@ -1829,7 +1829,7 @@ void CCamWnd::OnPaint() {
|
||||
CamWnd_EnsureMenuBar(this);
|
||||
CamWnd_LayoutMenuBar(this);
|
||||
|
||||
idGraphicsDeviceContextHelper context(dc.m_hDC, hglrc);
|
||||
idGraphicsDeviceContextHelper context(dc.m_hDC, hglrc, true);
|
||||
|
||||
g_pSplitList = NULL;
|
||||
if (g_bClipMode) {
|
||||
|
||||
@@ -278,7 +278,6 @@ SCommandInfo g_Commands[] = {
|
||||
{ "Find_Entity", VK_F3, RAD_CONTROL, ID_MISC_FINDORREPLACEENTITY},
|
||||
{ "Find_NextEntity", VK_F3,RAD_SHIFT, ID_MISC_FINDNEXTENT},
|
||||
|
||||
{ "_ShowDOOM", VK_F2, 0, ID_SHOW_DOOM },
|
||||
|
||||
{ "Rotate_MouseRotate", 'R', 0, ID_SELECT_MOUSEROTATE },
|
||||
{ "Rotate_ToggleFlatRotation", 'R', RAD_CONTROL, ID_VIEW_CAMERAUPDATE },
|
||||
@@ -1360,12 +1359,71 @@ BOOL CMainFrame::CreateEmbeddedMainToolBar(UINT nID) {
|
||||
}
|
||||
|
||||
m_wndToolBar.SetOwner(this);
|
||||
RemoveDoomToolbarButton();
|
||||
if (m_pXYDockWnd) {
|
||||
m_pXYDockWnd->SetEmbeddedToolBar(&m_wndToolBar);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
=======================================================================================================================
|
||||
=======================================================================================================================
|
||||
*/
|
||||
static BOOL RemoveMenuCommandRecursive(HMENU hMenu, UINT nCommandID) {
|
||||
if (!hMenu) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL removed = FALSE;
|
||||
for (int i = ::GetMenuItemCount(hMenu) - 1; i >= 0; --i) {
|
||||
MENUITEMINFO info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.cbSize = sizeof(info);
|
||||
info.fMask = MIIM_ID | MIIM_SUBMENU;
|
||||
|
||||
if (!::GetMenuItemInfo(hMenu, i, TRUE, &info)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (info.hSubMenu) {
|
||||
removed |= RemoveMenuCommandRecursive(info.hSubMenu, nCommandID);
|
||||
if (::GetMenuItemCount(info.hSubMenu) == 0) {
|
||||
::DeleteMenu(hMenu, i, MF_BYPOSITION);
|
||||
removed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!info.hSubMenu && info.wID == nCommandID) {
|
||||
::DeleteMenu(hMenu, i, MF_BYPOSITION);
|
||||
removed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
void CMainFrame::RemoveDoomMenuItems(HMENU hMenu) {
|
||||
if (hMenu) {
|
||||
RemoveMenuCommandRecursive(hMenu, ID_SHOW_DOOM);
|
||||
}
|
||||
}
|
||||
|
||||
void CMainFrame::RemoveDoomToolbarButton() {
|
||||
if (!m_wndToolBar.GetSafeHwnd()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CToolBarCtrl &toolBarCtrl = m_wndToolBar.GetToolBarCtrl();
|
||||
for (int i = toolBarCtrl.GetButtonCount() - 1; i >= 0; --i) {
|
||||
TBBUTTON button;
|
||||
memset(&button, 0, sizeof(button));
|
||||
if (toolBarCtrl.GetButton(i, &button) && button.idCommand == ID_SHOW_DOOM) {
|
||||
toolBarCtrl.DeleteButton(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=======================================================================================================================
|
||||
=======================================================================================================================
|
||||
@@ -1384,6 +1442,7 @@ void CMainFrame::MoveFrameMenuIntoXYWnd() {
|
||||
}
|
||||
|
||||
m_hMovedMenu = hMenu;
|
||||
RemoveDoomMenuItems(hMenu);
|
||||
m_pXYDockWnd->SetMenuHandle(hMenu);
|
||||
|
||||
if (::GetMenu(GetSafeHwnd()) == hMenu) {
|
||||
@@ -1409,6 +1468,62 @@ void CMainFrame::RecalcMainLayout() {
|
||||
RecalcXYDockLayout();
|
||||
}
|
||||
|
||||
void CMainFrame::AttachDoomWindowToGameTab() {
|
||||
if (!m_pXYDockWnd || !m_pXYDockWnd->GetSafeHwnd()) {
|
||||
return;
|
||||
}
|
||||
if (!win32.hWnd || !::IsWindow(win32.hWnd)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_pXYDockWnd->GetDockedGameWindow() != win32.hWnd) {
|
||||
m_pXYDockWnd->AttachGameWindow(win32.hWnd);
|
||||
RecalcXYDockLayout();
|
||||
} else {
|
||||
m_pXYDockWnd->AttachGameWindow(win32.hWnd);
|
||||
}
|
||||
}
|
||||
|
||||
bool CMainFrame::IsDockedGameInputActive() const {
|
||||
return (m_pXYDockWnd &&
|
||||
m_pXYDockWnd->GetSafeHwnd() &&
|
||||
m_pXYDockWnd->IsGameTabActive() &&
|
||||
m_pXYDockWnd->IsGameWindowDocked());
|
||||
}
|
||||
|
||||
BOOL CMainFrame::ForwardDockedGameKey(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
if (!IsDockedGameInputActive()) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HWND hGameWnd = m_pXYDockWnd->GetDockedGameWindow();
|
||||
if (!hGameWnd || !::IsWindow(hGameWnd)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HWND hFocus = ::GetFocus();
|
||||
if (hFocus != hGameWnd && !::IsChild(hGameWnd, hFocus)) {
|
||||
::SetFocus(hGameWnd);
|
||||
}
|
||||
|
||||
::PostMessage(hGameWnd, message, wParam, lParam);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void CMainFrame::ApplyActiveTabInputMode() {
|
||||
AttachDoomWindowToGameTab();
|
||||
|
||||
if (IsDockedGameInputActive()) {
|
||||
common->ActivateTool(false);
|
||||
m_pXYDockWnd->FocusGameWindow();
|
||||
} else {
|
||||
common->ActivateTool(true);
|
||||
if (soundSystem) {
|
||||
soundSystem->SetPlayingSoundWorld(g_qeglobals.sw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=======================================================================================================================
|
||||
=======================================================================================================================
|
||||
@@ -1971,6 +2086,12 @@ void CMainFrame::CreateQEChildren() {
|
||||
=======================================================================================================================
|
||||
*/
|
||||
BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam) {
|
||||
if (IsDockedGameInputActive()) {
|
||||
const UINT commandID = LOWORD(wParam);
|
||||
if (commandID != ID_SHOW_DOOM) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return CFrameWnd::OnCommand(wParam, lParam);
|
||||
}
|
||||
|
||||
@@ -2049,6 +2170,11 @@ bool MouseDown() {
|
||||
void CMainFrame::OnTimer(UINT_PTR nIDEvent) {
|
||||
static bool autoSavePending = false;
|
||||
|
||||
if (nIDEvent == QE_TIMER0) {
|
||||
AttachDoomWindowToGameTab();
|
||||
ApplyActiveTabInputMode();
|
||||
}
|
||||
|
||||
if ( nIDEvent == QE_TIMER0 && !MouseDown() ) {
|
||||
QE_CountBrushesAndUpdateStatusBar();
|
||||
}
|
||||
@@ -2118,6 +2244,10 @@ void CMainFrame::OnDestroy() {
|
||||
|
||||
SaveWindowPlacement(GetSafeHwnd(), "radiant_MainWindowPlace");
|
||||
|
||||
if (m_pXYDockWnd && m_pXYDockWnd->GetSafeHwnd()) {
|
||||
m_pXYDockWnd->DetachGameWindow(TRUE);
|
||||
}
|
||||
|
||||
if (m_pXYDockWnd && m_pXYDockWnd->GetSafeHwnd()) {
|
||||
SaveWindowPlacement(m_pXYDockWnd->GetSafeHwnd(), "radiant_xywindow");
|
||||
} else if (m_pXYWnd && m_pXYWnd->GetSafeHwnd()) {
|
||||
@@ -2241,6 +2371,11 @@ void CMainFrame::OnClose() {
|
||||
=======================================================================================================================
|
||||
*/
|
||||
void CMainFrame::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) {
|
||||
if (IsDockedGameInputActive()) {
|
||||
ForwardDockedGameKey(WM_KEYUP, nChar, MAKELPARAM(nRepCnt, nFlags));
|
||||
return;
|
||||
}
|
||||
|
||||
// run through our list to see if we have a handler for nChar
|
||||
|
||||
for (int i = 0; i < g_nCommandCount; i++) {
|
||||
@@ -2312,6 +2447,11 @@ bool CamOK(unsigned int nKey) {
|
||||
=======================================================================================================================
|
||||
*/
|
||||
void CMainFrame::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {
|
||||
if (IsDockedGameInputActive()) {
|
||||
ForwardDockedGameKey(WM_SYSKEYDOWN, nChar, MAKELPARAM(nRepCnt, nFlags));
|
||||
return;
|
||||
}
|
||||
|
||||
// OnKeyDown(nChar, nRepCnt, nFlags);
|
||||
if (nChar == VK_DOWN) {
|
||||
OnKeyDown(nChar, nRepCnt, nFlags);
|
||||
@@ -2326,6 +2466,11 @@ void CMainFrame::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {
|
||||
*/
|
||||
void CMainFrame::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {
|
||||
|
||||
if (IsDockedGameInputActive()) {
|
||||
ForwardDockedGameKey(WM_KEYDOWN, nChar, MAKELPARAM(nRepCnt, nFlags));
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < g_nCommandCount; i++) {
|
||||
if (g_Commands[i].m_nKey == nChar) { // find a match?
|
||||
// check modifiers
|
||||
@@ -2422,6 +2567,8 @@ BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext *pContext) {
|
||||
RecalcMainLayout();
|
||||
|
||||
CreateQEChildren();
|
||||
AttachDoomWindowToGameTab();
|
||||
ApplyActiveTabInputMode();
|
||||
|
||||
if (m_pXYWnd) {
|
||||
m_pXYWnd->SetActive(true);
|
||||
@@ -5903,6 +6050,24 @@ void CMainFrame::NudgeSelection(int nDirection, float fAmount) {
|
||||
=======================================================================================================================
|
||||
*/
|
||||
BOOL CMainFrame::PreTranslateMessage(MSG *pMsg) {
|
||||
if (pMsg && IsDockedGameInputActive()) {
|
||||
const UINT message = pMsg->message;
|
||||
const BOOL keyMessage = (message >= WM_KEYFIRST && message <= WM_KEYLAST);
|
||||
|
||||
if (keyMessage) {
|
||||
HWND hGameWnd = m_pXYDockWnd->GetDockedGameWindow();
|
||||
if (hGameWnd && ::IsWindow(hGameWnd)) {
|
||||
if (pMsg->hwnd == hGameWnd || ::IsChild(hGameWnd, pMsg->hwnd)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
::SetFocus(hGameWnd);
|
||||
::PostMessage(hGameWnd, pMsg->message, pMsg->wParam, pMsg->lParam);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pMsg && m_pXYDockWnd && m_pXYDockWnd->GetSafeHwnd()) {
|
||||
BOOL menuKey = FALSE;
|
||||
|
||||
@@ -7004,13 +7169,14 @@ void CMainFrame::OnActivate(UINT nState, CWnd *pWndOther, BOOL bMinimized) {
|
||||
CFrameWnd::OnActivate(nState, pWndOther, bMinimized);
|
||||
|
||||
if ( nState != WA_INACTIVE ) {
|
||||
common->ActivateTool( true );
|
||||
if (::IsWindowVisible(win32.hWnd)) {
|
||||
::ShowWindow(win32.hWnd, SW_HIDE);
|
||||
}
|
||||
AttachDoomWindowToGameTab();
|
||||
ApplyActiveTabInputMode();
|
||||
|
||||
// start playing the editor sound world
|
||||
soundSystem->SetPlayingSoundWorld( g_qeglobals.sw );
|
||||
if (win32.hWnd && ::IsWindow(win32.hWnd) && ::IsWindowVisible(win32.hWnd)) {
|
||||
if (!m_pXYDockWnd || !m_pXYDockWnd->IsGameWindowDocked()) {
|
||||
::ShowWindow(win32.hWnd, SW_HIDE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
//com_editorActive = false;
|
||||
@@ -7266,11 +7432,16 @@ void CMainFrame::OnPatchCombine() {
|
||||
|
||||
void CMainFrame::OnShowDoom()
|
||||
{
|
||||
int show = ::IsWindowVisible(win32.hWnd) ? SW_HIDE : SW_NORMAL;
|
||||
if (show == SW_NORMAL) {
|
||||
// Legacy command path. The menu/toolbar entry is removed, but if an old
|
||||
// accelerator or external command still reaches this handler, switch to the
|
||||
// always-attached Game tab instead of showing a popup.
|
||||
AttachDoomWindowToGameTab();
|
||||
if (m_pXYDockWnd && m_pXYDockWnd->GetSafeHwnd()) {
|
||||
g_Inspectors->SetMode(W_TEXTURE);
|
||||
m_pXYDockWnd->SelectGameTab();
|
||||
ApplyActiveTabInputMode();
|
||||
RecalcXYDockLayout();
|
||||
}
|
||||
::ShowWindow(win32.hWnd, show);
|
||||
}
|
||||
|
||||
void CMainFrame::OnViewRendermode()
|
||||
|
||||
@@ -117,7 +117,7 @@ protected:
|
||||
// CMainFrameLayoutWnd
|
||||
//
|
||||
// Main workspace split:
|
||||
// [ Camera/Inspector stack ] [ splitter ] [ XYDock: menu, toolbar, Z | XY ]
|
||||
// [ Camera/Inspector stack ] [ splitter ] [ XYDock: XY tab | Game tab ]
|
||||
//
|
||||
// XYDock already owns the Z/XY splitter. This wrapper supplies the missing
|
||||
// MainFrm-level split and gives startup proportions like the reference image.
|
||||
@@ -231,6 +231,10 @@ public:
|
||||
CMenu* GetMenu() const;
|
||||
void RecalcMainLayout();
|
||||
void RecalcXYDockLayout();
|
||||
void AttachDoomWindowToGameTab();
|
||||
bool IsDockedGameInputActive() const;
|
||||
BOOL ForwardDockedGameKey(UINT message, WPARAM wParam, LPARAM lParam);
|
||||
void ApplyActiveTabInputMode();
|
||||
|
||||
void SetActiveXY(CXYWnd* p)
|
||||
{
|
||||
@@ -275,6 +279,8 @@ protected:
|
||||
void CreateQEChildren();
|
||||
BOOL CreateEmbeddedMainToolBar(UINT nID);
|
||||
void MoveFrameMenuIntoXYWnd();
|
||||
void RemoveDoomMenuItems(HMENU hMenu);
|
||||
void RemoveDoomToolbarButton();
|
||||
void LoadCommandMap();
|
||||
void SaveCommandMap();
|
||||
void ShowMenuItemKeyBindings(CMenu *pMenu);
|
||||
|
||||
@@ -84,21 +84,25 @@ extern std::mutex g_graphicsDeviceContextMutex;
|
||||
class idGraphicsDeviceContextHelper
|
||||
{
|
||||
public:
|
||||
idGraphicsDeviceContextHelper(HDC inDC, HGLRC inRC)
|
||||
idGraphicsDeviceContextHelper(HDC inDC, HGLRC inRC, bool tsaaEnabled = false)
|
||||
: dc(inDC)
|
||||
, rc(inRC)
|
||||
{
|
||||
this->tsaaEnabled = tsaaEnabled;
|
||||
g_graphicsDeviceContextMutex.lock();
|
||||
wglMakeCurrent(dc, rc);
|
||||
}
|
||||
|
||||
~idGraphicsDeviceContextHelper()
|
||||
{
|
||||
QD3D12_EnableTAA(tsaaEnabled);
|
||||
SwapBuffers(dc);
|
||||
QD3D12_EnableTAA(true);
|
||||
g_graphicsDeviceContextMutex.unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
bool tsaaEnabled = false;
|
||||
HDC dc = nullptr;
|
||||
HGLRC rc = nullptr;
|
||||
};
|
||||
|
||||
@@ -42,6 +42,16 @@ If you have questions concerning this license or the applicable additional terms
|
||||
#define WM_IDLEUPDATECMDUI 0x0363
|
||||
#endif
|
||||
|
||||
#define ID_XYDOCK_TABS 0x7A00
|
||||
#define ID_XYDOCK_XYPAGE 0x7A03
|
||||
#define ID_XYDOCK_GAMEPAGE 0x7A04
|
||||
|
||||
#define ID_GAME_HOST 0x7A30
|
||||
#define ID_GAME_FILL_FIT 0x7A40
|
||||
#define ID_GAME_FILL_100 0x7A41
|
||||
#define ID_GAME_FILL_75 0x7A42
|
||||
#define ID_GAME_FILL_50 0x7A43
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
@@ -586,6 +596,16 @@ int CXYMDIContainerWnd::GetFixedZWidth() const {
|
||||
return GetZWidth();
|
||||
}
|
||||
|
||||
void CXYMDIContainerWnd::FocusXYWindow() {
|
||||
if (m_pXYWnd && m_pXYWnd->GetSafeHwnd()) {
|
||||
m_pXYWnd->SetFocus();
|
||||
}
|
||||
}
|
||||
|
||||
CWnd *CXYMDIContainerWnd::GetXYWindow() const {
|
||||
return m_pXYWnd;
|
||||
}
|
||||
|
||||
bool CXYMDIContainerWnd::HitTestSplitter(const CPoint &point) const {
|
||||
return !m_rcSplitter.IsRectEmpty() && m_rcSplitter.PtInRect(point);
|
||||
}
|
||||
@@ -756,6 +776,421 @@ BOOL CXYMDIContainerWnd::OnCmdMsg(UINT nID, int nCode, void *pExtra, AFX_CMDHAND
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// CGameDockWnd
|
||||
//=============================================================================
|
||||
IMPLEMENT_DYNAMIC(CGameDockWnd, CWnd)
|
||||
|
||||
BEGIN_MESSAGE_MAP(CGameDockWnd, CWnd)
|
||||
ON_WM_CREATE()
|
||||
ON_WM_SIZE()
|
||||
ON_WM_ERASEBKGND()
|
||||
ON_WM_DESTROY()
|
||||
ON_WM_SETFOCUS()
|
||||
ON_BN_CLICKED(ID_GAME_FILL_FIT, OnFillFit)
|
||||
ON_BN_CLICKED(ID_GAME_FILL_100, OnFill100)
|
||||
ON_BN_CLICKED(ID_GAME_FILL_75, OnFill75)
|
||||
ON_BN_CLICKED(ID_GAME_FILL_50, OnFill50)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
CGameDockWnd::CGameDockWnd() {
|
||||
m_hGameWnd = NULL;
|
||||
m_hOldParent = NULL;
|
||||
m_dwOldStyle = 0;
|
||||
m_dwOldExStyle = 0;
|
||||
m_nFillPercent = 0;
|
||||
m_bActive = FALSE;
|
||||
}
|
||||
|
||||
CGameDockWnd::~CGameDockWnd() {
|
||||
}
|
||||
|
||||
BOOL CGameDockWnd::Create(CWnd *pParent, UINT nID) {
|
||||
CString className = AfxRegisterWndClass(
|
||||
CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS,
|
||||
::LoadCursor(NULL, IDC_ARROW),
|
||||
(HBRUSH)::GetStockObject(BLACK_BRUSH),
|
||||
NULL
|
||||
);
|
||||
|
||||
return CWnd::CreateEx(
|
||||
0,
|
||||
className,
|
||||
"RadiantGameDockWnd",
|
||||
WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
|
||||
CRect(0, 0, 0, 0),
|
||||
pParent,
|
||||
nID
|
||||
);
|
||||
}
|
||||
|
||||
void CGameDockWnd::SendGameActivate(BOOL bActive) {
|
||||
if (!m_hGameWnd || !::IsWindow(m_hGameWnd)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Doom 3's MainWndProc expects:
|
||||
//
|
||||
// LOWORD(wParam) = WA_ACTIVE / WA_INACTIVE
|
||||
// HIWORD(wParam) = minimized flag
|
||||
//
|
||||
// We are not minimizing it when changing tabs, so HIWORD is FALSE.
|
||||
//
|
||||
const WPARAM activateParam = MAKEWPARAM(bActive ? WA_ACTIVE : WA_INACTIVE, FALSE);
|
||||
|
||||
//
|
||||
// lParam is the other window involved in activation.
|
||||
// For our embedded case, use the host when activating/deactivating.
|
||||
//
|
||||
HWND hOther = m_wndHost.GetSafeHwnd();
|
||||
|
||||
::SendMessage(m_hGameWnd, WM_ACTIVATE, activateParam, reinterpret_cast<LPARAM>(hOther));
|
||||
|
||||
common->ActivateTool(!bActive);
|
||||
|
||||
if (bActive) {
|
||||
//
|
||||
// WM_ACTIVATE updates win32.activeApp / mouse grabbing.
|
||||
// SetFocus makes keyboard input go directly to the game HWND.
|
||||
//
|
||||
::SetFocus(m_hGameWnd);
|
||||
::SendMessage(m_hGameWnd, WM_SETFOCUS, reinterpret_cast<WPARAM>(hOther), 0);
|
||||
}
|
||||
else {
|
||||
::SendMessage(m_hGameWnd, WM_KILLFOCUS, reinterpret_cast<WPARAM>(hOther), 0);
|
||||
}
|
||||
}
|
||||
|
||||
int CGameDockWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) {
|
||||
if (CWnd::OnCreate(lpCreateStruct) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
CString hostClass = AfxRegisterWndClass(
|
||||
CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS,
|
||||
::LoadCursor(NULL, IDC_ARROW),
|
||||
(HBRUSH)::GetStockObject(BLACK_BRUSH),
|
||||
NULL
|
||||
);
|
||||
|
||||
m_wndTitle.Create("GAME", WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE, CRect(0, 0, 0, 0), this);
|
||||
|
||||
m_btnFit.Create("FIT", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(0, 0, 0, 0), this, ID_GAME_FILL_FIT);
|
||||
m_btn100.Create("100%", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(0, 0, 0, 0), this, ID_GAME_FILL_100);
|
||||
m_btn75.Create("75%", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(0, 0, 0, 0), this, ID_GAME_FILL_75);
|
||||
m_btn50.Create("50%", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(0, 0, 0, 0), this, ID_GAME_FILL_50);
|
||||
|
||||
if (!m_wndHost.CreateEx(
|
||||
WS_EX_CLIENTEDGE,
|
||||
hostClass,
|
||||
"RadiantGameRenderHost",
|
||||
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
|
||||
CRect(0, 0, 0, 0),
|
||||
this,
|
||||
ID_GAME_HOST
|
||||
)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CGameDockWnd::OnDestroy() {
|
||||
DetachGameWindow(TRUE);
|
||||
CWnd::OnDestroy();
|
||||
}
|
||||
|
||||
void CGameDockWnd::OnSetFocus(CWnd *pOldWnd) {
|
||||
CWnd::OnSetFocus(pOldWnd);
|
||||
FocusGameWindow();
|
||||
}
|
||||
|
||||
void CGameDockWnd::SetActive(BOOL bActive) {
|
||||
const BOOL wasActive = m_bActive;
|
||||
m_bActive = bActive;
|
||||
|
||||
if (m_hGameWnd && ::IsWindow(m_hGameWnd)) {
|
||||
::ShowWindow(m_hGameWnd, bActive ? SW_SHOW : SW_HIDE);
|
||||
|
||||
if (bActive) {
|
||||
LayoutGameWindow();
|
||||
::InvalidateRect(m_hGameWnd, NULL, FALSE);
|
||||
}
|
||||
|
||||
//
|
||||
// Only synthesize WM_ACTIVATE on real active-state transitions.
|
||||
// LayoutChildren() calls ShowActiveTab(), so without this guard the
|
||||
// game would get repeated WA_ACTIVE messages every layout pass.
|
||||
//
|
||||
if (wasActive != m_bActive) {
|
||||
SendGameActivate(m_bActive);
|
||||
}
|
||||
|
||||
if (bActive) {
|
||||
FocusGameWindow();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Keep the engine/editor global mode in sync even if the HWND does not
|
||||
// exist yet. This way attaching the game later starts in the correct mode.
|
||||
//
|
||||
if (bActive) {
|
||||
common->ActivateTool(false);
|
||||
}
|
||||
else {
|
||||
common->ActivateTool(true);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CGameDockWnd::IsGameWindowDocked() const {
|
||||
return (m_hGameWnd && ::IsWindow(m_hGameWnd)) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
HWND CGameDockWnd::GetGameWindow() const {
|
||||
return (m_hGameWnd && ::IsWindow(m_hGameWnd)) ? m_hGameWnd : NULL;
|
||||
}
|
||||
|
||||
void CGameDockWnd::FocusGameWindow() {
|
||||
if (m_bActive && m_hGameWnd && ::IsWindow(m_hGameWnd)) {
|
||||
::SetFocus(m_hGameWnd);
|
||||
}
|
||||
}
|
||||
|
||||
void CGameDockWnd::AttachGameWindow(HWND hGameWnd) {
|
||||
if (!hGameWnd || !::IsWindow(hGameWnd) || !m_wndHost.GetSafeHwnd()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_hGameWnd == hGameWnd) {
|
||||
LayoutGameWindow();
|
||||
return;
|
||||
}
|
||||
|
||||
DetachGameWindow(TRUE);
|
||||
|
||||
m_hGameWnd = hGameWnd;
|
||||
m_hOldParent = ::GetParent(hGameWnd);
|
||||
m_dwOldStyle = ::GetWindowLong(hGameWnd, GWL_STYLE);
|
||||
m_dwOldExStyle = ::GetWindowLong(hGameWnd, GWL_EXSTYLE);
|
||||
|
||||
::SetParent(hGameWnd, m_wndHost.GetSafeHwnd());
|
||||
|
||||
LONG style = m_dwOldStyle;
|
||||
style &= ~(WS_POPUP | WS_CAPTION | WS_THICKFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
|
||||
style |= WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
|
||||
::SetWindowLong(hGameWnd, GWL_STYLE, style);
|
||||
|
||||
LONG exStyle = m_dwOldExStyle;
|
||||
exStyle &= ~(WS_EX_APPWINDOW | WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME);
|
||||
exStyle |= WS_EX_CONTROLPARENT;
|
||||
::SetWindowLong(hGameWnd, GWL_EXSTYLE, exStyle);
|
||||
|
||||
::SetWindowPos(
|
||||
hGameWnd,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_SHOWWINDOW
|
||||
);
|
||||
|
||||
LayoutGameWindow();
|
||||
|
||||
::ShowWindow(hGameWnd, m_bActive ? SW_SHOW : SW_HIDE);
|
||||
|
||||
Sys_GrabMouseCursor(m_bActive);
|
||||
|
||||
IceDI_ForceOverrideSkipCenter(!m_bActive);
|
||||
|
||||
if (m_bActive) {
|
||||
//
|
||||
// If the Game tab was already active before the HWND got attached,
|
||||
// SetActive(TRUE) would not see a false->true transition, so force the
|
||||
// initial activation here.
|
||||
//
|
||||
SendGameActivate(TRUE);
|
||||
FocusGameWindow();
|
||||
}
|
||||
}
|
||||
|
||||
void CGameDockWnd::DetachGameWindow(BOOL bRestore) {
|
||||
if (!m_hGameWnd || !::IsWindow(m_hGameWnd)) {
|
||||
m_hGameWnd = NULL;
|
||||
m_hOldParent = NULL;
|
||||
m_dwOldStyle = 0;
|
||||
m_dwOldExStyle = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
HWND hGameWnd = m_hGameWnd;
|
||||
m_hGameWnd = NULL;
|
||||
|
||||
::ShowWindow(hGameWnd, SW_HIDE);
|
||||
|
||||
if (bRestore) {
|
||||
::SetParent(hGameWnd, m_hOldParent);
|
||||
::SetWindowLong(hGameWnd, GWL_STYLE, m_dwOldStyle);
|
||||
::SetWindowLong(hGameWnd, GWL_EXSTYLE, m_dwOldExStyle);
|
||||
::SetWindowPos(
|
||||
hGameWnd,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED
|
||||
);
|
||||
}
|
||||
|
||||
m_hOldParent = NULL;
|
||||
m_dwOldStyle = 0;
|
||||
m_dwOldExStyle = 0;
|
||||
}
|
||||
|
||||
void CGameDockWnd::SetFillPercent(int percent) {
|
||||
m_nFillPercent = percent;
|
||||
LayoutGameWindow();
|
||||
}
|
||||
|
||||
CRect CGameDockWnd::ComputeGameRect(const CRect &hostClient) const {
|
||||
CRect rc = hostClient;
|
||||
|
||||
if (hostClient.Width() <= 0 || hostClient.Height() <= 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
int targetW = hostClient.Width();
|
||||
int targetH = hostClient.Height();
|
||||
|
||||
if (m_nFillPercent == 0) {
|
||||
// Fit to a 16:9 frame while preserving aspect ratio.
|
||||
targetW = hostClient.Width();
|
||||
targetH = (targetW * 9) / 16;
|
||||
|
||||
if (targetH > hostClient.Height()) {
|
||||
targetH = hostClient.Height();
|
||||
targetW = (targetH * 16) / 9;
|
||||
}
|
||||
} else {
|
||||
targetW = (hostClient.Width() * m_nFillPercent) / 100;
|
||||
targetH = (hostClient.Height() * m_nFillPercent) / 100;
|
||||
}
|
||||
|
||||
if (targetW < 1) {
|
||||
targetW = 1;
|
||||
}
|
||||
if (targetH < 1) {
|
||||
targetH = 1;
|
||||
}
|
||||
|
||||
int x = hostClient.left + (hostClient.Width() - targetW) / 2;
|
||||
int y = hostClient.top + (hostClient.Height() - targetH) / 2;
|
||||
|
||||
rc.SetRect(x, y, x + targetW, y + targetH);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void CGameDockWnd::LayoutGameWindow() {
|
||||
if (!m_hGameWnd || !::IsWindow(m_hGameWnd) || !m_wndHost.GetSafeHwnd()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CRect hostClient;
|
||||
m_wndHost.GetClientRect(hostClient);
|
||||
|
||||
CRect gameRect = ComputeGameRect(hostClient);
|
||||
|
||||
::MoveWindow(
|
||||
m_hGameWnd,
|
||||
gameRect.left,
|
||||
gameRect.top,
|
||||
gameRect.Width(),
|
||||
gameRect.Height(),
|
||||
TRUE
|
||||
);
|
||||
|
||||
::InvalidateRect(m_hGameWnd, NULL, FALSE);
|
||||
}
|
||||
|
||||
void CGameDockWnd::LayoutChildren() {
|
||||
if (!GetSafeHwnd()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CRect client;
|
||||
GetClientRect(client);
|
||||
|
||||
const int stripH = 34;
|
||||
const int gap = 6;
|
||||
int x = client.left + 8;
|
||||
int y = client.top + 4;
|
||||
|
||||
if (m_wndTitle.GetSafeHwnd()) {
|
||||
m_wndTitle.MoveWindow(x, y, 90, 24, TRUE);
|
||||
x += 100;
|
||||
}
|
||||
|
||||
CWnd *buttons[] = { &m_btnFit, &m_btn100, &m_btn75, &m_btn50 };
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (buttons[i]->GetSafeHwnd()) {
|
||||
buttons[i]->MoveWindow(x, y, 54, 24, TRUE);
|
||||
x += 54 + gap;
|
||||
}
|
||||
}
|
||||
|
||||
CRect hostRect(
|
||||
client.left + 4,
|
||||
client.top + stripH + 4,
|
||||
client.right - 4,
|
||||
client.bottom - 4
|
||||
);
|
||||
|
||||
if (hostRect.Width() < 1 || hostRect.Height() < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_wndHost.GetSafeHwnd()) {
|
||||
m_wndHost.MoveWindow(hostRect, TRUE);
|
||||
}
|
||||
|
||||
LayoutGameWindow();
|
||||
}
|
||||
|
||||
void CGameDockWnd::OnSize(UINT nType, int cx, int cy) {
|
||||
CWnd::OnSize(nType, cx, cy);
|
||||
LayoutChildren();
|
||||
}
|
||||
|
||||
BOOL CGameDockWnd::OnEraseBkgnd(CDC *pDC) {
|
||||
CRect client;
|
||||
GetClientRect(client);
|
||||
pDC->FillSolidRect(client, RGB(18, 18, 18));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void CGameDockWnd::OnFillFit() {
|
||||
SetFillPercent(0);
|
||||
FocusGameWindow();
|
||||
}
|
||||
|
||||
void CGameDockWnd::OnFill100() {
|
||||
SetFillPercent(100);
|
||||
FocusGameWindow();
|
||||
}
|
||||
|
||||
void CGameDockWnd::OnFill75() {
|
||||
SetFillPercent(75);
|
||||
FocusGameWindow();
|
||||
}
|
||||
|
||||
void CGameDockWnd::OnFill50() {
|
||||
SetFillPercent(50);
|
||||
FocusGameWindow();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// CXYDockWnd
|
||||
//=============================================================================
|
||||
@@ -766,11 +1201,13 @@ BEGIN_MESSAGE_MAP(CXYDockWnd, CWnd)
|
||||
ON_WM_SIZE()
|
||||
ON_WM_ERASEBKGND()
|
||||
ON_MESSAGE(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI)
|
||||
ON_NOTIFY(TCN_SELCHANGE, ID_XYDOCK_TABS, OnTabSelChange)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
CXYDockWnd::CXYDockWnd() {
|
||||
m_pToolBar = NULL;
|
||||
m_bInLayout = false;
|
||||
m_nActiveTab = XYDOCK_TAB_XY;
|
||||
}
|
||||
|
||||
CXYDockWnd::~CXYDockWnd() {
|
||||
@@ -803,15 +1240,69 @@ int CXYDockWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) {
|
||||
if (CWnd::OnCreate(lpCreateStruct) == -1) {
|
||||
return -1;
|
||||
}
|
||||
if (!m_wndMenuBar.Create(this, 0x7A01)) {
|
||||
|
||||
if (!m_wndTabs.Create(
|
||||
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TCS_TABS | TCS_SINGLELINE,
|
||||
CRect(0, 0, 0, 0),
|
||||
this,
|
||||
ID_XYDOCK_TABS
|
||||
)) {
|
||||
return -1;
|
||||
}
|
||||
if (!m_wndMDIContainer.Create(this, 0x7A02)) {
|
||||
|
||||
TCITEM item;
|
||||
memset(&item, 0, sizeof(item));
|
||||
item.mask = TCIF_TEXT;
|
||||
|
||||
item.pszText = "XY";
|
||||
m_wndTabs.InsertItem(XYDOCK_TAB_XY, &item);
|
||||
|
||||
item.pszText = "Game";
|
||||
m_wndTabs.InsertItem(XYDOCK_TAB_GAME, &item);
|
||||
|
||||
CString pageClass = AfxRegisterWndClass(
|
||||
CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS,
|
||||
::LoadCursor(NULL, IDC_ARROW),
|
||||
(HBRUSH)(COLOR_BTNFACE + 1),
|
||||
NULL
|
||||
);
|
||||
|
||||
if (!m_wndXYPage.CreateEx(
|
||||
0,
|
||||
pageClass,
|
||||
"RadiantXYTabPage",
|
||||
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
|
||||
CRect(0, 0, 0, 0),
|
||||
&m_wndTabs,
|
||||
ID_XYDOCK_XYPAGE
|
||||
)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!m_wndGamePage.Create(&m_wndTabs, ID_XYDOCK_GAMEPAGE)) {
|
||||
return -1;
|
||||
}
|
||||
m_wndGamePage.ShowWindow(SW_HIDE);
|
||||
|
||||
if (!m_wndMenuBar.Create(&m_wndXYPage, 0x7A01)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!m_wndMDIContainer.Create(&m_wndXYPage, 0x7A02)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
m_wndTabs.SetCurSel(XYDOCK_TAB_XY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CWnd *CXYDockWnd::GetXYPageParent() const {
|
||||
if (m_wndXYPage.GetSafeHwnd()) {
|
||||
return const_cast<CWnd *>(&m_wndXYPage);
|
||||
}
|
||||
return const_cast<CXYDockWnd *>(this);
|
||||
}
|
||||
|
||||
void CXYDockWnd::SetChildWindows(CXYWnd *pXYWnd, CZWnd *pZWnd) {
|
||||
m_wndMDIContainer.SetChildWindows(pXYWnd, pZWnd);
|
||||
LayoutChildren();
|
||||
@@ -825,15 +1316,14 @@ void CXYDockWnd::SetEmbeddedWindows(CWnd *pZWnd, CWnd *pXYWnd) {
|
||||
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);
|
||||
CWnd *toolbarParent = GetXYPageParent();
|
||||
m_pToolBar->SetParent(toolbarParent);
|
||||
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);
|
||||
m_pToolBar->ModifyStyle(
|
||||
WS_POPUP | WS_CAPTION | WS_THICKFRAME | WS_SYSMENU,
|
||||
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN
|
||||
);
|
||||
}
|
||||
LayoutChildren();
|
||||
}
|
||||
@@ -858,6 +1348,10 @@ CWnd *CXYDockWnd::GetCommandTarget() const {
|
||||
}
|
||||
|
||||
void CXYDockWnd::UpdateToolBarCmdUI(BOOL bDisableIfNoHndler) {
|
||||
if (m_nActiveTab != XYDOCK_TAB_XY) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_pToolBar || !m_pToolBar->GetSafeHwnd() || !m_pToolBar->IsWindowVisible()) {
|
||||
return;
|
||||
}
|
||||
@@ -923,6 +1417,121 @@ int CXYDockWnd::GetZPercent() const {
|
||||
return GetZDockPercent();
|
||||
}
|
||||
|
||||
void CXYDockWnd::ShowActiveTab() {
|
||||
const BOOL xyActive = (m_nActiveTab == XYDOCK_TAB_XY);
|
||||
const BOOL gameActive = (m_nActiveTab == XYDOCK_TAB_GAME);
|
||||
|
||||
if (m_wndXYPage.GetSafeHwnd()) {
|
||||
m_wndXYPage.ShowWindow(xyActive ? SW_SHOW : SW_HIDE);
|
||||
if (xyActive) {
|
||||
m_wndXYPage.SetWindowPos(&wndTop, 0, 0, 0, 0,
|
||||
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_wndGamePage.GetSafeHwnd()) {
|
||||
m_wndGamePage.ShowWindow(gameActive ? SW_SHOW : SW_HIDE);
|
||||
if (gameActive) {
|
||||
m_wndGamePage.SetWindowPos(&wndTop, 0, 0, 0, 0,
|
||||
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||
}
|
||||
m_wndGamePage.SetActive(gameActive);
|
||||
}
|
||||
}
|
||||
|
||||
void CXYDockWnd::SetActiveTab(int nTab) {
|
||||
if (nTab != XYDOCK_TAB_XY && nTab != XYDOCK_TAB_GAME) {
|
||||
nTab = XYDOCK_TAB_XY;
|
||||
}
|
||||
|
||||
const BOOL changed = (m_nActiveTab != nTab);
|
||||
m_nActiveTab = nTab;
|
||||
|
||||
if (m_wndTabs.GetSafeHwnd()) {
|
||||
m_wndTabs.SetCurSel(nTab);
|
||||
}
|
||||
|
||||
LayoutChildren();
|
||||
|
||||
if (changed) {
|
||||
if (m_nActiveTab == XYDOCK_TAB_GAME) {
|
||||
//
|
||||
// Game tab selected:
|
||||
// - editor tool input off
|
||||
// - game HWND receives WM_ACTIVATE/WA_ACTIVE through SetActive(TRUE)
|
||||
// - keyboard/mouse focus moves to game
|
||||
//
|
||||
common->ActivateTool(false);
|
||||
|
||||
if (m_wndGamePage.GetSafeHwnd()) {
|
||||
m_wndGamePage.SetActive(TRUE);
|
||||
}
|
||||
|
||||
FocusGameWindow();
|
||||
}
|
||||
else {
|
||||
//
|
||||
// XY tab selected:
|
||||
// - game HWND receives WM_ACTIVATE/WA_INACTIVE through SetActive(FALSE)
|
||||
// - editor tool input comes back
|
||||
// - focus returns to XY
|
||||
//
|
||||
if (m_wndGamePage.GetSafeHwnd()) {
|
||||
m_wndGamePage.SetActive(FALSE);
|
||||
}
|
||||
|
||||
common->ActivateTool(true);
|
||||
FocusXYWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CXYDockWnd::OnTabSelChange(NMHDR *pNMHDR, LRESULT *pResult) {
|
||||
int sel = m_wndTabs.GetCurSel();
|
||||
SetActiveTab(sel);
|
||||
|
||||
if (pResult) {
|
||||
*pResult = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CXYDockWnd::SelectXYTab() {
|
||||
SetActiveTab(XYDOCK_TAB_XY);
|
||||
}
|
||||
|
||||
void CXYDockWnd::SelectGameTab() {
|
||||
SetActiveTab(XYDOCK_TAB_GAME);
|
||||
}
|
||||
|
||||
BOOL CXYDockWnd::IsGameTabActive() const {
|
||||
return (m_nActiveTab == XYDOCK_TAB_GAME) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
void CXYDockWnd::AttachGameWindow(HWND hGameWnd) {
|
||||
m_wndGamePage.AttachGameWindow(hGameWnd);
|
||||
m_wndGamePage.SetActive(IsGameTabActive());
|
||||
}
|
||||
|
||||
void CXYDockWnd::DetachGameWindow(BOOL bRestore) {
|
||||
m_wndGamePage.DetachGameWindow(bRestore);
|
||||
}
|
||||
|
||||
BOOL CXYDockWnd::IsGameWindowDocked() const {
|
||||
return m_wndGamePage.IsGameWindowDocked();
|
||||
}
|
||||
|
||||
HWND CXYDockWnd::GetDockedGameWindow() const {
|
||||
return m_wndGamePage.GetGameWindow();
|
||||
}
|
||||
|
||||
void CXYDockWnd::FocusGameWindow() {
|
||||
m_wndGamePage.FocusGameWindow();
|
||||
}
|
||||
|
||||
void CXYDockWnd::FocusXYWindow() {
|
||||
m_wndMDIContainer.FocusXYWindow();
|
||||
}
|
||||
|
||||
void CXYDockWnd::LayoutChildren() {
|
||||
if (!GetSafeHwnd() || m_bInLayout) {
|
||||
return;
|
||||
@@ -933,41 +1542,77 @@ void CXYDockWnd::LayoutChildren() {
|
||||
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) {
|
||||
if (client.Width() < 1 || client.Height() < 1) {
|
||||
m_bInLayout = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_wndMDIContainer.GetSafeHwnd()) {
|
||||
m_wndMDIContainer.MoveWindow(content, TRUE);
|
||||
m_wndMDIContainer.LayoutChildren();
|
||||
CRect pageRect(0, 0, client.Width(), client.Height());
|
||||
|
||||
if (m_wndTabs.GetSafeHwnd()) {
|
||||
m_wndTabs.MoveWindow(client, TRUE);
|
||||
|
||||
// The tab pages are children of the tab control, so use tab-client
|
||||
// coordinates here. Creating/moving them as siblings of the tab control
|
||||
// can leave them behind the tab control's client area, which makes both
|
||||
// tabs look empty even though their child windows exist.
|
||||
m_wndTabs.GetClientRect(&pageRect);
|
||||
m_wndTabs.AdjustRect(FALSE, &pageRect);
|
||||
pageRect.DeflateRect(2, 2);
|
||||
}
|
||||
|
||||
if (m_wndXYPage.GetSafeHwnd()) {
|
||||
m_wndXYPage.MoveWindow(pageRect, TRUE);
|
||||
}
|
||||
|
||||
if (m_wndGamePage.GetSafeHwnd()) {
|
||||
m_wndGamePage.MoveWindow(pageRect, TRUE);
|
||||
m_wndGamePage.LayoutChildren();
|
||||
}
|
||||
|
||||
ShowActiveTab();
|
||||
|
||||
if (m_pToolBar && m_pToolBar->GetSafeHwnd() && m_wndXYPage.GetSafeHwnd()) {
|
||||
if (::GetParent(m_pToolBar->GetSafeHwnd()) != m_wndXYPage.GetSafeHwnd()) {
|
||||
m_pToolBar->SetParent(&m_wndXYPage);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_wndXYPage.GetSafeHwnd()) {
|
||||
CRect xyClient;
|
||||
m_wndXYPage.GetClientRect(xyClient);
|
||||
|
||||
int y = xyClient.top;
|
||||
const int width = xyClient.Width();
|
||||
|
||||
if (m_wndMenuBar.GetSafeHwnd()) {
|
||||
if (m_wndMenuBar.GetMenuHandle()) {
|
||||
m_wndMenuBar.ShowWindow(SW_SHOW);
|
||||
const int menuHeight = m_wndMenuBar.PreferredHeight();
|
||||
m_wndMenuBar.MoveWindow(xyClient.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(xyClient.left, y, width, toolbarHeight, TRUE);
|
||||
y += toolbarHeight;
|
||||
}
|
||||
}
|
||||
|
||||
CRect content(xyClient.left, y, xyClient.right, xyClient.bottom);
|
||||
if (content.Width() >= 1 && content.Height() >= 1 && m_wndMDIContainer.GetSafeHwnd()) {
|
||||
m_wndMDIContainer.MoveWindow(content, TRUE);
|
||||
m_wndMDIContainer.LayoutChildren();
|
||||
}
|
||||
}
|
||||
|
||||
m_bInLayout = false;
|
||||
@@ -978,6 +1623,10 @@ void CXYDockWnd::RecalcLayout() {
|
||||
}
|
||||
|
||||
BOOL CXYDockWnd::TrackMenuMnemonic(UINT nChar) {
|
||||
if (m_nActiveTab != XYDOCK_TAB_XY) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (m_wndMenuBar.GetSafeHwnd()) {
|
||||
return m_wndMenuBar.TrackMnemonic(nChar);
|
||||
}
|
||||
@@ -999,6 +1648,10 @@ LRESULT CXYDockWnd::OnIdleUpdateCmdUI(WPARAM wParam, LPARAM lParam) {
|
||||
}
|
||||
|
||||
BOOL CXYDockWnd::OnCommand(WPARAM wParam, LPARAM lParam) {
|
||||
if (m_nActiveTab != XYDOCK_TAB_XY) {
|
||||
return CWnd::OnCommand(wParam, lParam);
|
||||
}
|
||||
|
||||
CWnd *commandTarget = GetCommandTarget();
|
||||
if (commandTarget && commandTarget->GetSafeHwnd() && commandTarget != this) {
|
||||
return static_cast<BOOL>(commandTarget->SendMessage(WM_COMMAND, wParam, lParam));
|
||||
@@ -1007,6 +1660,10 @@ BOOL CXYDockWnd::OnCommand(WPARAM wParam, LPARAM lParam) {
|
||||
}
|
||||
|
||||
BOOL CXYDockWnd::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT *pResult) {
|
||||
if (wParam == ID_XYDOCK_TABS) {
|
||||
return CWnd::OnNotify(wParam, lParam, pResult);
|
||||
}
|
||||
|
||||
CWnd *commandTarget = GetCommandTarget();
|
||||
if (commandTarget && commandTarget->GetSafeHwnd() && commandTarget != this) {
|
||||
LRESULT result = commandTarget->SendMessage(WM_NOTIFY, wParam, lParam);
|
||||
@@ -1026,6 +1683,10 @@ BOOL CXYDockWnd::OnCmdMsg(UINT nID, int nCode, void *pExtra, AFX_CMDHANDLERINFO
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (m_nActiveTab != XYDOCK_TAB_XY) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CWnd *commandTarget = GetCommandTarget();
|
||||
if (commandTarget && commandTarget->GetSafeHwnd() && commandTarget != this) {
|
||||
return commandTarget->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
|
||||
|
||||
@@ -39,6 +39,7 @@ If you have questions concerning this license or the applicable additional terms
|
||||
|
||||
#include "qe3.h"
|
||||
#include "CamWnd.h"
|
||||
#include <afxcmn.h>
|
||||
|
||||
|
||||
class CXYWnd;
|
||||
@@ -109,6 +110,8 @@ public:
|
||||
int GetZDockPercent() const;
|
||||
int GetZWidth() const;
|
||||
int GetFixedZWidth() const;
|
||||
void FocusXYWindow();
|
||||
CWnd *GetXYWindow() const;
|
||||
|
||||
protected:
|
||||
CWnd *m_pXYWnd;
|
||||
@@ -143,16 +146,83 @@ protected:
|
||||
DECLARE_MESSAGE_MAP()
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// CGameDockWnd
|
||||
//
|
||||
// Docked game preview page used by CXYDockWnd's Game tab. This class owns a
|
||||
// small command strip and a black child host window. The real game HWND is
|
||||
// reparented into the host so the existing renderer/context can keep using the
|
||||
// same window instead of a popup.
|
||||
//=============================================================================
|
||||
class CGameDockWnd : public CWnd
|
||||
{
|
||||
DECLARE_DYNAMIC(CGameDockWnd)
|
||||
|
||||
public:
|
||||
CGameDockWnd();
|
||||
virtual ~CGameDockWnd();
|
||||
|
||||
BOOL Create(CWnd *pParent, UINT nID);
|
||||
void AttachGameWindow(HWND hGameWnd);
|
||||
void DetachGameWindow(BOOL bRestore = TRUE);
|
||||
BOOL IsGameWindowDocked() const;
|
||||
HWND GetGameWindow() const;
|
||||
void FocusGameWindow();
|
||||
|
||||
void SetActive(BOOL bActive);
|
||||
void LayoutChildren();
|
||||
void SendGameActivate(BOOL bActive);
|
||||
protected:
|
||||
CStatic m_wndTitle;
|
||||
CButton m_btnFit;
|
||||
CButton m_btn100;
|
||||
CButton m_btn75;
|
||||
CButton m_btn50;
|
||||
CWnd m_wndHost;
|
||||
|
||||
HWND m_hGameWnd;
|
||||
HWND m_hOldParent;
|
||||
LONG m_dwOldStyle;
|
||||
LONG m_dwOldExStyle;
|
||||
|
||||
int m_nFillPercent; // 0 = fit 16:9, otherwise percentage of host area
|
||||
BOOL m_bActive;
|
||||
|
||||
void SetFillPercent(int percent);
|
||||
void LayoutGameWindow();
|
||||
CRect ComputeGameRect(const CRect &hostClient) const;
|
||||
|
||||
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
|
||||
afx_msg void OnSize(UINT nType, int cx, int cy);
|
||||
afx_msg BOOL OnEraseBkgnd(CDC *pDC);
|
||||
afx_msg void OnDestroy();
|
||||
afx_msg void OnSetFocus(CWnd *pOldWnd);
|
||||
|
||||
afx_msg void OnFillFit();
|
||||
afx_msg void OnFill100();
|
||||
afx_msg void OnFill75();
|
||||
afx_msg void OnFill50();
|
||||
|
||||
DECLARE_MESSAGE_MAP()
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// CXYDockWnd
|
||||
//
|
||||
// Owns the embedded XY editor layout:
|
||||
// Owns the embedded XY editor layout and the new docked game preview:
|
||||
// [ tabs: XY | Game ]
|
||||
//
|
||||
// XY tab:
|
||||
// [ menu bar ]
|
||||
// [ toolbar ]
|
||||
// [ MDI client: Z window | splitter | XY top render window ]
|
||||
//
|
||||
// Game tab:
|
||||
// [ game command strip / fill controls ]
|
||||
// [ hosted game HWND ]
|
||||
//
|
||||
// The docked Z window starts at 5% of the MDI container width. The divider in
|
||||
// the MDI client can be dragged to resize the Z and XY top panes.
|
||||
// the MDI client can be dragged to resize the Z and XY top panes interactively.
|
||||
//=============================================================================
|
||||
class CXYDockWnd : public CWnd
|
||||
{
|
||||
@@ -187,16 +257,41 @@ public:
|
||||
int GetZDockPercent() const;
|
||||
int GetZPercent() const;
|
||||
|
||||
void AttachGameWindow(HWND hGameWnd);
|
||||
void DetachGameWindow(BOOL bRestore = TRUE);
|
||||
BOOL IsGameWindowDocked() const;
|
||||
HWND GetDockedGameWindow() const;
|
||||
BOOL IsGameTabActive() const;
|
||||
void SelectXYTab();
|
||||
void SelectGameTab();
|
||||
void FocusGameWindow();
|
||||
void FocusXYWindow();
|
||||
|
||||
protected:
|
||||
enum {
|
||||
XYDOCK_TAB_XY = 0,
|
||||
XYDOCK_TAB_GAME = 1
|
||||
};
|
||||
|
||||
CTabCtrl m_wndTabs;
|
||||
CWnd m_wndXYPage;
|
||||
CGameDockWnd m_wndGamePage;
|
||||
|
||||
CXYMenuBar m_wndMenuBar;
|
||||
CXYMDIContainerWnd m_wndMDIContainer;
|
||||
CToolBar *m_pToolBar;
|
||||
bool m_bInLayout;
|
||||
int m_nActiveTab;
|
||||
|
||||
void SetActiveTab(int nTab);
|
||||
void ShowActiveTab();
|
||||
CWnd *GetXYPageParent() const;
|
||||
|
||||
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
|
||||
afx_msg void OnSize(UINT nType, int cx, int cy);
|
||||
afx_msg BOOL OnEraseBkgnd(CDC *pDC);
|
||||
afx_msg LRESULT OnIdleUpdateCmdUI(WPARAM wParam, LPARAM lParam);
|
||||
afx_msg void OnTabSelChange(NMHDR *pNMHDR, LRESULT *pResult);
|
||||
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
|
||||
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT *pResult);
|
||||
virtual BOOL OnCmdMsg(UINT nID, int nCode, void *pExtra, AFX_CMDHANDLERINFO *pHandlerInfo);
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"mapspath" "w:\doom\base\maps"
|
||||
"bsp" ""
|
||||
"bsp noflood" ""
|
||||
"bsp shadowOpt 2" ""
|
||||
"bsp noaas" ""
|
||||
"bspext" ""
|
||||
"bspext noflood" ""
|
||||
"autosave" "c:\autosave.map"
|
||||
"autosave1" "c:\autosave1.map"
|
||||
"autosave2" "c:\autosave2.map"
|
||||
"texturepath" "w:\doom\base\textures"
|
||||
"entitypath" "w:\doom\base\scripts\*.def"
|
||||
"remotebasepath" "w:\doom\base"
|
||||
"rshcmd" ""
|
||||
"basepath" "w:\doom\base"
|
||||
"brush_primit" "1"
|
||||
}
|
||||
Reference in New Issue
Block a user