1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
#include "PerlOGRECallbackManager.h"
#include <string>
using namespace std;
PerlOGRECallbackManager::PerlOGRECallbackManager()
{
}
PerlOGRECallbackManager::~PerlOGRECallbackManager()
{
// clean up addFrameListener
for (FrameListenerMap::iterator it = mFrameListenerMap.begin(); it != mFrameListenerMap.end(); ++it) {
delete it->second;
}
mFrameListenerMap.clear();
// clean up addWindowEventListener
mWinEvtListenerWindowMMap.clear();
for (WinEvtListenerMap::iterator it = mWinEvtListenerMap.begin(); it != mWinEvtListenerMap.end(); ++it) {
delete it->second;
}
mWinEvtListenerMap.clear();
}
void PerlOGRECallbackManager::addFrameListener(SV *pobj, Ogre::Root *root)
{
if (sv_isobject(pobj)) {
PerlOGREFrameListener *fl = new PerlOGREFrameListener(pobj);
HV *stash = SvSTASH(SvRV(pobj));
string pkgname(HvNAME(stash));
// add to the manager
// (note: won't insert if pkgname already has a listener,
// that's how maps work)
pair<FrameListenerMap::iterator, bool> insertPair;
insertPair = mFrameListenerMap.insert(FrameListenerMap::value_type(pkgname, static_cast<Ogre::FrameListener *>(fl)));
if (insertPair.second) {
// add to Root if inserting worked (i.e. didn't already exist)
root->addFrameListener(fl);
} else {
warn("FrameListener %s not added (probably already added)\n", pkgname.c_str());
}
} else {
croak("Argument to addFrameListener has to be an object\n");
}
}
void PerlOGRECallbackManager::removeFrameListener(SV *pobj, Ogre::Root *root)
{
// get package name from object
HV *stash = SvSTASH(SvRV(pobj));
string pkgname(HvNAME(stash));
FrameListenerMap::iterator it = mFrameListenerMap.find(pkgname);
if (it != mFrameListenerMap.end()) {
// remove from Root
root->removeFrameListener(it->second);
// remove from the manager
delete it->second;
mFrameListenerMap.erase(it);
} else {
warn("removeFrameListener: %s didn't have a FrameListener, so not removed",
pkgname.c_str());
}
}
void PerlOGRECallbackManager::addWindowEventListener(SV *pobj, Ogre::RenderWindow *win)
{
if (sv_isobject(pobj)) {
PerlOGREWindowEventListener *wel = new PerlOGREWindowEventListener(pobj);
// As with FrameListener, we keep track of the Perl pkgname for each
// C++ listener
HV *stash = SvSTASH(SvRV(pobj));
string pkgname(HvNAME(stash));
mWinEvtListenerMap.insert(WinEvtListenerMap::value_type(pkgname, static_cast<Ogre::WindowEventListener *>(wel)));
// Now, we can have multiple listeners per window,
// and multiple windows per listener,
// so we also keep track of which Windows are associated
// with each Perl package
// find out if pkg is already mapped to this win;
// if so, don't insert and ignore all this
bool doInsert = true;
WinEvtListenerWindowMMap::iterator it = mWinEvtListenerWindowMMap.find(pkgname);
while (it != mWinEvtListenerWindowMMap.end() && it->first == pkgname) {
if (it->second == win) {
doInsert = false;
break;
}
++it;
}
if (doInsert) {
mWinEvtListenerWindowMMap.insert(WinEvtListenerWindowMMap::value_type(pkgname, win));
// do the C++ (the whole point of this manager crap :)
Ogre::WindowEventUtilities::addWindowEventListener(win, wel);
}
} else {
croak("Argument to addWindowEventListener has to be an object\n");
}
}
void PerlOGRECallbackManager::removeWindowEventListener(SV *pobj, Ogre::RenderWindow *win)
{
HV *stash = SvSTASH(SvRV(pobj));
string pkgname(HvNAME(stash));
WinEvtListenerMap::iterator mit = mWinEvtListenerMap.find(pkgname);
if (mit != mWinEvtListenerMap.end()) {
// First remove the listener->window mapping
WinEvtListenerWindowMMap::iterator mmit = mWinEvtListenerWindowMMap.find(pkgname);
while (mmit != mWinEvtListenerWindowMMap.end() && mmit->first == pkgname) {
if (mmit->second == win) {
// do the C++ part
Ogre::WindowEventUtilities::removeWindowEventListener(win, mit->second);
// and take it out of the manager
mWinEvtListenerWindowMMap.erase(mmit);
}
++mmit;
}
// Also, if that was the last window, get rid of the
// pkgname-listener mapping
if (mWinEvtListenerWindowMMap.empty()) {
delete mit->second; // cleanup object created in addWindowEventListener
mWinEvtListenerMap.erase(mit);
}
} else {
warn("removeWindowEventListener: %s didn't have a WindowEventListener, so not removed",
pkgname.c_str());
}
}
|