Here is the code:
irrCC.h
Code: Select all
#ifndef _IRR_CONFIG_CONTROLLER
#define _IRR_CONFIG_CONTROLLER
#include <irrlicht.h>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
/**
* @class CIrrCC
* @brief The central class of IrrConfigController
* This class is used to provide the use configurable Irrlicht controller. Controller items can be
* defined, and the user will be able to change the controls using a GUI provided by this class. Controls
* can be grouped into several sets, but this does only influence the creation of the GUI.
* @author Christian Keimel / dustbin::games
*/
class CIrrCC : public IEventReceiver {
public:
enum eControllerType {
eCtrlAxis, //the controller is an axis
eCtrlToggleButton, //the controller is a toggle button (state changes when button is pushed, e.g. drop a bomb
eCtrlButton, //the controller is a normal button (state remains the same, e.g. boost
eCtrlFader
};
private:
/**
* The supported controller types
* @see CIrrCC::CIrrCCItem::m_iType
*/
enum IrrConfigControlTypes {
CC_TYPE_NUL, /**< NULL type ... not used */
CC_TYPE_KEY, /**< keyboard type */
CC_TYPE_JOY, /**< joystick axis type */
CC_TYPE_MOU, /**< mouse movement type */
CC_TYPE_MBT, /**< mouse button type */
CC_TYPE_JBT, /**< joystick button type */
CC_TYPE_POV /**< joystick POV type */
};
/**
* @class CIrrCC::CIrrCCItem
* @brief this class represents the controllers the user can configure
* @see CIrrCC::m_aItems
*/
class CIrrCCItem {
private:
stringw keyCodeToString(EKEY_CODE e); /**< helper function to convert a keycode to a string */
IrrlichtDevice *m_pDevice; /**< the Irrlicht device */
IGUIEnvironment *m_pGuiEnv; /**< the Irrlicht gui environment */
ICursorControl *m_pCrsCtrl; /**< the cursor control */
IGUIStaticText *m_pCtrlText; /**< the static text that displays the control */
IGUITab *m_pGuiElement; /**< the GUI element that contains the control */
void updateMouse();
public:
IrrConfigControlTypes m_iType; /**< type of control, e.g. key or joystick */
stringw m_sName; /**< name of the control */
EKEY_CODE m_eKey; /**< the key code of the control */
eControllerType m_eType; /**< type of control */
u32 m_iSet, /**< The set of the control. */
m_iIdx, /**< The index of the control in CIrrCC::m_aItems */
m_iMouseAxis, /**< This control's mouse axis */
m_iMouseBtn, /**< This control's mouse button */
m_iJoyAxis, /**< This control's joystick axis */
m_iJoyButton, /**< This control's joystick button */
m_iFaderStep, /**< time step for fader */
m_iFaderLastStep; /**< the last step time of the fader */
u8 m_iJoyId; /**< This control's joystick .. irrlicht joystick ID */
u16 m_iPov; /**< This control's POV position */
s32 m_iMouseDirection, /**< This control's mouse direction */
m_iJoyDirection; /**< This control's joystick direction */
f32 m_fValue, /**< This control's value. Should be queried using CIrrCCItem::get() */
m_fDetectedValue, /**< The last detected value. CIrrCCItem::set does not influence this */
m_fMouseSensitivity, /**< This control's mouse sensitivity */
m_fFaderDiff, /**< increase / decrease per time step for fader */
m_fFaderValue; /**< the value of the fader */
CIrrCCItem *m_pBrother; /**< the other CCItem with forms an axis with this one */
bool m_bConflict; /**< does this control have a conflict with another control? */
bool isButton(); /**< is this controller a button? */
/**
* The item's constructor.
* @param sName name of the item
* @param pDevice irrlicht device for the item
* @param iSet set of the item
*/
CIrrCCItem(stringw sName, IrrlichtDevice *pDevice, u32 iSet);
/**
* The item's destructor
*/
~CIrrCCItem();
/**
* This method constructs a GUI element for changing this control item
* @param pParent parent GUI element
* @param cPos position of the item's element
* @param cEditPos position of the item's static text that can change
*/
IGUITab *getGuiElement(IGUIElement *pParent, position2di cPos, position2di cEditPos);
/**
* Set the item to "CC_TYPE_KEY" using the given key
* @param e the key for this item
*/
void setKey(EKEY_CODE e);
/**
* Set the item to "CC_TYPE_MOU" using the given mouse axis in the given direction
* @param iAxis the mouse axis
* @param iDirection the direction of this item
*/
void setMouseMove(u32 iAxis, s32 iDirection);
/**
* Set the item to "CC_TYPE_MBT" using the given button number
* @param iBtn button number to use (0=left, 1=right, 2=middle)
*/
void setMouseButton(u32 iBtn);
/**
* Set the item to "CC_TYPE_JOY" using the given joystick, axis and direction
* @param id the irrlicht joystick id
* @param iAxis the axis for this item
* @param iDirection the direction for this item
*/
void setJoyAxis(u8 id, u32 iAxis, s32 iDirection);
/**
* Set the item to "CC_TYPE_JBT" using the given joystick and joystick button
* @param id the irrlicht joystick id
* @param iBtn the joystick button to use
*/
void setJoyButton(u8 id, u32 iBtn);
/**
* Set the item to "CC_TYPE_POV" using the given joystick and POV position
* @param id the irrlicht joystick id
* @param iPov the POV position for this item
*/
void setPov(u8 id, u16 iPov);
/**
* Update the item's text. This method is called after the control has changed
*/
void updateCtrlText();
/**
* Get the item's text
* @return the item's text
*/
IGUIStaticText *getCtrlText();
/**
* Does this item have a conflict with another item?
* @return Does this item have a conflict with another item?
*/
bool hasConflict();
/**
* Set the item's conflict flag
* @param b "true" if a conflict was found, "false" otherwise
*/
void setConflict(bool b);
/**
* Check whether or not this item is in conflict with another one
* @param pOther the other item
* @return "true" if both of the items use the same control, "false" otherwise
*/
bool conflicts(CIrrCCItem *pOther);
/**
* Set the item's mouse sensitivity. This is use for items that use mouse movement as control
* @param f the item's mouse sensitivity
*/
void setMouseSensitivity(f32 f);
/**
* Get the item's current position. You could also just take the item's public "m_fValue" property,
* but mouse movement items calculate this value in this method
*/
f32 get();
f32 getRaw();
/**
* Set the item's value. Can be called from outside to reset e.g. a button state
* @param f the new value
*/
void set(f32 f);
/**
* Set the item's value. Is called by CIrrCC::OnEvent
* @param f the new value
*/
void setWithDetected(f32 f);
};
/**
* @class CJoyState
* @brief This class is used for detecting joystick movement when changing an item's control
*/
class CJoyState {
public:
u16 iAxis[6]; /**< the axis positions of the joystick */
u32 iButtons; /**< the button states of the joystick */
u16 iPov; /**< the POV position of the joystick */
/**
* Constructor
*/
CJoyState() {
for (u32 i=0; i<6; i++) iAxis[i]=0;
iButtons=0;
iPov=0;
}
/**
* Check whether or not a button was pressed
* @param iBtn the button number
* @return "true" if the button was pressed, "false" otherwise
*/
bool buttonPressed(u32 iBtn) {
u32 i=1<<iBtn;
return (iButtons&i)!=0;
}
};
IrrlichtDevice *m_pDevice; /**< the Irrlicht device */
u32 m_iGuiItemHeight; /**< the height of the items using the current font */
s32 m_iFocusedIndex; /**< index of the currently focused GUI element */
f32 m_fMouseSensitivity; /**< the mouse sensitivity */
IGUIStaticText *m_pFocused; /**< the focused text element */
ICursorControl *m_pCrsCtrl; /**< the cursor control object */
position2di m_cMousePos; /**< the position of the mouse */
array<CIrrCCItem *> m_aItems; /**< the array with the control items */
array<stringw> m_aMaxLenText; /**< the texts with the maximum length of all sets */
array<SJoystickInfo> m_aJoysticks; /**< the joystick info array */
array<CJoyState *> m_aJoyState; /**< array with the current joystick states */
bool m_bAllowMouse, /**< is mouse movement allowed for items? */
m_bAllowFKeys, /**< are "Fxx" keys allowed for items? */
m_bAllowJoystick, /**< is joystick allows for items? */
m_bLoaded, /**< is the control set already loaded from the XML file? */
m_bSetsCanConflict; /**< do same controls of different sets cause a conflict? */
public:
/**
* The constructor
* @param pDevice the irrlicht device
*/
CIrrCC(IrrlichtDevice *pDevice);
/**
* destructor
*/
virtual ~CIrrCC();
/**
* add a new control item
* @param iSet set of the item
* @param sName name of the item
* @param eDefault default control key of the item
* @param bIsButton is this a button or part of an axis?
* @return index of the item
*/
u32 addItem(u32 iSet, stringw sName, EKEY_CODE eDefault, eControllerType eType);
/**
* Create a gui to configure the control items
* @param iSet set of items
* @param pParent parent GUI element
* @param cPos position of the newly created gui
*/
void addGui(u32 iSet, IGUIElement *pParent, position2di cPos);
/**
* Set the "allow mouse" flag
* @param b new value for the "allow mouse" flag
*/
void setAllowMouse(bool b);
/**
* Set the "allow F-Keys" flag
* @param b new value for the "allow F-Keys" flag
*/
void setAllowFKeys(bool b);
/**
* Set the "allow joystick" flag
* @param b new value for the "allow joystick" flag
*/
void setAllowJoystick(bool b);
/**
* Set the mouse sensitivity
* @param f new value for the mouse sensitivity
*/
void setMouseSensitivity(f32 f);
/**
* Get the status of a specific item. This value is always between "0" and "1" (except for mouse movement)
* @param idx index of the item
* @return status of the item
*/
f32 get(u32 idx);
void set(u32 idx, f32 f);
/**
* This method must be called from the GUI's event receiver. It handles configuration of the control items
* @param event the event to be handled
* @return "true" if the event was processed, "false" otherwise
*/
bool ConfigEvent(const SEvent &event);
void reset();
/**
* This is the event handler to update the item's values. You can either set the instance of the class
* as irrlicht event receiver or call this method from your own event receiving code.
* @param event the event to be handled
* @return "true" if the event was processed, "false" otherwise
*/
virtual bool OnEvent (const SEvent &event);
/**
* decide whether or not the various defined sets cause conflicts or not
* @param b true if the sets can cause conflicts, false otherwise
*/
void setSetsCanConflict(bool b) { m_bSetsCanConflict=b; }
/**
* Can the various defined sets cause conflicts?
* @return Can the various defined sets cause conflicts?
*/
bool setsCanConflict() { return m_bSetsCanConflict; }
/**
* Create an axis of two controls defined as eCtrlAxis. If you query the value of the first
* control item you will get <position of idx1>-<position of idx2>, if you query the second
* item you'll get <position of idx2>-<position of idx1>.
* @param idx1 the first index of the axis (value returned by CIrrCC::addItem)
* @param idx2 the second index of the axis (value returned by CIrrCC::addItem)
* @see eControllerType
*/
void createAxis(u32 idx1, u32 idx2);
void createFader(u32 idx1, u32 idx2, u32 iStep, f32 iInc);
/**
* Save the controls to an XML file
* @param sFileName name of the XML file
*/
void save(c8 *sFileName);
/**
* Load the controls from an XML file
* @param sFileName name of the XML file
*/
void load(c8 *sFileName);
};
#endif
Code: Select all
#include <irrCC.h>
CIrrCC::CIrrCCItem::CIrrCCItem(stringw sName, IrrlichtDevice *pDevice, u32 iSet) {
m_pDevice=pDevice;
m_sName=sName;
m_iSet=iSet;
m_iType=CC_TYPE_NUL;
m_eKey=KEY_KEY_CODES_COUNT;
m_eType=eCtrlAxis;
m_pGuiEnv=m_pDevice->getGUIEnvironment();
m_bConflict=false;
m_fValue=0.0f;
m_pCrsCtrl=pDevice->getCursorControl();
m_fMouseSensitivity=10.0f;
m_pCtrlText=NULL;
m_pBrother=NULL;
m_iFaderStep=0;
m_iFaderLastStep=0;
m_fFaderDiff=0.0f;
m_fFaderValue=0.0f;
}
CIrrCC::CIrrCCItem::~CIrrCCItem() {
}
bool CIrrCC::CIrrCCItem::isButton() {
return m_eType==CIrrCC::eCtrlButton || m_eType==CIrrCC::eCtrlToggleButton;
}
stringw CIrrCC::CIrrCCItem::keyCodeToString(EKEY_CODE e) {
if (e == KEY_LBUTTON) return stringw(L"KEY_LBUTTON");
if (e == KEY_RBUTTON) return stringw(L"KEY_RBUTTON");
if (e == KEY_CANCEL) return stringw(L"KEY_CANCEL");
if (e == KEY_MBUTTON) return stringw(L"KEY_MBUTTON");
if (e == KEY_XBUTTON1) return stringw(L"KEY_XBUTTON1");
if (e == KEY_XBUTTON2) return stringw(L"KEY_XBUTTON2");
if (e == KEY_BACK) return stringw(L"KEY_BACK");
if (e == KEY_TAB) return stringw(L"KEY_TAB");
if (e == KEY_CLEAR) return stringw(L"KEY_CLEAR");
if (e == KEY_RETURN) return stringw(L"KEY_RETURN");
if (e == KEY_SHIFT) return stringw(L"KEY_SHIFT");
if (e == KEY_CONTROL) return stringw(L"KEY_CONTROL");
if (e == KEY_MENU) return stringw(L"KEY_MENU");
if (e == KEY_PAUSE) return stringw(L"KEY_PAUSE");
if (e == KEY_CAPITAL) return stringw(L"KEY_CAPITAL");
if (e == KEY_KANA) return stringw(L"KEY_KANA");
if (e == KEY_HANGUEL) return stringw(L"KEY_HANGUEL");
if (e == KEY_HANGUL) return stringw(L"KEY_HANGUL");
if (e == KEY_JUNJA) return stringw(L"KEY_JUNJA");
if (e == KEY_FINAL) return stringw(L"KEY_FINAL");
if (e == KEY_HANJA) return stringw(L"KEY_HANJA");
if (e == KEY_KANJI) return stringw(L"KEY_KANJI");
if (e == KEY_ESCAPE) return stringw(L"KEY_ESCAPE");
if (e == KEY_CONVERT) return stringw(L"KEY_CONVERT");
if (e == KEY_NONCONVERT) return stringw(L"KEY_NONCONVERT");
if (e == KEY_ACCEPT) return stringw(L"KEY_ACCEPT");
if (e == KEY_MODECHANGE) return stringw(L"KEY_MODECHANGE");
if (e == KEY_SPACE) return stringw(L"KEY_SPACE");
if (e == KEY_PRIOR) return stringw(L"KEY_PRIOR");
if (e == KEY_NEXT) return stringw(L"KEY_NEXT");
if (e == KEY_END) return stringw(L"KEY_END");
if (e == KEY_HOME) return stringw(L"KEY_HOME");
if (e == KEY_LEFT) return stringw(L"KEY_LEFT");
if (e == KEY_UP) return stringw(L"KEY_UP");
if (e == KEY_RIGHT) return stringw(L"KEY_RIGHT");
if (e == KEY_DOWN) return stringw(L"KEY_DOWN");
if (e == KEY_SELECT) return stringw(L"KEY_SELECT");
if (e == KEY_PRINT) return stringw(L"KEY_PRINT");
if (e == KEY_EXECUT) return stringw(L"KEY_EXECUT");
if (e == KEY_SNAPSHOT) return stringw(L"KEY_SNAPSHOT");
if (e == KEY_INSERT) return stringw(L"KEY_INSERT");
if (e == KEY_DELETE) return stringw(L"KEY_DELETE");
if (e == KEY_HELP) return stringw(L"KEY_HELP");
if (e == KEY_KEY_0) return stringw(L"KEY_KEY_0");
if (e == KEY_KEY_1) return stringw(L"KEY_KEY_1");
if (e == KEY_KEY_2) return stringw(L"KEY_KEY_2");
if (e == KEY_KEY_3) return stringw(L"KEY_KEY_3");
if (e == KEY_KEY_4) return stringw(L"KEY_KEY_4");
if (e == KEY_KEY_5) return stringw(L"KEY_KEY_5");
if (e == KEY_KEY_6) return stringw(L"KEY_KEY_6");
if (e == KEY_KEY_7) return stringw(L"KEY_KEY_7");
if (e == KEY_KEY_8) return stringw(L"KEY_KEY_8");
if (e == KEY_KEY_9) return stringw(L"KEY_KEY_9");
if (e == KEY_KEY_A) return stringw(L"KEY_KEY_A");
if (e == KEY_KEY_B) return stringw(L"KEY_KEY_B");
if (e == KEY_KEY_C) return stringw(L"KEY_KEY_C");
if (e == KEY_KEY_D) return stringw(L"KEY_KEY_D");
if (e == KEY_KEY_E) return stringw(L"KEY_KEY_E");
if (e == KEY_KEY_F) return stringw(L"KEY_KEY_F");
if (e == KEY_KEY_G) return stringw(L"KEY_KEY_G");
if (e == KEY_KEY_H) return stringw(L"KEY_KEY_H");
if (e == KEY_KEY_I) return stringw(L"KEY_KEY_I");
if (e == KEY_KEY_J) return stringw(L"KEY_KEY_J");
if (e == KEY_KEY_K) return stringw(L"KEY_KEY_K");
if (e == KEY_KEY_L) return stringw(L"KEY_KEY_L");
if (e == KEY_KEY_M) return stringw(L"KEY_KEY_M");
if (e == KEY_KEY_N) return stringw(L"KEY_KEY_N");
if (e == KEY_KEY_O) return stringw(L"KEY_KEY_O");
if (e == KEY_KEY_P) return stringw(L"KEY_KEY_P");
if (e == KEY_KEY_Q) return stringw(L"KEY_KEY_Q");
if (e == KEY_KEY_R) return stringw(L"KEY_KEY_R");
if (e == KEY_KEY_S) return stringw(L"KEY_KEY_S");
if (e == KEY_KEY_T) return stringw(L"KEY_KEY_T");
if (e == KEY_KEY_U) return stringw(L"KEY_KEY_U");
if (e == KEY_KEY_V) return stringw(L"KEY_KEY_V");
if (e == KEY_KEY_W) return stringw(L"KEY_KEY_W");
if (e == KEY_KEY_X) return stringw(L"KEY_KEY_X");
if (e == KEY_KEY_Y) return stringw(L"KEY_KEY_Y");
if (e == KEY_KEY_Z) return stringw(L"KEY_KEY_Z");
if (e == KEY_LWIN) return stringw(L"KEY_LWIN");
if (e == KEY_RWIN) return stringw(L"KEY_RWIN");
if (e == KEY_APPS) return stringw(L"KEY_APPS");
if (e == KEY_SLEEP) return stringw(L"KEY_SLEEP");
if (e == KEY_NUMPAD0) return stringw(L"KEY_NUMPAD0");
if (e == KEY_NUMPAD1) return stringw(L"KEY_NUMPAD1");
if (e == KEY_NUMPAD2) return stringw(L"KEY_NUMPAD2");
if (e == KEY_NUMPAD3) return stringw(L"KEY_NUMPAD3");
if (e == KEY_NUMPAD4) return stringw(L"KEY_NUMPAD4");
if (e == KEY_NUMPAD5) return stringw(L"KEY_NUMPAD5");
if (e == KEY_NUMPAD6) return stringw(L"KEY_NUMPAD6");
if (e == KEY_NUMPAD7) return stringw(L"KEY_NUMPAD7");
if (e == KEY_NUMPAD8) return stringw(L"KEY_NUMPAD8");
if (e == KEY_NUMPAD9) return stringw(L"KEY_NUMPAD9");
if (e == KEY_MULTIPLY) return stringw(L"KEY_MULTIPLY");
if (e == KEY_ADD) return stringw(L"KEY_ADD");
if (e == KEY_SEPARATOR) return stringw(L"KEY_SEPARATOR");
if (e == KEY_SUBTRACT) return stringw(L"KEY_SUBTRACT");
if (e == KEY_DECIMAL) return stringw(L"KEY_DECIMAL");
if (e == KEY_DIVIDE) return stringw(L"KEY_DIVIDE");
if (e == KEY_F1) return stringw(L"KEY_F1");
if (e == KEY_F2) return stringw(L"KEY_F2");
if (e == KEY_F3) return stringw(L"KEY_F3");
if (e == KEY_F4) return stringw(L"KEY_F4");
if (e == KEY_F5) return stringw(L"KEY_F5");
if (e == KEY_F6) return stringw(L"KEY_F6");
if (e == KEY_F7) return stringw(L"KEY_F7");
if (e == KEY_F8) return stringw(L"KEY_F8");
if (e == KEY_F9) return stringw(L"KEY_F9");
if (e == KEY_F10) return stringw(L"KEY_F10");
if (e == KEY_F11) return stringw(L"KEY_F11");
if (e == KEY_F12) return stringw(L"KEY_F12");
if (e == KEY_F13) return stringw(L"KEY_F13");
if (e == KEY_F14) return stringw(L"KEY_F14");
if (e == KEY_F15) return stringw(L"KEY_F15");
if (e == KEY_F16) return stringw(L"KEY_F16");
if (e == KEY_F17) return stringw(L"KEY_F17");
if (e == KEY_F18) return stringw(L"KEY_F18");
if (e == KEY_F19) return stringw(L"KEY_F19");
if (e == KEY_F20) return stringw(L"KEY_F20");
if (e == KEY_F21) return stringw(L"KEY_F21");
if (e == KEY_F22) return stringw(L"KEY_F22");
if (e == KEY_F23) return stringw(L"KEY_F23");
if (e == KEY_F24) return stringw(L"KEY_F24");
if (e == KEY_NUMLOCK) return stringw(L"KEY_NUMLOCK");
if (e == KEY_SCROLL) return stringw(L"KEY_SCROLL");
if (e == KEY_LSHIFT) return stringw(L"KEY_LSHIFT");
if (e == KEY_RSHIFT) return stringw(L"KEY_RSHIFT");
if (e == KEY_LCONTROL) return stringw(L"KEY_LCONTROL");
if (e == KEY_RCONTROL) return stringw(L"KEY_RCONTROL");
if (e == KEY_LMENU) return stringw(L"KEY_LMENU");
if (e == KEY_RMENU) return stringw(L"KEY_RMENU");
if (e == KEY_PLUS) return stringw(L"KEY_PLUS");
if (e == KEY_COMMA) return stringw(L"KEY_COMMA");
if (e == KEY_MINUS) return stringw(L"KEY_MINUS");
if (e == KEY_PERIOD) return stringw(L"KEY_PERIOD");
if (e == KEY_ATTN) return stringw(L"KEY_ATTN");
if (e == KEY_CRSEL) return stringw(L"KEY_CRSEL");
if (e == KEY_EXSEL) return stringw(L"KEY_EXSEL");
if (e == KEY_EREOF) return stringw(L"KEY_EREOF");
if (e == KEY_PLAY) return stringw(L"KEY_PLAY");
if (e == KEY_ZOOM) return stringw(L"KEY_ZOOM");
if (e == KEY_PA1) return stringw(L"KEY_PA1");
if (e == KEY_OEM_CLEAR) return stringw(L"KEY_OEM_CLEAR");
return stringw(L"UNKNOWN");
}
IGUITab *CIrrCC::CIrrCCItem::getGuiElement(IGUIElement *pParent, position2di cPos, position2di cEditPos) {
IGUIFont *pFont=m_pGuiEnv->getSkin()->getFont();
dimension2du dim=pFont->getDimension(m_sName.c_str());
position2di ulc(cPos.X,cPos.Y),lrc(cPos.Y+dim.Width+cEditPos.X+250,cPos.Y+dim.Height+10);
m_pGuiElement=m_pGuiEnv->addTab(rect<s32>(ulc.X,ulc.Y,lrc.X,lrc.Y),pParent,-1);
m_pGuiEnv->addStaticText(m_sName.c_str(),rect<s32>(0,0,dim.Width+10,dim.Height+10),false,true,m_pGuiElement);
m_pCtrlText=m_pGuiEnv->addStaticText(L"Not set",rect<s32>(cEditPos.X,cEditPos.Y,cEditPos.X+200,cEditPos.Y+dim.Height+2),true,true,m_pGuiElement,65536+m_iIdx);
this->updateCtrlText();
return m_pGuiElement;
}
void CIrrCC::CIrrCCItem::setKey(EKEY_CODE e) {
m_eKey=e;
m_iType=CC_TYPE_KEY;
}
void CIrrCC::CIrrCCItem::setMouseMove(u32 iAxis, s32 iDirection) {
m_iMouseAxis=iAxis;
m_iMouseDirection=iDirection;
m_iType=CC_TYPE_MOU;
}
void CIrrCC::CIrrCCItem::setMouseButton(u32 iBtn) {
m_iMouseBtn=iBtn;
m_iType=CC_TYPE_MBT;
}
void CIrrCC::CIrrCCItem::setJoyAxis(u8 id, u32 iAxis, s32 iDirection) {
m_iJoyId=id;
m_iJoyAxis=iAxis;
m_iJoyDirection=iDirection;
m_iType=CC_TYPE_JOY;
}
void CIrrCC::CIrrCCItem::setJoyButton(u8 id, u32 iBtn) {
m_iJoyId=id;
m_iJoyButton=iBtn;
m_iType=CC_TYPE_JBT;
}
void CIrrCC::CIrrCCItem::setPov(u8 id, u16 iPov) {
m_iPov=iPov;
m_iJoyId=id;
m_iType=CC_TYPE_POV;
}
IGUIStaticText *CIrrCC::CIrrCCItem::getCtrlText() {
return m_pCtrlText;
}
bool CIrrCC::CIrrCCItem::hasConflict() {
return m_bConflict;
}
void CIrrCC::CIrrCCItem::setConflict(bool b) {
m_bConflict=b;
}
void CIrrCC::CIrrCCItem::updateCtrlText() {
if (!m_pCtrlText) return;
wchar_t s[0xFF];
switch (m_iType) {
case CC_TYPE_KEY:
m_pCtrlText->setText(keyCodeToString(m_eKey).c_str());
break;
case CC_TYPE_MOU:
swprintf(s,0xFF,L"Mouse %s %s",m_iMouseAxis==0?L"X":L"Y",m_iMouseDirection>0?L"+":L"-");
m_pCtrlText->setText(s);
break;
case CC_TYPE_MBT:
swprintf(s,0xFF,L"Mouse Button %i",m_iMouseBtn);
m_pCtrlText->setText(s);
break;
case CC_TYPE_JOY:
swprintf(s,0xFF,L"Joy %i Axis %i %s",m_iJoyId,m_iJoyAxis,m_iJoyDirection>0?L"+":L"-");
m_pCtrlText->setText(s);
break;
case CC_TYPE_JBT:
swprintf(s,0xFF,L"Joy %i Button %i",m_iJoyId,m_iJoyButton);
m_pCtrlText->setText(s);
break;
case CC_TYPE_POV:
swprintf(s,0xFF,L"Joy %i POV %u",m_iJoyId,m_iPov/100);
m_pCtrlText->setText(s);
break;
default:
break;
}
}
bool CIrrCC::CIrrCCItem::conflicts(CIrrCCItem *pOther) {
bool bRet=m_iType==pOther->m_iType;
if (bRet) {
switch (m_iType) {
case CC_TYPE_KEY:
bRet=m_eKey==pOther->m_eKey;
break;
case CC_TYPE_MOU:
bRet=m_iMouseAxis==pOther->m_iMouseAxis && m_iMouseDirection==pOther->m_iMouseDirection;
break;
case CC_TYPE_MBT:
bRet=m_iMouseBtn==pOther->m_iMouseBtn;
break;
case CC_TYPE_JOY:
bRet=m_iJoyId==pOther->m_iJoyId && m_iJoyAxis==pOther->m_iJoyAxis && m_iJoyDirection==pOther->m_iJoyDirection;
break;
case CC_TYPE_JBT:
bRet=m_iJoyId==pOther->m_iJoyId && m_iJoyButton==pOther->m_iJoyButton;
break;
case CC_TYPE_POV:
bRet=m_iJoyId==pOther->m_iJoyId && m_iPov==pOther->m_iPov;
break;
default:
break;
}
}
return bRet;
}
void CIrrCC::CIrrCCItem::setMouseSensitivity(f32 f) {
m_fMouseSensitivity=f;
}
void CIrrCC::CIrrCCItem::updateMouse() {
m_fValue=0.0f;
position2di pos=m_pCrsCtrl->getPosition();
if (m_iMouseAxis==0) {
if (m_iMouseDirection>0 && pos.X>320) {
m_fValue=((f32)pos.X-320)/m_fMouseSensitivity;
m_fDetectedValue=m_fValue;
pos.X=320;
}
if (m_iMouseDirection<0 && pos.X<320) {
m_fValue=((f32)320-pos.X)/m_fMouseSensitivity;
m_fDetectedValue=m_fValue;
pos.X=320;
}
}
if (m_iMouseAxis==1) {
if (m_iMouseDirection>0 && pos.Y>200) {
m_fValue=((f32)pos.Y-200)/m_fMouseSensitivity;
m_fDetectedValue=m_fValue;
pos.Y=200;
}
if (m_iMouseDirection<0 && pos.Y<200) {
m_fValue=((f32)200-pos.Y)/m_fMouseSensitivity;
m_fDetectedValue=m_fValue;
pos.Y=200;
}
}
if (m_fValue) m_pCrsCtrl->setPosition(pos);
}
f32 CIrrCC::CIrrCCItem::get() {
if (m_iType==CC_TYPE_MOU) updateMouse();
return m_pBrother==NULL?m_fValue:m_fValue-m_pBrother->getRaw();
}
f32 CIrrCC::CIrrCCItem::getRaw() {
if (m_iType==CC_TYPE_MOU) updateMouse();
return m_fValue;
}
void CIrrCC::CIrrCCItem::set(f32 f) {
m_fValue=f;
}
void CIrrCC::CIrrCCItem::setWithDetected(f32 f) {
if (m_eType==eCtrlToggleButton && f==m_fDetectedValue) return;
m_fValue=f;
m_fDetectedValue=f;
}
CIrrCC::CIrrCC(IrrlichtDevice *pDevice) {
m_pDevice=pDevice;
m_iGuiItemHeight=pDevice->getGUIEnvironment()->getSkin()->getFont()->getDimension(L"Hello World").Height;
m_pFocused=NULL;
m_iFocusedIndex=-1;
m_pDevice->activateJoysticks(m_aJoysticks);
for (u32 i=0; i<m_aJoysticks.size(); i++) {
CJoyState *p=new CJoyState();
m_aJoyState.push_back(p);
}
m_bAllowMouse=true;
m_bAllowFKeys=true;
m_bAllowJoystick=true;
m_bLoaded=false;
m_pCrsCtrl=m_pDevice->getCursorControl();
m_fMouseSensitivity=10.0f;
}
CIrrCC::~CIrrCC() {
for (u32 i=0; i<m_aItems.size(); i++) delete m_aItems[i];
m_aItems.clear();
m_bSetsCanConflict=true;
}
u32 CIrrCC::addItem(u32 iSet,stringw sName, EKEY_CODE eDefault, eControllerType eType) {
u32 iRet=0;
if (m_aMaxLenText.size()<=iSet)
m_aMaxLenText.push_back(sName);
else
if (m_aMaxLenText[iSet].size()<sName.size())
m_aMaxLenText[iSet]=sName;
CIrrCCItem *item=new CIrrCCItem(sName,m_pDevice,iSet);
item->setKey(eDefault);
item->m_eType=eType;
item->setMouseSensitivity(m_fMouseSensitivity);
m_aItems.push_back(item);
iRet=m_aItems.size()-1;
item->m_iIdx=iRet;
return iRet;
}
void CIrrCC::addGui(u32 iSet, IGUIElement *pParent, position2di cPos) {
u32 editX=m_pDevice->getGUIEnvironment()->getSkin()->getFont()->getDimension(m_aMaxLenText[iSet].c_str()).Width+10;
for (u32 i=0; i<m_aItems.size(); i++)
if (m_aItems[i]->m_iSet==iSet) {
m_aItems[i]->getGuiElement(pParent,cPos,position2di(editX,0));
cPos.Y+=(s32)(2.5f*m_iGuiItemHeight);
}
}
bool CIrrCC::ConfigEvent (const SEvent &event) {
bool bRet=false;
stringw s;
u32 iItem=m_iFocusedIndex-65536;
if (event.EventType==EET_GUI_EVENT && event.GUIEvent.EventType==EGET_ELEMENT_FOCUSED) {
m_cMousePos=m_pDevice->getCursorControl()->getPosition();
if (event.GUIEvent.Caller->getID()>=65536) {
if (m_pFocused) m_pFocused->setBackgroundColor(SColor(128,192,192,192));
s=stringw(event.GUIEvent.Caller->getText());
m_pFocused=(IGUIStaticText *)event.GUIEvent.Caller;
m_pFocused->setBackgroundColor(SColor(128,0,255,0));
m_iFocusedIndex=m_pFocused->getID();
}
}
if (m_pFocused) {
CIrrCCItem *pItem=iItem<m_aItems.size()?m_aItems[iItem]:NULL,
*pBrother=pItem!=NULL?pItem->m_pBrother:NULL;
if (event.EventType==EET_KEY_INPUT_EVENT) {
if ((m_bAllowFKeys || event.KeyInput.Key<KEY_F1 || event.KeyInput.Key>KEY_F24) && event.KeyInput.Key!=KEY_ESCAPE) {
pItem->setKey(event.KeyInput.Key);
bRet=true;
}
for (u32 i=0; i<m_aItems.size(); i++) {
m_aItems[i]->setConflict(false);
m_aItems[i]->getCtrlText()->setBackgroundColor(SColor(128,192,192,192));
}
}
if (event.EventType==EET_MOUSE_INPUT_EVENT && m_bAllowMouse) {
position2di mPos=m_pDevice->getCursorControl()->getPosition();
if ((mPos.X>m_cMousePos.X+50 || mPos.X<m_cMousePos.X-50) && !pItem->isButton()) {
s32 iDirection=mPos.X>m_cMousePos.X+50?1:-1;
pItem->setMouseMove(0,iDirection);
if (pBrother!=NULL) {
if (pBrother->m_iMouseAxis!=pItem->m_iMouseAxis && pBrother->m_iMouseDirection!=-pItem->m_iMouseDirection) {
pBrother->setMouseMove(0,-iDirection);
}
}
bRet=true;
}
if ((mPos.Y>m_cMousePos.Y+50 || mPos.Y<m_cMousePos.Y-50) && !pItem->isButton()) {
s32 iDirection=mPos.Y>m_cMousePos.Y+50?1:-1;
pItem->setMouseMove(1,iDirection);
if (pBrother->m_iMouseAxis!=pItem->m_iMouseAxis && pBrother->m_iMouseDirection!=-pItem->m_iMouseDirection) {
pBrother->setMouseMove(1,-iDirection);
}
bRet=true;
}
if (event.MouseInput.Event==EMIE_LMOUSE_PRESSED_DOWN) {
pItem->setMouseButton(0);
bRet=true;
}
if (event.MouseInput.Event==EMIE_RMOUSE_PRESSED_DOWN) {
pItem->setMouseButton(1);
bRet=true;
}
if (event.MouseInput.Event==EMIE_MMOUSE_PRESSED_DOWN) {
pItem->setMouseButton(2);
bRet=true;
}
}
if (event.EventType==EET_JOYSTICK_INPUT_EVENT && m_bAllowJoystick) {
u8 joyId=event.JoystickEvent.Joystick;
for (u32 i=0; i<6; i++) {
s16 pos1=(m_aJoyState[joyId]->iAxis[i]),
pos2=event.JoystickEvent.Axis[i];
if (pos2<16000 && pos2>-16000) pos2=0;
if (pos1!=pos2 && !pItem->isButton()) {
s32 iDirection=pos1>pos2?1:-1;
pItem->setJoyAxis(joyId,i,iDirection);
if (pBrother!=NULL) {
if (pItem->m_iJoyId!=pBrother->m_iJoyId || pItem->m_iJoyAxis!=pBrother->m_iJoyAxis)
pBrother->setJoyAxis(joyId,i,-iDirection);
}
bRet=true;
}
if (m_aJoyState[joyId]->iPov!=event.JoystickEvent.POV) {
pItem->setPov(joyId,event.JoystickEvent.POV);
bRet=true;
}
if (m_aJoyState[joyId]->iButtons!=event.JoystickEvent.ButtonStates)
for (u32 i=0; i<32; i++)
if (m_aJoyState[joyId]->buttonPressed(i)!=event.JoystickEvent.IsButtonPressed(i)) {
pItem->setJoyButton(joyId,i);
bRet=true;
}
}
}
if (bRet) {
pItem->updateCtrlText();
pItem->setConflict(false);
if (pBrother!=NULL) {
pBrother->updateCtrlText();
pBrother->setConflict(false);
pBrother->getCtrlText()->setBackgroundColor(SColor(128,192,192,192));
}
m_pFocused->setBackgroundColor(SColor(128,192,192,192));
m_pFocused=NULL;
m_iFocusedIndex=-1;
m_pDevice->getGUIEnvironment()->setFocus(NULL);
}
}
for (u32 i=0; i<m_aItems.size(); i++) {
for (u32 j=i+1; j<m_aItems.size(); j++) {
if (m_aItems[i]->conflicts(m_aItems[j]) && (m_aItems[i]->m_iSet==m_aItems[j]->m_iSet || m_bSetsCanConflict)) {
m_aItems[j]->getCtrlText()->setBackgroundColor(SColor(128,255,0,0)); m_aItems[j]->setConflict(true);
m_aItems[i]->getCtrlText()->setBackgroundColor(SColor(128,255,0,0)); m_aItems[i]->setConflict(true);
}
}
}
if (!m_pFocused) {
if (event.EventType==EET_JOYSTICK_INPUT_EVENT) {
for (u32 i=0; i<6; i++) {
s16 pos=event.JoystickEvent.Axis[i];
if (pos<16000 && pos>-16000) pos=0;
m_aJoyState[event.JoystickEvent.Joystick]->iAxis[i]=pos;
}
m_aJoyState[event.JoystickEvent.Joystick]->iPov=event.JoystickEvent.POV;
}
}
return bRet;
}
void CIrrCC::setAllowMouse(bool b) {
m_bAllowMouse=b;
}
void CIrrCC::setAllowFKeys(bool b) {
m_bAllowFKeys=b;
}
void CIrrCC::setAllowJoystick(bool b) {
m_bAllowJoystick=b;
}
f32 CIrrCC::get(u32 idx) {
//if the queried item is a fader we have to do something special.
if (m_aItems[idx]->m_eType==eCtrlFader && m_aItems[idx]->m_pBrother!=NULL) {
//get the two items that make the fader
CIrrCCItem *p1=m_aItems[idx],*p2=m_aItems[idx]->m_pBrother;
u32 iTime=m_pDevice->getTimer()->getTime();
//if the fader is a joy or mouse axis we simply return it's value
if (p1->m_iType==CC_TYPE_JOY || p1->m_iType==CC_TYPE_MOU) {
p1->m_fFaderValue=p1->get();
p2->m_fFaderValue=p1->m_fFaderValue;
}
else {
//if if's a button or a key we need to calculate it's current
//value from using it's time step and it's diff per step value
//in case the value is queried for the first time we need to initialize the timer stuff...
if (p1->m_iFaderLastStep==0) {
p1->m_iFaderLastStep=iTime;
p2->m_iFaderLastStep=iTime;
}
else {
//otherwise we calculate and return it's value
f32 fValue=p1->get();
while (p1->m_iFaderLastStep<iTime) {
p1->m_fFaderValue+=fValue*p1->m_fFaderDiff;
p1->m_iFaderLastStep+=p1->m_iFaderStep;
}
if (p1->m_fFaderValue> 1.0f) p1->m_fFaderValue= 1.0f;
if (p1->m_fFaderValue<-1.0f) p1->m_fFaderValue=-1.0f;
p2->m_fFaderValue=p1->m_fFaderValue;
}
}
return p1->m_fFaderValue;
}
//if it's not a fader we simply return it's value
return m_aItems[idx]->get();
}
void CIrrCC::set(u32 idx, f32 f) {
m_aItems[idx]->set(f);
}
bool CIrrCC::OnEvent (const SEvent &event) {
bool bRet=false;
u32 i,j;
if (event.EventType==EET_KEY_INPUT_EVENT)
for (i=0; i<m_aItems.size(); i++) {
CIrrCCItem *p=m_aItems[i];
if (p->m_iType==CC_TYPE_KEY && p->m_eKey==event.KeyInput.Key) {
p->setWithDetected(event.KeyInput.PressedDown?1.0f:0.0f);
bRet=true;
}
}
if (event.EventType==EET_JOYSTICK_INPUT_EVENT)
for (i=0; i<m_aItems.size(); i++) {
CIrrCCItem *p=m_aItems[i];
switch (p->m_iType) {
case CC_TYPE_JOY:
if (p->m_iJoyId==event.JoystickEvent.Joystick)
for (j=0; j<6; j++)
if (p->m_iJoyAxis==j) {
f32 pos=((f32)event.JoystickEvent.Axis[j])/256.0f;
if (pos>10.0f) {
pos/=127;
if (p->m_iJoyDirection<0) p->setWithDetected(pos);
}
else
if (pos<-10.0f) {
pos/=128;
if (p->m_iJoyDirection>0) p->setWithDetected(-pos);
}
else p->setWithDetected(0.0f);
bRet=true;
}
break;
case CC_TYPE_JBT:
if (p->m_iJoyId==event.JoystickEvent.Joystick)
p->setWithDetected(event.JoystickEvent.IsButtonPressed(p->m_iJoyButton)?1.0f:0.0f);
break;
case CC_TYPE_POV:
if (p->m_iJoyId==event.JoystickEvent.Joystick) {
p->setWithDetected(event.JoystickEvent.POV==p->m_iPov?1.0f:0.0f);
bRet=true;
}
break;
default:
break;
}
}
if (event.EventType==EET_MOUSE_INPUT_EVENT)
for (i=0; i<m_aItems.size(); i++) {
CIrrCCItem *p=m_aItems[i];
if (p->m_iType==CC_TYPE_MBT) {
if (p->m_iMouseBtn==0) {
if (event.MouseInput.Event==EMIE_LMOUSE_PRESSED_DOWN) { p->setWithDetected(1.0f); bRet=true; }
if (event.MouseInput.Event==EMIE_LMOUSE_LEFT_UP ) { p->setWithDetected(0.0f); bRet=true; }
}
if (p->m_iMouseBtn==1) {
if (event.MouseInput.Event==EMIE_RMOUSE_PRESSED_DOWN) { p->setWithDetected(1.0f); bRet=true; }
if (event.MouseInput.Event==EMIE_RMOUSE_LEFT_UP ) { p->setWithDetected(0.0f); bRet=true; }
}
if (p->m_iMouseBtn==2) {
if (event.MouseInput.Event==EMIE_MMOUSE_PRESSED_DOWN) { p->setWithDetected(1.0f); bRet=true; }
if (event.MouseInput.Event==EMIE_MMOUSE_LEFT_UP ) { p->setWithDetected(0.0f); bRet=true; }
}
}
}
return bRet;
}
void CIrrCC::setMouseSensitivity(f32 f) {
m_fMouseSensitivity=f;
for (u32 i=0; i<m_aItems.size(); i++) m_aItems[i]->setMouseSensitivity(f);
}
void CIrrCC::reset() {
for (u32 i=0; i<m_aItems.size(); i++) {
m_aItems[i]->m_fValue=0.0f;
m_aItems[i]->m_fDetectedValue=0.0f;
}
}
void CIrrCC::createAxis(u32 idx1, u32 idx2) {
m_aItems[idx1]->m_pBrother=m_aItems[idx2];
m_aItems[idx2]->m_pBrother=m_aItems[idx1];
}
void CIrrCC::createFader(u32 idx1, u32 idx2, u32 iStep, f32 fInc) {
CIrrCCItem *item1=idx1<m_aItems.size()?m_aItems[idx1]:NULL,
*item2=idx2<m_aItems.size()?m_aItems[idx2]:NULL;
if (item1==NULL || item2==NULL) return;
item1->m_pBrother=item2;
item2->m_pBrother=item1;
item1->m_iFaderStep=iStep;
item2->m_iFaderStep=iStep;
item1->m_fFaderDiff= fInc;
item2->m_fFaderDiff=-fInc;
item1->m_fFaderValue=0.0f;
item2->m_fFaderValue=0.0f;
}
void CIrrCC::save(c8 *sFileName) {
IXMLWriter *pXml=m_pDevice->getFileSystem()->createXMLWriter(sFileName);
if (pXml) {
pXml->writeXMLHeader();
pXml->writeElement(L"IrrConfigControl");
pXml->writeLineBreak();
for (u32 i=0; i<m_aItems.size(); i++) {
CIrrCCItem *p=m_aItems[i];
array<stringw> names,values;
wchar_t s[0xFF];
names.push_back(stringw(L"name")); values.push_back(p->m_sName.c_str());
swprintf(s,0xFF,L"%u",p->m_iSet ); names.push_back(stringw(L"set" )); values.push_back(s );
swprintf(s,0xFF,L"%u",p->m_iType); names.push_back(stringw(L"type")); values.push_back(s );
switch (p->m_iType) {
case CC_TYPE_KEY:
names.push_back(stringw(L"key")); swprintf(s,0xFF,L"%u",(u32)p->m_eKey); values.push_back(s);
break;
case CC_TYPE_MOU:
names.push_back(stringw(L"m_axis")); swprintf(s,0xFF,L"%u",p->m_iMouseAxis ); values.push_back(s);
names.push_back(stringw(L"m_dir" )); swprintf(s,0xFF,L"%i",p->m_iMouseDirection); values.push_back(s);
break;
case CC_TYPE_MBT:
names.push_back(stringw(L"m_btn")); swprintf(s,0xFF,L"%u",p->m_iMouseBtn); values.push_back(s);
break;
case CC_TYPE_JOY:
names.push_back(stringw(L"joy" )); swprintf(s,0xFF,L"%u",p->m_iJoyId ); values.push_back(s);
names.push_back(stringw(L"j_axis")); swprintf(s,0xFF,L"%u",p->m_iJoyAxis ); values.push_back(s);
names.push_back(stringw(L"j_dir" )); swprintf(s,0xFF,L"%i",p->m_iJoyDirection); values.push_back(s);
break;
case CC_TYPE_JBT:
names.push_back(stringw(L"joy" )); swprintf(s,0xFF,L"%u",p->m_iJoyId ); values.push_back(s);
names.push_back(stringw(L"j_btn")); swprintf(s,0xFF,L"%u",p->m_iJoyButton); values.push_back(s);
break;
case CC_TYPE_POV:
names.push_back(stringw(L"joy")); swprintf(s,0xFF,L"%u",p->m_iJoyId); values.push_back(s);
names.push_back(stringw(L"pov")); swprintf(s,0xFF,L"%u",p->m_iPov ); values.push_back(s);
break;
default:
break;
}
pXml->writeElement(L"control",true,names,values);
pXml->writeLineBreak();
}
pXml->writeClosingTag(L"IrrConfigControl");
pXml->writeLineBreak();
pXml->drop();
}
}
void CIrrCC::load(c8 *sFileName) {
if (m_bLoaded) return;
IXMLReaderUTF8 *pXml=m_pDevice->getFileSystem()->createXMLReaderUTF8(sFileName);
u32 iNum=0;
if (pXml)
while (pXml->read() && iNum<m_aItems.size()) {
if (!strcmp(pXml->getNodeName(),"control")) {
CIrrCCItem *p=m_aItems[iNum];
p->m_iType=(IrrConfigControlTypes)(atoi(pXml->getAttributeValue("type")));
p->m_iSet =atoi(pXml->getAttributeValue("set"));
switch (p->m_iType) {
case CC_TYPE_KEY:
p->setKey((EKEY_CODE)atoi(pXml->getAttributeValue("key")));
break;
case CC_TYPE_MOU:
p->setMouseMove(atoi(pXml->getAttributeValue("m_axis")),atoi(pXml->getAttributeValue("m_dir")));
break;
case CC_TYPE_MBT:
p->setMouseButton(atoi(pXml->getAttributeValue("m_btn")));
break;
case CC_TYPE_JOY:
p->setJoyAxis(atoi(pXml->getAttributeValue("joy")),atoi(pXml->getAttributeValue("j_axis")),atoi(pXml->getAttributeValue("j_dir")));
break;
case CC_TYPE_JBT:
p->setJoyButton(atoi(pXml->getAttributeValue("joy")),atoi(pXml->getAttributeValue("j_btn")));
break;
case CC_TYPE_POV:
p->setPov(atoi(pXml->getAttributeValue("joy")),atoi(pXml->getAttributeValue("pov")));
break;
default:
break;
}
p->updateCtrlText();
iNum++;
}
}
m_bLoaded=true;
}