Jump to content

Transparency Check for Images


Recommended Posts

  • Premium

M2 Download Center

This is the hidden content, please
( Internal )

Hi there devs,

 

Probably the most of us know the problem when an image contains alpha/fully transparent parts but you can't click trough them and it would be very necessary to do so. This problem is very common with the taskbars, for example with the ilumina taskbar (you know when it looks like you are clicking the ground, but the image is still there but that part is transparent).

Video:

How to:

EterPythonLib\PythonWindow.h
 
Spoiler

After this:



				FLAG_RTL				= (1 << 11),	// Right-to-left

Add this:



				FLAG_ALPHA_SENSITIVE	= (1 << 12),	// flag for activating alpha sensitive

Then above this:



		public:
			CWindow(PyObject * ppyObject);
			virtual ~CWindow();

Add this:



			enum WindowTypes // window type flags to recognize expanded_image class
			{
				WINDOW_TYPE_WINDOW,
				WINDOW_TYPE_EX_IMAGE,

				WINDOW_TYPE_MAX_NUM
			};

Under this:



			int				GetChildCount()	{ return m_pChildList.size(); }

Add this:



			void			IsTransparentOnPixel(long* x, long* y, bool* ret);

Under this:



			TWindowContainer	m_pReserveChildList;

Add this:



			BYTE				m_windowType; // to recognize window type

In the class CExpandedImageBox : public CImageBox class after this:



			void SetRenderingMode(int iMode);

Add this:



			D3DXCOLOR GetPixelColor(int x, int y) { if (m_pImageInstance) return m_pImageInstance->GetPixelColor(x, y); else return D3DXCOLOR(0, 0, 0, 0); }

 

EterPythonLib\PythonWindowManagerModule.cpp
Spoiler

After this:



		else if (!stricmp(pszFlag, "ltr"))
			pWin->RemoveFlag(UI::CWindow::FLAG_RTL);

Add this:



		else if (!stricmp(pszFlag, "alpha_sensitive"))
			pWin->AddFlag(UI::CWindow::FLAG_ALPHA_SENSITIVE);

 

EterPythonLib\PythonWindow.cpp

Spoiler

In function CWindow::CWindow(PyObject * ppyObject) after this:



		m_limitBiasRect.bottom = m_limitBiasRect.left = m_limitBiasRect.right = m_limitBiasRect.top = 0;

Add this:



		m_windowType = WINDOW_TYPE_WINDOW; // setting all window type to window first

In function CWindow * CWindow::PickWindow(long x, long y) after this:



		if (IsFlag(CWindow::FLAG_NOT_PICK))
			return NULL;

Add this:



		if (IsFlag(CWindow::FLAG_ALPHA_SENSITIVE)) // check flag
		{
			bool isFullTransparent = true;
			IsTransparentOnPixel(&x, &y, &isFullTransparent); // check transparency of the clicking position
			if (isFullTransparent)
				return NULL; // if transparent then return nothing, else give current window
		}

Then above this:



	CWindow * CWindow::PickTopWindow(long x, long y)
	{

Add this:



	void CWindow::IsTransparentOnPixel(long* x, long* y, bool* ret)
	{
		if (IsShow() && IsIn(*x, *y)) // check if the window is active and the cursor is in the window
		{
			if (m_windowType == WINDOW_TYPE_EX_IMAGE) // check if its an expanded_image
			{
				D3DXCOLOR pixel = ((CExpandedImageBox*)this)->GetPixelColor(*x - m_rect.left, *y - m_rect.top); // get current pixel color

				if ((BYTE)pixel.a != 0) // if the pixel is not trasparent then the whole window is not trasparent
				{
					*ret = false;
					return;
				}
			}
			else if (m_pChildList.empty()) // if its not ex_image and has no child then its NOT transparent [default for other components]
			{
				*ret = false;
				return;
			}
		}
		if (!m_pChildList.empty()) // check if all the childs are trasparent on the current position
		{
			std::list<CWindow *>::reverse_iterator ritor = m_pChildList.rbegin();
			for (; ritor != m_pChildList.rend(); ritor++)
			{
				(*ritor)->IsTransparentOnPixel(x, y, ret);
				if (!*ret)
					return;
			}
		}
	}

In the CWindow * CWindow::PickTopWindow(long x, long y) function replace this:



						return pWin;

With this:



					{
						if (pWin->IsFlag(CWindow::FLAG_ALPHA_SENSITIVE)) // if the window is alpha sensitive check the alpha
						{
							bool isFullTransparent = true;
							pWin->IsTransparentOnPixel(&x, &y, &isFullTransparent);
							if (isFullTransparent) // if the window is transparent at the coordinates then its not the top window
								continue;
						}
						return pWin;
					}

Then replace this:



	CExpandedImageBox::CExpandedImageBox(PyObject * ppyObject) : CImageBox(ppyObject)
	{
	}

With this:



	CExpandedImageBox::CExpandedImageBox(PyObject * ppyObject) : CImageBox(ppyObject)
	{
		m_windowType = WINDOW_TYPE_EX_IMAGE;
	}

 

EterLib\GrpImageTexture.cpp

Spoiler

In the function bool CGraphicImageTexture::CreateFromMemoryFile(UINT bufSize, const void * c_pvBuf, D3DFORMAT d3dFmt, DWORD dwFilter) replace this:



		if (FAILED(D3DXCreateTextureFromFileInMemoryEx(
					ms_lpd3dDevice,
					c_pvBuf,
					bufSize,
					D3DX_DEFAULT,
					D3DX_DEFAULT,
					D3DX_DEFAULT,
					0,
					d3dFmt,
					D3DPOOL_MANAGED,
					dwFilter,
					dwFilter,
					0xffff00ff,
					&imageInfo,
					NULL,
					&m_lpd3dTexture)))
		{
			TraceError("CreateFromMemoryFile: Cannot create texture");
			return false;
		}

With this:



		if (FAILED(D3DXGetImageInfoFromFileInMemory(c_pvBuf, bufSize, &imageInfo))) //first get the imageinfo (reason: sizes needed)
		{
			TraceError("CreateFromMemoryFile: Cannot GetImageInfo from texture");
			return false;
		}
		if (FAILED(D3DXCreateTextureFromFileInMemoryEx(
					ms_lpd3dDevice,
					c_pvBuf,
					bufSize,
					imageInfo.Width, // using the correct filesizes here will result that the maximum mipmap size will be the file's original size: its necessary for the alpha sensitive,
					imageInfo.Height, // cous otherwise it reads wrong picture colors since the image will be resized in the result of mipmap generation
					D3DX_DEFAULT,     // also it will improve the quality of the images with a little
					0,
					d3dFmt,
					D3DPOOL_MANAGED,
					dwFilter,
					dwFilter,
					0xffff00ff,
					NULL, //we already have our image info, doesn't need to get it again
					NULL,
					&m_lpd3dTexture)))
		{
			TraceError("CreateFromMemoryFile: Cannot create texture");
			return false;
		}

 

EterLib\GrpImageInstance.h

Spoiler

After this:



		bool operator == (const CGraphicImageInstance & rhs) const;

Add this:



		D3DXCOLOR GetPixelColor(int x, int y);

 

EterLib\GrpImageInstance.cpp

Spoiler

Add this to the end of the file:



D3DXCOLOR CGraphicImageInstance::GetPixelColor(int x, int y)
{
	// we first need the d3d texture, but its the "shortest" way to get it
	D3DXCOLOR dxClr = D3DXCOLOR(0, 0, 0, 0);
	CGraphicImage * pImage = m_roImage.GetPointer();
	if (!pImage)
		return dxClr;
	CGraphicTexture * pTexture = pImage->GetTexturePointer();
	if (!pTexture)
		return dxClr;

	LPDIRECT3DTEXTURE8 d3dTexture = pTexture->GetD3DTexture();
	if (!d3dTexture)
		return dxClr;

	IDirect3DSurface8* surface;
	D3DSURFACE_DESC desc;
	D3DLOCKED_RECT rect;
	RECT rc;

	// we want just want to lock only one pixel
	rc.left = x;
	rc.right = x + 1;
	rc.top = y;
	rc.bottom = y + 1;

	if (FAILED(d3dTexture->GetSurfaceLevel(0, &surface))) // get the top surface of the image (it contains the whole image)
		return dxClr;
	if (FAILED(surface->GetDesc(&desc)))
		return dxClr;
	if (FAILED(surface->LockRect(&rect, &rc, D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK))) // lock the pixel
		return dxClr;

	PBYTE dwTexel = (PBYTE)rect.pBits;

	switch (desc.Format)
	{
	// there are several possible image formats, but its the most common one and as I saw its more than enough
	case D3DFMT_A8R8G8B8:
		dxClr.a = dwTexel[3];
		dxClr.r = dwTexel[2];
		dxClr.g = dwTexel[1];
		dxClr.b = dwTexel[0];
		break;
	}
	surface->UnlockRect(); // unlock the pixel for further using (like render)

	return dxClr;
}

 

By default it won't check the alpha value, so it means that you have to add manually the "alpha_sensitive" flag to the preferred windows/objects (also note that its only effective with an expandedImageBox object and it has some interference with the "float" flag (if both added to the same object)). For the usage check the video. If you have any question, remark, or anything that you like to ask or suggest, feel free to post it here, or send it in PM.

Have a nice day,
~masodikbela

  • Metin2 Dev 16
  • Think 1
  • Good 2
  • Love 1
  • Love 30

The one and only UI programming guideline

Link to comment
Share on other sites

  • 1 month later...
  • Premium
9 hours ago, Shang said:

There is a bug with scaled images, look at this gif:

01f346e1a1.gif

Does the window have "float" flag anywhere? Because it looks like the same when you add "float" to a window. Also as far as I remember it should work with scaled windows...

Edited by Metin2 Dev
Core X - External 2 Internal

The one and only UI programming guideline

Link to comment
Share on other sites

  • 5 years later...

Announcements



×
×
  • 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.