Show how to modify cursors and offer some useful tool-functions for creating cursors. It can also be used for experiments with the mouse in general.
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#endif
const int DELAY_TIME = 3000;
enum ETimerAction
{
ETA_MOUSE_VISIBLE,
ETA_MOUSE_INVISIBLE,
};
Main header file of the irrlicht, the only file needed to include.
Everything in the Irrlicht Engine can be found in this namespace.
Structure to allow delayed execution of some actions.
struct TimerAction
{
ETimerAction Action;
};
unsigned int u32
32 bit unsigned variable.
struct SAppContext
{
SAppContext()
: Device(0), InfoStatic(0), EventBox(0), CursorBox(0), SpriteBox(0)
, ButtonSetVisible(0), ButtonSetInvisible(0), ButtonSimulateBadFps(0)
, ButtonChangeIcon(0)
, SimulateBadFps(false)
{
}
void update()
{
if (!Device)
return;
u32 timeNow = Device->getTimer()->getTime();
for (
u32 i=0; i < TimerActions.size(); ++i )
{
if ( timeNow >= TimerActions[i].TargetTime )
{
runTimerAction(TimerActions[i]);
TimerActions.erase(i);
}
else
{
++i;
}
}
}
void runTimerAction(const TimerAction& action)
{
if (ETA_MOUSE_VISIBLE == action.Action)
{
Device->getCursorControl()->setVisible(true);
ButtonSetVisible->setEnabled(true);
}
else if ( ETA_MOUSE_INVISIBLE == action.Action)
{
Device->getCursorControl()->setVisible(false);
ButtonSetInvisible->setEnabled(true);
}
}
Add another icon which the user can click and select as cursor later on.
void addIcon(const stringw& name, const SCursorSprite &sprite, bool addCursor=true)
{
SpriteBox->addItem(name.c_str(), sprite.SpriteId);
Sprites.push_back(sprite);
if ( addCursor )
{
Here we create a hardware cursor from a sprite
Device->getCursorControl()->addIcon(sprite);
CursorBox->addItem(name.c_str());
}
}
array<TimerAction> TimerActions;
bool SimulateBadFps;
array<SCursorSprite> Sprites;
};
The Irrlicht device. You can create it with createDevice() or createDeviceEx().
Default list box GUI element.
Multi or single line text label.
Helper function to print mouse event names into a stringw
void PrintMouseEventName(
const SEvent& event, stringw &result)
{
{
case EMIE_LMOUSE_PRESSED_DOWN: result += stringw(L"EMIE_LMOUSE_PRESSED_DOWN"); break;
case EMIE_RMOUSE_PRESSED_DOWN: result += stringw(L"EMIE_RMOUSE_PRESSED_DOWN"); break;
case EMIE_MMOUSE_PRESSED_DOWN: result += stringw(L"EMIE_MMOUSE_PRESSED_DOWN"); break;
case EMIE_LMOUSE_LEFT_UP: result += stringw(L"EMIE_LMOUSE_LEFT_UP"); break;
case EMIE_RMOUSE_LEFT_UP: result += stringw(L"EMIE_RMOUSE_LEFT_UP"); break;
case EMIE_MMOUSE_LEFT_UP: result += stringw(L"EMIE_MMOUSE_LEFT_UP"); break;
case EMIE_MOUSE_MOVED: result += stringw(L"EMIE_MOUSE_MOVED"); break;
case EMIE_MOUSE_WHEEL: result += stringw(L"EMIE_MOUSE_WHEEL"); break;
case EMIE_LMOUSE_DOUBLE_CLICK: result += stringw(L"EMIE_LMOUSE_DOUBLE_CLICK"); break;
case EMIE_RMOUSE_DOUBLE_CLICK: result += stringw(L"EMIE_RMOUSE_DOUBLE_CLICK"); break;
case EMIE_MMOUSE_DOUBLE_CLICK: result += stringw(L"EMIE_MMOUSE_DOUBLE_CLICK"); break;
case EMIE_LMOUSE_TRIPLE_CLICK: result += stringw(L"EMIE_LMOUSE_TRIPLE_CLICK"); break;
case EMIE_RMOUSE_TRIPLE_CLICK: result += stringw(L"EMIE_RMOUSE_TRIPLE_CLICK"); break;
case EMIE_MMOUSE_TRIPLE_CLICK: result += stringw(L"EMIE_MMOUSE_TRIPLE_CLICK"); break;
default:
break;
}
}
SEvents hold information about an event. See irr::IEventReceiver for details on event handling.
struct SMouseInput MouseInput
Helper function to print all the state information which get from a mouse-event into a stringw
void PrintMouseState(
const SEvent& event, stringw &result)
{
result += stringw(L"X: ");
result += stringw(L"\n");
result += stringw(L"Y: ");
result += stringw(L"\n");
result += stringw(L"Wheel: ");
result += stringw(L"\n");
result += stringw(L"Shift: ");
result += stringw(L"true\n");
else
result += stringw(L"false\n");
result += stringw(L"Control: ");
result += stringw(L"true\n");
else
result += stringw(L"false\n");
result += stringw(L"ButtonStates: ");
result += stringw(L"\n");
result += stringw(L"isLeftPressed: ");
result += stringw(L"true\n");
else
result += stringw(L"false\n");
result += stringw(L"isRightPressed: ");
result += stringw(L"true\n");
else
result += stringw(L"false\n");
result += stringw(L"isMiddlePressed: ");
result += stringw(L"true\n");
else
result += stringw(L"false\n");
result += stringw(L"Event: ");
PrintMouseEventName(event, result);
result += stringw(L"\n");
}
A typical event receiver.
{
public:
MyEventReceiver(SAppContext & context) : Context(context) { }
virtual bool OnEvent(
const SEvent& event)
{
{
{
case EGET_BUTTON_CLICKED:
{
u32 timeNow = Context.Device->getTimer()->getTime();
TimerAction action;
action.TargetTime = timeNow + DELAY_TIME;
{
action.Action = ETA_MOUSE_VISIBLE;
Context.TimerActions.push_back(action);
Context.ButtonSetVisible->setEnabled(false);
}
{
action.Action = ETA_MOUSE_INVISIBLE;
Context.TimerActions.push_back(action);
Context.ButtonSetInvisible->setEnabled(false);
}
{
Context.SimulateBadFps = Context.ButtonSimulateBadFps->isPressed();
}
{
Interface of an object which can receive events.
gui::IGUIElement * Caller
IGUIElement who called the event.
gui::EGUI_EVENT_TYPE EventType
Type of GUI Event.
struct SGUIEvent GUIEvent
Replace an existing cursor icon by another icon. The user has to select both - the icon which should be replaced and the icon which will replace it.
s32 selectedCursor = Context.CursorBox->getSelected();
s32 selectedSprite = Context.SpriteBox->getSelected();
if ( selectedCursor >= 0 && selectedSprite >= 0 )
{
signed int s32
32 bit signed variable.
This does replace the icon.
Context.Device->getCursorControl()->changeIcon((ECURSOR_ICON)selectedCursor, Context.Sprites[selectedSprite] );
Do also show the new icon.
Context.Device->getCursorControl()->setActiveIcon( ECURSOR_ICON(selectedCursor) );
}
}
}
break;
{
{
@ EGET_LISTBOX_SELECTED_AGAIN
An item in the listbox was selected, which was already selected.
@ EGET_LISTBOX_CHANGED
A new item in a listbox was selected.
Find out which cursor the user selected
s32 selected = Context.CursorBox->getSelected();
if ( selected >= 0 )
{
Here we set the new cursor icon which will now be used within our window.
Context.Device->getCursorControl()->setActiveIcon( ECURSOR_ICON(selected) );
}
}
}
break;
default:
break;
}
}
if (event.
EventType == EET_MOUSE_INPUT_EVENT)
{
PrintMouseState(event, infoText);
Context.InfoStatic->setText(infoText.c_str());
{
infoText = L"";
PrintMouseEventName(event, infoText);
Context.EventBox->insertItem(0, infoText.c_str(), -1);
}
}
return false;
}
private:
SAppContext & Context;
};
string< wchar_t > stringw
Typedef for wide character strings.
Use several imagefiles as animation frames for a sprite which can be used as cursor icon. The images in those files all need to have the same size. Return sprite index on success or -1 on failure
{
if ( !spriteBank || !driver || !files.size() )
return -1;
if ( tex )
{
array< rect<s32> >& spritePositions = spriteBank->
getPositions();
u32 idxRect = spritePositions.size();
SGUISprite sprite;
sprite.frameTime = frameTime;
array< SGUISprite >& sprites = spriteBank->
getSprites();
for (
u32 f=0; f < files.size(); ++f )
{
if ( tex )
{
sprite.Frames.push_back( frame );
}
}
sprites.push_back( sprite );
return sprites.size()-1;
}
return -1;
}
T Width
Width of the dimension.
T Height
Height of the dimension.
virtual core::array< SGUISprite > & getSprites()=0
Returns the array of animated sprites within the sprite bank.
virtual u32 getTextureCount() const =0
Returns the number of textures held by the sprite bank.
virtual void addTexture(video::ITexture *texture)=0
Adds a texture to the sprite bank.
virtual core::array< core::rect< s32 > > & getPositions()=0
Returns the list of rectangles held by the sprite bank.
Interface of a Video Driver dependent Texture.
virtual const core::dimension2d< u32 > & getSize() const =0
Get dimension (=size) of the texture.
Interface to driver which is able to perform 2d and 3d graphics functions.
virtual ITexture * getTexture(const io::path &filename)=0
Get access to a named texture.
Use several images within one imagefile as animation frames for a sprite which can be used as cursor icon The sizes of the icons within that file all need to have the same size Return sprite index on success or -1 on failure
{
if ( !spriteBank || !driver || !rects.size() )
return -1;
if ( tex )
{
array< rect<s32> >& spritePositions = spriteBank->
getPositions();
u32 idxRect = spritePositions.size();
SGUISprite sprite;
sprite.frameTime = frameTime;
array< SGUISprite >& sprites = spriteBank->
getSprites();
for (
u32 i=0; i < rects.size(); ++i )
{
spritePositions.push_back( rects[i] );
sprite.Frames.push_back( frame );
}
sprites.push_back( sprite );
return sprites.size()-1;
}
return -1;
}
Create a non-animated icon from the given file and position and put it into the spritebank. We can use this icon later on in a cursor.
{
if ( !spriteBank || !driver )
return -1;
if ( tex )
{
array< SGUISprite >& sprites = spriteBank->
getSprites();
SGUISprite sprite;
sprite.frameTime = 0;
sprite.Frames.push_back( frame );
sprites.push_back( sprite );
return sprites.size()-1;
}
return -1;
}
int main()
{
if (driverType==video::EDT_COUNT)
return 1;
if (device == 0)
return 1;
SAppContext context;
context.Device = device;
env->addStaticText (L"Cursor state information", rectInfoStatic, true, true);
context.InfoStatic = env->addStaticText (L"", rectInfoStatic, true, true);
env->addStaticText (L"click events (new on top)", rectEventBox, true, true);
context.EventBox = env->addListBox(rectEventBox);
env->addStaticText (L"cursors, click to set the active one", rectCursorBox, true, true);
context.CursorBox = env->addListBox(rectCursorBox);
env->addStaticText (L"sprites", rectSpriteBox, true, true);
context.SpriteBox = env->addListBox(rectSpriteBox);
context.ButtonSetVisible = env->addButton( rect<s32>( 410, 20, 560, 40 ), 0, -1, L"set visible (delayed)" );
context.ButtonSetInvisible = env->addButton( rect<s32>( 410, 50, 560, 70 ), 0, -1, L"set invisible (delayed)" );
context.ButtonSimulateBadFps = env->addButton( rect<s32>( 410, 80, 560, 100 ), 0, -1, L"simulate bad FPS" );
context.ButtonSimulateBadFps->setIsPushButton(true);
context.ButtonChangeIcon = env->addButton( rect<s32>( 410, 140, 560, 160 ), 0, -1, L"replace cursor icon\n(cursor+sprite must be selected)" );
for ( int i=0; i < (int)gui::ECI_COUNT; ++i )
{
context.CursorBox->addItem(
stringw( GUICursorIconNames[i] ).c_str());
}
virtual void setWindowCaption(const wchar_t *text)=0
Sets the caption of the window.
virtual void setResizable(bool resize=false)=0
Sets if the window should be resizable in windowed mode.
virtual video::IVideoDriver * getVideoDriver()=0
Provides access to the video driver for drawing 3d and 2d geometry.
virtual gui::IGUIEnvironment * getGUIEnvironment()=0
Provides access to the 2d user interface environment.
Axis aligned bounding box in 3d dimensional space.
u32 size() const
Get number of occupied elements of the array.
void push_back(const T &element)
Adds an element at back of array.
dimension2d< s32 > dimension2di
Typedef for an integer dimension.
E_DRIVER_TYPE
An enum for all types of drivers the Irrlicht Engine supports.
IRRLICHT_API IrrlichtDevice *IRRCALLCONV createDevice(video::E_DRIVER_TYPE deviceType=video::EDT_SOFTWARE, const core::dimension2d< u32 > &windowSize=(core::dimension2d< u32 >(640, 480)), u32 bits=16, bool fullscreen=false, bool stencilbuffer=false, bool vsync=false, IEventReceiver *receiver=0)
Creates an Irrlicht device. The Irrlicht device is the root object for using the engine.
Create sprites which then can be used as cursor icons.
SpriteBankIcons = env->addEmptySpriteBank(
io::path(
"cursor_icons"));
context.SpriteBox->setSpriteBank(SpriteBankIcons);
array< io::path > files;
files.push_back(
io::path(
"../../media/icon_crosshairs16x16bw1.png") );
files.push_back(
io::path(
"../../media/icon_crosshairs16x16bw2.png") );
files.push_back(
io::path(
"../../media/icon_crosshairs16x16bw3.png") );
files.push_back(
io::path(
"../../media/icon_crosshairs16x16bw3.png") );
files.push_back(
io::path(
"../../media/icon_crosshairs16x16bw2.png") );
SCursorSprite spriteBw;
spriteBw.SpriteId = AddAnimatedIconToSpriteBank( SpriteBankIcons, driver, files, 200 );
spriteBw.SpriteBank = SpriteBankIcons;
spriteBw.HotSpot = position2d<s32>(7,7);
context.addIcon(L"crosshair_bw", spriteBw);
array< rect<s32> > iconRects;
iconRects.push_back( rect<s32>(0,0, 16, 16) );
iconRects.push_back( rect<s32>(16,0, 32, 16) );
iconRects.push_back( rect<s32>(0,16, 16, 32) );
iconRects.push_back( rect<s32>(0,16, 16, 32) );
iconRects.push_back( rect<s32>(16,0, 32, 16) );
SCursorSprite spriteCol;
spriteCol.SpriteId = AddAnimatedIconToSpriteBank( SpriteBankIcons, driver,
io::path(
"../../media/icon_crosshairs16x16col.png"), iconRects, 200 );
spriteCol.HotSpot = position2d<s32>(7,7);
spriteCol.SpriteBank = SpriteBankIcons;
context.addIcon(L"crosshair_colored", spriteCol);
rect<s32> rectIcon;
SCursorSprite spriteNonAnimated(SpriteBankIcons, 0, position2d<s32>(7,7));
rectIcon = rect<s32>(0,0, 16, 16);
spriteNonAnimated.SpriteId = AddIconToSpriteBank( SpriteBankIcons, driver,
io::path(
"../../media/icon_crosshairs16x16col.png"), rectIcon );
context.addIcon(L"crosshair_col1", spriteNonAnimated, false);
rectIcon = rect<s32>(16,0, 32, 16);
spriteNonAnimated.SpriteId = AddIconToSpriteBank( SpriteBankIcons, driver,
io::path(
"../../media/icon_crosshairs16x16col.png"), rectIcon );
context.addIcon(L"crosshair_col2", spriteNonAnimated, false);
rectIcon = rect<s32>(0,16, 16, 32);
spriteNonAnimated.SpriteId = AddIconToSpriteBank( SpriteBankIcons, driver,
io::path(
"../../media/icon_crosshairs16x16col.png"), rectIcon );
context.addIcon(L"crosshair_col3", spriteNonAnimated, false);
MyEventReceiver receiver(context);
while(device->
run() && driver)
{
{
context.update();
driver->
beginScene(
true,
true, SColor(0,200,200,200));
env->drawAll();
if ( context.SpriteBox )
{
s32 selectedSprite = context.SpriteBox->getSelected();
if ( selectedSprite >= 0 && context.Sprites[selectedSprite].SpriteId >= 0 )
{
SpriteBankIcons->
draw2DSprite(
u32(context.Sprites[selectedSprite].SpriteId), position2di(580, 140), 0,
video::SColor(255, 255, 255, 255), 0, realTimeNow);
}
}
}
if ( context.SimulateBadFps )
{
}
else
{
}
}
return 0;
}
bool drop() const
Drops the object. Decrements the reference counter by one.
virtual u32 getRealTime() const =0
Returns current real time in milliseconds of the system.
virtual bool run()=0
Runs the device.
virtual void sleep(u32 timeMs, bool pauseTimer=false)=0
Pause execution and let other processes to run for a specified amount of time.
virtual ITimer * getTimer()=0
Provides access to the engine's timer.
virtual void setEventReceiver(IEventReceiver *receiver)=0
Sets a new user event receiver which will receive events from the engine.
virtual void draw2DSprite(u32 index, const core::position2di &pos, const core::rect< s32 > *clip=0, const video::SColor &color=video::SColor(255, 255, 255, 255), u32 starttime=0, u32 currenttime=0, bool loop=true, bool center=false)=0
Draws a sprite in 2d with position and color.
virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255, 0, 0, 0), const SExposedVideoData &videoData=SExposedVideoData(), core::rect< s32 > *sourceRect=0)=0
Applications must call this method before performing any rendering.
virtual bool endScene()=0
Presents the rendered image to the screen.
Class representing a 32 bit ARGB color.