Jump to content
For maintenance and updates, the community will be offline on 31 December 2022 ×
!-->
  • 0

Change resolution in realtime


Helia01

Question

  • Silver

Hi, m2dev!
The game cannot change the screen resolution in real time (as is done in most new games).
I started trying to implement this function, but I do not know how to change the screen resolution correctly.

 

//UserInterface/PythonApplication.cpp
//Original code.
unsigned __GetWindowMode(bool windowed)
{
	if (windowed)
		return WS_OVERLAPPED | WS_CAPTION |   WS_SYSMENU | WS_MINIMIZEBOX;

	return WS_POPUP;
}

//Change code
unsigned __GetWindowMode(bool windowed)
{
	if (windowed)
		return WS_TILEDWINDOW;

	return WS_POPUP;
}


In fact, the developers of this game laid the foundation for changing the resolution in real time. This is understandable if you open the file: UserInterface/PythonApplicationProcedure.cpp and find the function: 

//UserInterface/PythonApplicationProcedure.cpp
//seacrh function: LRESULT CPythonApplication::WindowProcedure(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
//We should be interested in this section
		case WM_SIZE:
			switch (wParam)
			{
				case SIZE_RESTORED:
				case SIZE_MAXIMIZED:
					{
						RECT rcWnd; 
						GetClientRect(&rcWnd); 
				
						UINT uWidth=rcWnd.right-rcWnd.left; 
						UINT uHeight=rcWnd.bottom-rcWnd.left; 
						m_grpDevice.ResizeBackBuffer(uWidth, uHeight);			
					}
					break;
			}

			if (wParam==SIZE_MINIMIZED)
				m_isMinimizedWnd=true;
			else
				m_isMinimizedWnd=false;

			OnSizeChange(short(LOWORD(lParam)), short(HIWORD(lParam)));

			break;

		case WM_EXITSIZEMOVE:  
			{
				RECT rcWnd; 
				GetClientRect(&rcWnd); 
				
				UINT uWidth=rcWnd.right-rcWnd.left; 
				UINT uHeight=rcWnd.bottom-rcWnd.left; 
				m_grpDevice.ResizeBackBuffer(uWidth, uHeight);				
				OnSizeChange(short(LOWORD(lParam)), short(HIWORD(lParam)));
			}
			break; 

//UserInterface/PythonApplicationEvent.cpp (We should be interested in the function: OnSizeChange)
void CPythonApplication::OnSizeChange(int width, int height)
{
  //Here it is necessary to implement a change in the size of GUI and etc...
}


If you leave everything in this form, then changing the screen resolution will be incorrect. The game will simply stretch the contents of the window to our screen resolution. This is not what it should be.
It looks ugly.


250921resize-window-in-realtime.gif

 

Please tell me how to properly handle the change in screen resolution in real time in the function: OnSizeChange?

  • Love 3
  • Think 2
Link to comment
Share on other sites

6 answers to this question

Recommended Posts

  • 0
  • Moderator

Hello,

Just for the record, the same thing happens when you Windows + Arrow left or right when you have two monitors with different resolutions, or when you change your DPI (Even when I've updated the method to handle the DPI change it still did the same).

  • Metin2 Dev 1

Gurgarath
coming soon

Link to comment
Share on other sites

  • 0

Up, this looks interesting. Maybe someone who has the knowledge can help us

This needs a function that resizes the GUI (inventory window/character window/chat/minimap/etc) and one that fixes the font display when resizing.

 

Edited by SCOOB
  • Metin2 Dev 1
Link to comment
Share on other sites

  • 0
  • Nitro Booster

This is actually something interesting to implement in the client with a drop-down menu because all modern games are now using this type of in-game setting.

Changing the size of the window is relatively easy but the biggest issue is that it will distort every texture, font and any type of graphical objects in the client. Since we are talking about Metin2 it will not be that easy task in my point of view because changing the resolution of the entire game isn’t so easy in DirectX as in OpenGL because you need to reset the device in DirectX and doing this it will mess the anti-analyzing of the terrain textures, you can call it the “famous UAC bug” (and that happens because when the screen is black/lost it will reset itself) and that’s just one problem. The worst part is all graphical elements in the client getting distorted like fonts. I’m not an expert in DirectX but I assume you would have to reset the *ms_lpd3dDevice device and render the entire graphical objects again. I did try to play around with CGraphicDevice and ms_matScreen2 but the results weren’t so good as expected.

Edited by Owsap
  • Metin2 Dev 1
  • Love 2
Link to comment
Share on other sites

  • 0
  • Silver

I want to make this game better, and I'm very glad that many people are also interested in it
I hope even more people will respond to this post.

Edited by Helia01
  • Love 1
Link to comment
Share on other sites

  • 0
  • Silver
4 hours ago, Owsap said:

This is actually something interesting to implement in the client with a drop-down menu because all modern games are now using this type of in-game setting.

Changing the size of the window is relatively easy but the biggest issue is that it will distort every texture, font and any type of graphical objects in the client. Since we are talking about Metin2 it will not be that easy task in my point of view because changing the resolution of the entire game isn’t so easy in DirectX as in OpenGL because you need to reset the device in DirectX and doing this it will mess the anti-analyzing of the terrain textures, you can call it the “famous UAC bug” (and that happens because when the screen is black/lost it will reset itself) and that’s just one problem. The worst part is all graphical elements in the client getting distorted like fonts. I’m not an expert in DirectX but I assume you would have to reset the *ms_lpd3dDevice device and render the entire graphical objects again. I did try to play around with CGraphicDevice and ms_matScreen2 but the results weren’t so good as expected.



I tried to use the function

int CPythonApplication::CheckDeviceState()
{
	CGraphicDevice::EDeviceState e_deviceState = m_grpDevice.GetDeviceState();

	switch (e_deviceState)
	{
	case CGraphicDevice::DEVICESTATE_NULL:
		return DEVICE_STATE_FALSE;

	case CGraphicDevice::DEVICESTATE_BROKEN:
		return DEVICE_STATE_SKIP;

	case CGraphicDevice::DEVICESTATE_NEEDS_RESET: // <-- Looks good?
		if (!m_grpDevice.Reset())
			return DEVICE_STATE_SKIP;

		break;
	}

	return DEVICE_STATE_OK;
}


After resizing, the device does not return the DEVICESTATE_NEEDS_RESET status
Then I tried to implement it in this stupid way.
 

//UserInterface/PythonApplication.cpp
bool CPythonApplication::ResetDevice()
{
	return m_grpDevice.Reset();
}

//UserInterface/PythonSystem.cpp
void CPythonSystem::SetWidth(DWORD width)
{
	m_Config.width = width;
}

void CPythonSystem::SetHeight(DWORD height)
{
	m_Config.height = height;
}

//UserInterface/PythonApplicationEvent.cpp
void CPythonApplication::OnSizeChange(int width, int height)
{
	//Check change size...
	if (width > 0 && height > 0 && m_pySystem.GetWidth() != width && m_pySystem.GetHeight() != height)
	{
		TraceError("CPythonApplication::OnSizeChange(width: %d, height: %d)", width, height);
		bool reset_status = CPythonApplication::ResetDevice();
		TraceError("reset_status: %d", reset_status);
		if (reset_status)
		{
			bool Windowed = CPythonSystem::Instance().IsWindowed() ? 1 : 0;
			m_pySystem.SetWidth(width);
			m_pySystem.SetHeight(height);
			//UI::CWindowManager::Instance().SetScreenSize(width, height);
			if (!CreateDevice(m_pySystem.GetWidth(), m_pySystem.GetHeight(), Windowed, m_pySystem.GetBPP(), m_pySystem.GetFrequency()))
			{
				TraceError("Error create device!");
				return;
			}

			TraceError("CreateDevice success!");

			
		}
	}
}



/*
In syserr

0926 01:21:08609 :: CPythonApplication::OnSizeChange(width: 1079, height: 686)
0926 01:21:08609 :: reset_status: 1
0926 01:21:08854 :: CreateDevice success!
*/

 

Since I do not know how to do it correctly, I only know the minimal theory. I try a wide variety of ideas.
Apparently, this is done much more difficult than we think...

I get two possible options in my tests.
1. It is possible to reset the device and create a new one. (for example, in the login and password entry menu). Then I get just a black screen.
2. The device cannot be reset (directly in the game).


Sorry if I'm writing some stupid code. (never worked with directx)
I believe that it is better to try something at least than to ignore this topic.

Edited by Helia01
  • Love 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.