CCursorController - Easy and Simple Cursor Controller v0.2

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

CCursorController - Easy and Simple Cursor Controller v0.2

Post by MasterGod »

I've created it for my engine but I feel I must share it here too.
Compiled with irrlicht 1.4 but should work with previous and future versions without many or even no modifications at all.
In short the features are:
OS's cursor - Hide/Show
Custom cursor - Hide/Show
Have more then 1 custom cursor with the ability to switch between them with their indexes.

Usage example:

Code: Select all

CCursorController* CC = new CCursorController(irrDevice->getCursorControl(), irrDevice->getVideoDriver());
...
delete CC;
Some notes:
1. Custom cursors must be in power of 2 (e.g 32x32, 64x32) images.
2. I'm open to any suggestion about improvements.
3. The license is the same as my engine's.
4. The last cursor loaded via addMouseCursorTexture() will be the first one active.

Enough talking..

CCursorController.h

Code: Select all

// Copyright (c) 2007-2008 Tomer Nosrati
// This file is part of the "NUSoftware Game Engine".
// For conditions of distribution and use, see copyright notice in nge.h

#ifndef __C_CURSOR_H__
#define __C_CURSOR_H__

#include "irrlicht.h"

using namespace irr;
using namespace irr::core;
using namespace irr::gui;
using namespace irr::scene;
using namespace irr::video;

//! Cursor controller v0.2
/*! This class controls the cursor. You can choose to use the OS's cursor, a custom
cursor or both. You can also have many custom cursors and switch between them easily.
*/
class CCursorController
{
public:
	CCursorController(ICursorControl* irrCursor, IVideoDriver* irrVideoDriver);
	~CCursorController();

	void setVisible(bool visible);
	bool isVisible() const;
	void setOSCursorVisible(bool visible);
	bool isOSCursorVisible() const;

	void render();
	void addMouseCursorTexture(c8* Cursor_file);
	ITexture* getCursorTexture(u32 index) const;
	void removeCursor(u32 index);
	void setActiveCursor(u32 index);
	void Clear();
	position2di& getMousePos();

private:
	position2di& updateMousePos();

	bool IsOSCursorVisible;
	bool IsVisible;
	position2di m_MousePos;
	ICursorControl* irrCursorControl;
	IVideoDriver* videoDriver;
	array<ITexture*> m_aMouseCursors;
	ITexture* m_pMouseCursor;

	u32 used;
};
#endif // __C_CURSOR_H__
CCursorController.cpp

Code: Select all

#include "CCursorController.h"

CCursorController::CCursorController(ICursorControl* irrCursor, IVideoDriver* irrVideoDriver) : 
m_pMouseCursor(0), used(0), irrCursorControl(irrCursor), videoDriver(irrVideoDriver)
{
	updateMousePos();

	setVisible(true);
	setOSCursorVisible(false);
}

CCursorController::~CCursorController()
{
	Clear();
}

void CCursorController::setVisible(bool visible)
{
	IsVisible = visible;
}

bool CCursorController::isVisible() const
{
	return IsVisible;
}

void CCursorController::setOSCursorVisible(bool visible)
{
	IsOSCursorVisible = visible;
}

bool CCursorController::isOSCursorVisible() const
{
	return IsOSCursorVisible;
}

void CCursorController::render()
{
	updateMousePos();

	if(isVisible() && used)
	{
		_IRR_DEBUG_BREAK_IF(!m_pMouseCursor); // There isn't any cursor texture loaded 
		if(m_pMouseCursor)
		{
			videoDriver->draw2DImage(m_pMouseCursor,
				position2di(m_MousePos.X - m_pMouseCursor->getSize().Width/2+1,
				m_MousePos.Y - m_pMouseCursor->getSize().Height/2+2),
				rect<s32>(position2di(0,0),m_pMouseCursor->getSize()), 
				0, SColor(255,255,255,255), true);
		}
	}

	if(isOSCursorVisible())
	{
		irrCursorControl->setVisible(true);
		irrCursorControl->setPosition(irrCursorControl->getPosition());
	}
	else
	{
		irrCursorControl->setVisible(false);
		irrCursorControl->setPosition(irrCursorControl->getPosition());
	}
}

void CCursorController::addMouseCursorTexture(c8* Cursor_file)
{
	m_pMouseCursor = videoDriver->getTexture(Cursor_file);
	
	bool isAlreadyLoaded = false;
	for(u32 i = 0; i < m_aMouseCursors.size() && !isAlreadyLoaded; i++)
	{
		if(m_aMouseCursors[i]->getName() == m_pMouseCursor->getName())
		{
			isAlreadyLoaded = !isAlreadyLoaded;
			break;
		}
	}

	if (!isAlreadyLoaded)
	{
		videoDriver->makeColorKeyTexture(m_pMouseCursor, SColor(255,0,0,0));

		m_aMouseCursors.push_back(m_pMouseCursor);
		used++;
	}

	// So the first loaded cursor will be active
	if(used > 0)
		setActiveCursor(0);
}

ITexture* CCursorController::getCursorTexture(u32 index) const
{
	_IRR_DEBUG_BREAK_IF(index>used); // access violation

	return m_aMouseCursors[index];
}

void CCursorController::removeCursor(u32 index)
{
	_IRR_DEBUG_BREAK_IF(index>used); // access violation

	videoDriver->removeTexture(m_aMouseCursors[index]);
	m_aMouseCursors.erase(index);
	used--;
}

void CCursorController::setActiveCursor(u32 index)
{
	_IRR_DEBUG_BREAK_IF(index>used); // access violation

	m_pMouseCursor = m_aMouseCursors[index];
}

void CCursorController::Clear()
{
	for(u32 i = 0; i < m_aMouseCursors.size(); i++)
	{
		removeCursor(i);
	}

	m_aMouseCursors.clear();
}

position2di& CCursorController::getMousePos()
{
	return updateMousePos();
}

position2di& CCursorController::updateMousePos()
{
	m_MousePos = irrCursorControl->getPosition();

	return m_MousePos;
}
Last edited by MasterGod on Wed Jan 30, 2008 8:17 pm, edited 1 time in total.
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
Frosty Topaz
Posts: 107
Joined: Sat Nov 04, 2006 9:42 pm

Post by Frosty Topaz »

It appears that the custom cursor you draw is centered over the cursor location.

Code: Select all

      if(m_pMouseCursor)
      {
         videoDriver->draw2DImage(m_pMouseCursor,
            position2di(m_MousePos.X - m_pMouseCursor->getSize().Width/2+1,
            m_MousePos.Y - m_pMouseCursor->getSize().Height/2+2),
            rect<s32>(position2di(0,0),m_pMouseCursor->getSize()),
            0, SColor(255,255,255,255), true);
      }
I've had problems with this kind of thing. I've found the GUI wont pick up clicks properly as the image of the cursor is being clicked on, not the GUI elements underneath it. Did you find a work-around? Or have you not seen this problem?
Frosty Topaz
=========
It isn't easy being ice-encrusted aluminum silicate fluoride hydroxide...
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

Frosty Topaz wrote:I've had problems with this kind of thing. I've found the GUI wont pick up clicks properly as the image of the cursor is being clicked on, not the GUI elements underneath it. Did you find a work-around? Or have you not seen this problem?
I haven't seen it but I'll check it, thanks.

Edit:
Maybe deleting - not drawing the pixel that is checked will fix it..
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
Frosty Topaz
Posts: 107
Joined: Sat Nov 04, 2006 9:42 pm

Post by Frosty Topaz »

I usually just have the cursor point to a corner and move the image over a pixel when I draw.
Frosty Topaz
=========
It isn't easy being ice-encrusted aluminum silicate fluoride hydroxide...
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

Frosty Topaz wrote:I usually just have the cursor point to a corner and move the image over a pixel when I draw.
Well that forces you for a arrow like cursors.. this class should be generic for any type of cursor image.

Maybe someone knows how to undraw the checked pixel so it wont interfere the GUI?
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

@Frosty Topaz: It doesn't interfere the GUI.. It uses ITextures.
I haven't checked if it Does or not but it shouldn't as bitplane said to me (on IRC) because it uses ITextures and not IGUIImages so its ok.

Did you actually used this class and had this problem or you just guess?
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
Frosty Topaz
Posts: 107
Joined: Sat Nov 04, 2006 9:42 pm

Post by Frosty Topaz »

I've done similar things and had that problem. So I guessed it might have popped up for you.
Frosty Topaz
=========
It isn't easy being ice-encrusted aluminum silicate fluoride hydroxide...
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

New version, v0.2.
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
Post Reply