am sure that 80% of us rewrite the same code to know if a key is pressed or not (for example keeping a table of booleans called Buttons set to true on PressedDown events,false otherwise) and to compute useful joystick-related events.
Among the few things I find annoying:
-Impossibility to retrieve state of a key
-Joystick events are inconsistants with mouse & keyboard handling, they are not events but states in fact
That's why I've started developing a proof of concept for windows API only just to know if devs were interested by these "improvements" (in my opinion). This is inspired by SFML (http://www.sfml-dev.org) and OIS as well.
Here is a summary of functions I've quickly implemented for the windows32 API (The main difference with current code is the creation of an IJoystick* class):
Code: Select all
bool IrrlichtDevice::isJoytickConnected(id)
IJoystick* IrrlichtDevice::getJoystick(u8 const& id)
bool IrrlichtDevice::getJoysticks( array<IJoystick*> )
CMouse::isButtonPressed(button)
CKeyboard::isKeyPressed(key)
IJoystick::isButtonPressed(button)
IJoystick::getAxisValue(axis)
IJoystick::hasAxis(axis)
bool IJoystick::hasPOV()
IJoystick::getPOV()
// if we generate events for axis we could use
[ IJoystick::setThreshold ]
// different types of event
enum EJOYSTICK_EVENT {
EJE_PLUGGED,
EJE_UNPLUGGED,
EJE_BUTTON_PRESSED,
EJE_BUTTON_RELEASED,
EJE_POV_MOVED,
EJE_AXIS_MOVED
};
// asks for a new SJoystickEvent
struct SJoystickEvent
{
EJOYSTICK_EVENT Type;
u8 Id; //joystick id (or pass IJoystick*)
EJOYSTICK_AXIS MovedAxis;
// could use a union here
u8 Button; // Index of pressed button
s16 Axis;
u16 POV;
}
For example:
-Right now, I delete unplugged IJoystick* and reallocate them when plugged. Maybe we could just change a boolean "Connected"
-How to handle IJoystick instances, with a reference counter ?
-should we generate plug/unplug events if joysticks are not activated with activeJoystick ?
-how often should we check joystick state ? each frame ? each 30ms ?
-concerns about design implementation, which function goes where, do we place enums in namespace/class etc...
I am willing to adapt directInput (it looks deprecated in favor of XInput which has some defects too, maybe rely on winapi only ? what are the advantages of Direct Input ?).
Tell me if you are interested and if yes how do you want me to proceed, patch per platform, what tests you want me to write etc...
That's also sthg to discuss if there is any interest. Keep in mind the current code is just to get some feedback and start a discussion and does not reflect a final one.
I think my improving this part of irrlicht shouldn't be a burden for current dev.In fact input code is a code part that once finished shouldn't evolve much.
Btw the patch is downloadable here (built against rev3905 / irrlicht1.
This is currently for WIN32 api ONLY and applying the patch on windows might be tricky. You should install patch.exe for windows and then transform line endings into CR+LF format (with notepad++ for instance). Then a "patch -p0 -i improvedInputForWin32api.patch" from trunk folder should do the trick. I know you are looking for developers that would help you solving bugs. That's something I might do in the future but this one has been in my bonnet for quite some time.
Here is a small main.cpp to test features.
Code: Select all
#include <irrlicht.h>
#include <iostream>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif
class MyEventReciever : public IEventReceiver
{
bool OnEvent(const SEvent& event){
if(event.EventType != EET_JOYSTICK_INPUT_EVENT){
return false;
}
char logString[256] = "no message";
// (void)sprintf(logString, "Found joystick %d, %d buttons '%s'",
// joystickId,
// caps.ButtonCount,
// "unknown");
switch(event.JoystickEvent.Type){
case EJE_PLUGGED:
sprintf(logString,"Joystick %d plugged",event.JoystickEvent.Id);break;
case EJE_UNPLUGGED:
sprintf(logString,"Joystick %d unplugged",event.JoystickEvent.Id);break;
case EJE_BUTTON_PRESSED:
sprintf(logString,"Button %d of Joystick %d pressed",event.JoystickEvent.Button,event.JoystickEvent.Id);break;
case EJE_BUTTON_RELEASED:
sprintf(logString,"Button %d of Joystick %d released",event.JoystickEvent.Button,event.JoystickEvent.Id);break;
case EJE_POV_MOVED:
sprintf(logString,"Pov moved");break;
case EJE_AXIS_MOVED:
sprintf(logString,"Axis %d moved. New value:",event.JoystickEvent.MovedAxis);break;
default:
break;
};
std::cout << logString << std::endl;
return false;
};
};
/*
This is the main method. We can now use main() on every platform.
*/
int main()
{
IrrlichtDevice *device =
createDevice( video::EDT_SOFTWARE, dimension2d<u32>(640, 480), 16,
false, false, false, 0);
if (!device)
return 1;
device->setWindowCaption(L"Hello World! - Improved Input Demo");
MyEventReciever myReceiver;
device->setEventReceiver( &myReceiver );
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IGUIEnvironment* guienv = device->getGUIEnvironment();
ILogger* logger = device->getLogger();
IJoystick* joystick0 = 0;
guienv->addStaticText(L"Hello World! This is the Irrlicht Software renderer!",
rect<s32>(10,10,260,22), true);
smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0));
// Kept cos it's just a proof of concept. Serve no purpose
core::array<SJoystickInfo> joystickInfo;
//device->activateJoysticks(joystickInfo);
if( device->activateJoysticks(joystickInfo) ){
logger->log("Joysticks enabled");
}
else {
logger->log("No joystick detected",ELL_ERROR);
return 0;
}
core::array<IJoystick*> Joysticks;
int res = device->getJoysticks(Joysticks);
std::cout << "Nb of Joysticks registered: " << Joysticks.size();
//int res = device->getJoysticks(Joysticks);
joystick0 = device->getJoystick(0);
if(!joystick0){
logger->log("No joystick retrieved",ELL_ERROR);
return 0;
}
else {
logger->log("At least one joystick retrieved");
joystick0 = Joysticks[0];
}
//sprintf()
SJoystickCapabilities caps = joystick0->getCapabilities();
char logString[256];
(void)sprintf(logString, "Found joystick %d, %d buttons '%s'",
0,
caps.ButtonCount,
joystick0->Name.c_str()
);
logger->log(logString);
while(device->run())
{
// if(irr::CKeyboard::isKeyPressed(irr::KEY_KEY_A)){
// logger->log("A is pressed");
// }
// else {
// logger->log("A not pressed");
// }
// if( joystick0->isButtonPressed(0) || joystick0->isButtonPressed(1)){
// logger->log("Button 0 pressed");
// }
// else {
// logger->log("Button 0 not pressed");
// }
driver->beginScene(true, true, SColor(255,100,101,140));
smgr->drawAll();
guienv->drawAll();
driver->endScene();
}
device->drop();
return 0;
}
/*
That's it. Compile and run.
**/