/*************************************************************************** * Copyright (C) 2003-2004 by Raphael Langerhorst * * raphael-langerhorst@gmx.at * * * * Permission is hereby granted, free of charge, to any person obtaining * * a copy of this software and associated documentation files (the * * "Software"), to deal in the Software without restriction, including * * without limitation the rights to use, copy, modify, merge, publish, * * distribute, sublicense, and/or sell copies of the Software, and to * * permit persons to whom the Software is furnished to do so, subject to * * the following conditions: * * * * The above copyright notice and this permission notice shall be * * included in all copies or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.* * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR * * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * * OTHER DEALINGS IN THE SOFTWARE. * ***************************************************************************/ #include "GElement.h" #include "GElementID.h" #include "GObject.h" #include "GElementInfluence.h" #include "GAgent.h" #include "GEnergy.h" #include "GForm.h" #include "GVector3.h" #include "GMatrix44.h" #include #include using namespace std; namespace GCS { // ###################### PUBLIC ################## GElement::GElement(GObject* object, const QDateTime& park_time) : Object(object), ParkTime(park_time) { } GElement::~GElement() { //stop all running agents emit park(); QValueList::iterator it; for (it = Agents.begin(); it != Agents.end(); ++it) { (*it)->wait(); //wait until thread is stopped before deleting (*it)->deleteLater(); //post a delete event (the event loop will delete it) } Q_CHECK_PTR(Object); if (Object) delete Object; } const GElementID& GElement::getElementID() const { Q_CHECK_PTR(Object); if (Object) return Object->getID(); else throw exception(); } QDateTime GElement::getParkTime() const { return this->ParkTime; } bool GElement::isParked() { //check all agents QValueList::iterator it; for (it = this->Agents.begin(); it != this->Agents.end(); ++it) { if ((*it)->running()) //directly accesses the QThread method return false; } return true; //when no running agent was found } QValueList GElement::getAgents() const { QValueList list; QValueList::const_iterator it; for (it = this->Agents.begin(); it != this->Agents.end(); ++it) { list.append(*it); } return list; } const GObject* GElement::getObject() const { Q_CHECK_PTR(Object); if (Object) return Object; else throw exception(); } // ################# PUBLIC SLOTS #################### void GElement::receiveInfluence(const GCS::GElementInfluence& influence) { QTime t(QTime::currentTime()); emit forwardInfluenceInternal(influence); //add the energy of the influence to own energy if (Object) { if (Object->hasEnergy()) { GEnergy* e = Object->getEnergy(); QMutexLocker m(e); e->put(influence.Energy); } } if (t.elapsed() > 100) { qWarning("Internal influence processing time longer than 100 milliseconds, this is bad agent design!!!"); } emit influenceReceived(influence); if (t.elapsed() > 100) { qWarning("External influence processing time longer than 100 milliseconds, this is bad agent design!!!"); } } void GElement::reparent(const GCS::GElementID& old_parent, const GCS::GElementID& new_parent, const GCS::GMatrix44& transformation) { if (Object) { if (old_parent != Object->getParent()) qWarning(QString("INCONSISTENCY DETECTED: Reparenting element %1, but old parent doesn't apply!").arg(old_parent.getID())); Object->reparent(new_parent); emit this->notifyReparentingInternal(old_parent,new_parent,transformation); if (this->Object->hasForm()) { GCS::GForm* f = Object->getForm(); QMutexLocker lock(f); f->Position = transformation.transform(f->Position); f->Rotation = transformation.transform(f->Rotation); } emit this->parentChanged(this,old_parent,new_parent,transformation); } } void GElement::addAgent(GCS::GAgent* agent) { agent->Object = this->Object; agent->Agents = &this->Agents; //connect signals from agent connect(agent,SIGNAL( sendInfluence(const GCS::GElementID&, const GCS::GElementInfluence&)), this,SIGNAL( sendInfluence(const GCS::GElementID&, const GCS::GElementInfluence&))); connect(agent,SIGNAL(radiateInfluence(const GCS::GElementInfluence&)), this,SIGNAL(radiateInfluence(const GCS::GElementInfluence&))); //connect slots from agent connect(this,SIGNAL(forwardInfluenceInternal(const GCS::GElementInfluence&)), agent,SLOT(receiveInfluence(const GCS::GElementInfluence&))); // control stuff (parking, executing) connect(this,SIGNAL(park()), agent,SLOT(beginPark())); // execute is used for "resuming" AND for starting the first time(!) connect(this,SIGNAL(execute(double)), agent,SLOT(threadStart(double))); // data change stuff connect(this,SIGNAL(notifyReparentingInternal(const GCS::GElementID&, const GCS::GElementID&, const GCS::GMatrix44& )), agent,SLOT(reparented(const GCS::GElementID&, const GCS::GElementID&, const GCS::GMatrix44& ))); connect(agent,SIGNAL(agentChanged(const GCS::GAgent& )), this,SIGNAL(agentChanged(const GCS::GAgent& ))); connect(agent,SIGNAL(energyChanged(const GCS::GEnergy& )), this,SIGNAL(energyChanged(const GCS::GEnergy& ))); connect(agent,SIGNAL(formChanged(const GCS::GForm& )), this,SIGNAL(formChanged(const GCS::GForm& ))); connect(agent,SIGNAL(childElementCreated(GCS::GElement* )), this,SIGNAL(childElementCreated(GCS::GElement* ))); connect(agent,SIGNAL(childElementRemoved(const GCS::GElementID& )), this,SIGNAL(childElementRemoved(const GCS::GElementID& ))); this->Agents.append(agent); } void GElement::removeAgent(GCS::GAgent* agent, bool del) { //park the agent agent->beginPark(); //wait until the agent is parked (the agent thread stops) agent->wait(); agent->Object = NULL; agent->Agents = NULL; //disconnect agent agent->disconnect(this); this->disconnect(agent); this->Agents.remove(agent); if (del) delete agent; } void GElement::parkElement() { // qDebug("Parking element " + QString::number(getElementID().getID())); emit park(); this->ParkTime = QDateTime::currentDateTime(); } void GElement::executeElement(double seconds_delta_t_offset) { // qDebug("Executing element " + QString::number(getElementID().getID())); QDateTime current = QDateTime::currentDateTime(); double delta_t = (double)(this->ParkTime.secsTo(current)) + seconds_delta_t_offset; emit execute(delta_t); } }