// Description: a space that generates events in the presence of a node
//
//notes:
//
//- derived nodes inherit all messages from their base classes
//
- see reset method for default settings
//
- this node generates events with the name of the node detected
//
- the local mode determines if the node position is local to the object or relative to world coordinates
//
//
// Category: Trigger
// Author: Alex Hill
// Revision: 10/01/02
//
#include
#include
#include
#include
#include "betterNodeTrigger.h"
using namespace std;
extern "C" ygNode* construct_betterNodeTrigger(const char* name,bool master) { return new betterNodeTrigger(name,master); }
struct _betterNodeTriggerPrivateData
{
ygString detectType;
ygString detectName;
set prevInside;
bool debugInside;
int lastFrame;
};
betterNodeTrigger::betterNodeTrigger(const char* name,bool master) : ygSpace(name,master)
{
setClassName("betterNodeTrigger");
p_ = new struct _betterNodeTriggerPrivateData;
p_->lastFrame = 0;
debugFlag("inside", &p_->debugInside);
}
betterNodeTrigger::~betterNodeTrigger(void)
{
delete p_;
}
void betterNodeTrigger::reset(void)
{
//clear set of nodes previously inside
p_->prevInside.clear();
p_->lastFrame = ygWorld::FrameNumber;
ygSpace::reset();
}
void betterNodeTrigger::message(const ygMessage& msg)
{
//set the type of node to detect
if (msg == "type")
{
if (msg.args.size() > 0)
setDetectType(msg.args[0]);
else
msg.error(name(),"(wrong number of arguments)");
}
else if (msg == "node")
{
setDetectName(msg.args[0]);
}
else
ygSpace::message(msg);
}
void betterNodeTrigger::setDetectType(const ygString& s)
{
p_->detectType = s;
}
void betterNodeTrigger::setDetectName(const ygString& s)
{
p_->detectName = s;
}
void betterNodeTrigger::app(void)
{
set inside;
int i;
if (p_->lastFrame < (ygWorld::FrameNumber-1))
p_->prevInside.clear();
p_->lastFrame = ygWorld::FrameNumber;
const vector& nodes = ygNodeDB::nodesOfType(p_->detectType);
//for each node of detect type in the world
for (i=0; i < nodes.size(); i++)
{
if (p_->detectName == "" || nodes[i]->name() == p_->detectName)
{
//if node is within the space
if (contains(nodes[i]->origin(this)))
{
if (p_->debugInside)
cout << name() << ": " << nodes[i]->name() << " is inside\n";
//add to set of nodes inside
inside.insert(inside.begin(),nodes[i]);
//if inside but not previously then generate enter event
if (p_->prevInside.find(nodes[i]) == p_->prevInside.end())
{
ygString args("node=");
args += nodes[i]->name();
//the node has entered the space
eventOccurred("enter",args);
}
}
}
}
set::const_iterator iter;
//for each node previously inside
for (iter = p_->prevInside.begin(); iter != p_->prevInside.end();
++iter)
//if not currently inside then generate exit event
if (inside.find(*iter) == inside.end())
{
ygString args("node=");
args += (*iter)->name();
//the node has exited the space
eventOccurred("exit",args);
}
p_->prevInside = inside;
ygSpace::app();
}