void EmberEntity::updateAttachment() { //Get the new location. We use getEmberLocation() since we always know that all entities are of type EmberEntity. EmberEntity* newLocationEntity = getEmberLocation(); if (newLocationEntity && newLocationEntity->getAttachment()) { try { IEntityAttachment* newAttachment = newLocationEntity->getAttachment()->attachEntity(*this); setAttachment(newAttachment); if (newAttachment) { newAttachment->updateScale(); } } catch (const std::exception& ex) { S_LOG_WARNING("Problem when creating new attachment for entity." << ex); } //If we're the top level entity the attachment has been set from the outside and shouldn't be changed. //FIXME This is a little hackish; how can we improve it to not require special cases? } else if (m_view->getTopLevel() == this) { return; } else { try { setAttachment(nullptr); } catch (const std::exception& ex) { S_LOG_WARNING("Problem when setting attachment for entity." << ex); } } }
void EmberEntity::onLocationChanged(Eris::Entity *oldLocation) { //Get the new location. We use getEmberLocation() since we always know that all entities are of type EmberEntity. EmberEntity* newLocationEntity = getEmberLocation(); if (newLocationEntity && newLocationEntity->getAttachment()) { try { IEntityAttachment* newAttachment = newLocationEntity->getAttachment()->attachEntity(*this); setAttachment(newAttachment); if (newAttachment) { newAttachment->updateScale(); } } catch (const std::exception& ex) { S_LOG_WARNING("Problem when creating new attachment for entity." << ex); } } else { try { setAttachment(0); } catch (const std::exception& ex) { S_LOG_WARNING("Problem when setting attachment for entity." << ex); } } Eris::Entity::onLocationChanged(oldLocation); }
std::string EntityTooltip::composeEntityInfoText(EmberEntity& entity) { std::stringstream ss; if (entity.getName() != "") { ss << entity.getName() << " (of type " << entity.getType()->getName() << ")"; } else { ss << entity.getType()->getName(); } if (entity.hasAttr("biomass")) { ss << std::endl << "Edible"; } if (entity.hasAttr("right_hand_wield")) { ss << std::endl << "Wieldable"; } if (entity.hasAttr("worn")) { const Atlas::Message::Element& element = entity.valueOfAttr("worn"); if (element.isString()) { ss << std::endl << "Worn on the " << element.asString(); } } std::vector<std::string> actions = entity.getActions(); if (actions.size()) { for (std::vector<std::string>::const_iterator I = actions.begin(); I != actions.end(); ++I) { ss << std::endl << "Can be used to " << *I; } } std::vector<std::string> operations = entity.getDefaultUseOperators(); if (operations.size()) { for (std::vector<std::string>::const_iterator I = operations.begin(); I != operations.end(); ++I) { ss << std::endl << "Can be used to " << *I; } } return ss.str(); }
SimpleEntityVisualization::SimpleEntityVisualization(EmberEntity& entity, Ogre::SceneNode* sceneNode) : mEntity(entity), mSceneNode(sceneNode), mErisEntityBoundingBox(OGRE_NEW Ogre::OOBBWireBoundingBox()), mBboxConnection(entity.observe("bbox", sigc::mem_fun(*this, &SimpleEntityVisualization::entity_BboxChanged))), mScaleConnection(entity.observe("scale", sigc::mem_fun(*this, &SimpleEntityVisualization::entity_BboxChanged))) { mVelocityArrowEntity = sceneNode->getCreator()->createEntity("common/primitives/model/arrow.mesh"); mVelocitySceneNode = sceneNode->getParentSceneNode()->createChildSceneNode(); mVelocitySceneNode->attachObject(mVelocityArrowEntity); mVelocitySceneNode->setScale(0.5, 0.5, 0.5); try { auto materialPtr = Ogre::MaterialManager::getSingleton().getByName(BboxMaterialName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); if (materialPtr) { mErisEntityBoundingBox->setMaterial(materialPtr); } } catch (const std::exception& ex) { S_LOG_FAILURE("Error when setting Ogre material for bounding box."); OGRE_DELETE mErisEntityBoundingBox; mErisEntityBoundingBox = nullptr; throw Exception("Error when setting Ogre material for bounding box."); } mSceneNode->attachObject(mErisEntityBoundingBox); mErisEntityBoundingBox->setVisible(true); updateBbox(); updatePositionAndOrientation(); mEntity.Moved.connect(sigc::mem_fun(*this, &SimpleEntityVisualization::entity_Moved)); }
void EmberEntity::reattachChildren() { for (unsigned int i = 0; i < numContained(); ++i) { EmberEntity* entity = getEmberContained(i); if (entity) { entity->updateAttachment(); entity->reattachChildren(); } } }
void EmberEntity::accept(IEntityVisitor& visitor) { visitor.visit(*this); for (unsigned int i = 0; i < numContained(); ++i) { EmberEntity* entity = getEmberContained(i); if (entity) { entity->accept(visitor); } } }
void EmberEntity::reattachChildren() { for (unsigned int i = 0; i < numContained(); ++i) { EmberEntity* entity = getEmberContained(i); if (entity) { entity->onLocationChanged(entity->getEmberLocation()); entity->reattachChildren(); } } }
void EmberEntity::accept(std::function<bool(const EmberEntity&)>& visitor) const { if (visitor(*this)) { for (unsigned int i = 0; i < numContained(); ++i) { EmberEntity* entity = getEmberContained(i); if (entity) { entity->accept(visitor); } } } }
// create whatever entity the client desires Eris::Entity* EmberEntityFactory::instantiate(const Atlas::Objects::Entity::RootEntity &ge, Eris::TypeInfo* type, Eris::View* w) { EmberEntity* entity = new EmberEntity(ge->getId(), type, w); //the creator binds the model mapping and this instance together by creating instance of EmberEntityModelAction and EmberEntityPartAction which in turn calls the setModel(..) and show/hideModelPart(...) methods. EmberEntityActionCreator creator(*entity, mScene); EntityMapping::EntityMapping* mapping = Mapping::EmberEntityMappingManager::getSingleton().getManager().createMapping(*entity, creator, &mView); entity->BeingDeleted.connect(sigc::bind(sigc::mem_fun(*this, &EmberEntityFactory::deleteMapping), mapping)); mapping->initialize(); S_LOG_VERBOSE("Entity " << entity->getId() << " (" << type->getName() << ") added to game view."); return entity; }
void EntityMoveManager::startMove(EmberEntity& entity) { //disallow moving of the root entity if (entity.getLocation()) { //Only provide movement for entities which have a node attachment. NodeAttachment* attachment = dynamic_cast<NodeAttachment*> (entity.getAttachment()); if (attachment) { EntityMover* mover = new EntityMover(*attachment, *this); mMoveAdapter.attachToBridge(mover); //The EntityMoveInstance will delete itself when either movement is finished or the entity is deleted, so we don't need to hold a reference to it. new EntityMoveInstance(entity, mMoveAdapter, EventFinishedMoving, EventCancelledMoving); EventStartMoving.emit(entity, *mover); } } }
AvatarLogger::AvatarLogger(EmberEntity& avatarEntity) : mChatLogger(nullptr) { assert(&avatarEntity); //Put log files in a "logs" subdirectory of the home directory. const std::string dir = EmberServices::getSingleton().getConfigService().getHomeDirectory() + "/logs/"; try { //make sure the directory exists oslink::directory osdir(dir); if (!osdir.isExisting()) { oslink::directory::mkdir(dir.c_str()); } //perform setup of the stream std::stringstream logFileSS; logFileSS << dir << "/" << avatarEntity.getName() << "_chatlog.log"; mChatLogger = std::unique_ptr<std::ofstream>(new std::ofstream(logFileSS.str().c_str(), std::ios::app)); S_LOG_VERBOSE("Chat Logging set to write in [ " << logFileSS.str() << " ]"); *mChatLogger << "-------------------------------------------------------" << std::endl; *mChatLogger << "Chat Logging Initialized at " << Time::getLocalTimeStr() << std::endl; *mChatLogger << "-------------------------------------------------------" << std::endl; //wait with connecting until everything has been properly set up GUIManager::getSingleton().AppendIGChatLine.connect(sigc::mem_fun(*this, &AvatarLogger::GUIManager_AppendIGChatLine)); } catch (const std::exception& ex) { S_LOG_FAILURE("Error when creating directory for logs." << ex); } }
void TerrainEntityManager::entityTerrainAttrChanged(EmberEntity& entity, const Atlas::Message::Element& value) { if (!mTerrainEntityDeleteConnection) { mTerrainEntityDeleteConnection = entity.BeingDeleted.connect([this](){ mTerrainHandler.EventTerrainDisabled(); mTerrainEntityDeleteConnection.disconnect(); }); } Terrain::TerrainShaderParser terrainShaderParser(mTerrainHandler); terrainShaderParser.createShaders(value); Terrain::TerrainParser terrainParser; WFMath::Point<3> pos = entity.getPosition().isValid() ? entity.getPredictedPos() : WFMath::Point<3>::ZERO(); mTerrainHandler.updateTerrain(terrainParser.parseTerrain(value, pos)); entity.setHeightProvider(&mTerrainHandler); mTerrainHandler.EventTerrainEnabled(entity); }
EmberEntity* EmberEntity::getAttachedEntity(const std::string& namedPoint) { //HACK: this is just a temporary solution if (hasAttr(namedPoint)) { const Atlas::Message::Element& idElement = valueOfAttr(namedPoint); std::string id; if (Eris::Entity::extractEntityId(idElement, id)) { for (unsigned int i = 0; i < numContained(); ++i) { EmberEntity* entity = getEmberContained(i); if (entity && entity->getId() == id) { return entity; } } } } return 0; }
void EmberEntityFactory::dumpAttributesOfEntity(const std::string& entityId) const { EmberEntity* entity = static_cast<EmberEntity*>(mView.getEntity(entityId)); if (entity) { //make sure the directory exists std::string dir(EmberServices::getSingleton().getConfigService().getHomeDirectory() + "/entityexport/"); if (!oslink::directory(dir).isExisting()) { S_LOG_INFO("Creating directory " << dir); oslink::directory::mkdir(dir.c_str()); } const std::string fileName(dir + entityId + ".atlas"); std::fstream exportFile(fileName.c_str(), std::fstream::out); S_LOG_INFO("Dumping attributes to " << fileName); entity->dumpAttributes(exportFile, std::cout); ConsoleBackend::getSingletonPtr()->pushMessage(std::string("Dumped attributes to ") + fileName, "info"); } }
void TerrainEntityManager::entityAreaAttrChanged(EmberEntity& entity, const Atlas::Message::Element& value) { Terrain::TerrainArea* terrainArea; auto I = mAreas.find(&entity); if (I == mAreas.end()) { terrainArea = new Terrain::TerrainArea(entity); mAreas.insert(std::make_pair(&entity, terrainArea)); terrainArea->EventEntityBeingDeleted.connect(sigc::bind(sigc::mem_fun(*this, &TerrainEntityManager::entityBeingDeletedArea), &entity)); terrainArea->EventEntityMoved.connect(sigc::bind(sigc::mem_fun(*this, &TerrainEntityManager::entityMovedArea), &entity)); } else { terrainArea = I->second; } Mercator::Area* area = nullptr; terrainArea->parse(value, &area); mTerrainHandler.updateArea(entity.getId(), area); delete area; }
void EntityWorldPickListener::processPickResult(bool& continuePicking, Ogre::RaySceneQueryResultEntry& entry, Ogre::Ray& cameraRay, const MousePickerArgs& mousePickerArgs) { if (!mContinuePickingThisContext) { return; } if (entry.worldFragment) { //this is terrain //a position of -1, -1, -1 is not valid terrain Ogre::SceneQuery::WorldFragment* wf = entry.worldFragment; static const Ogre::Vector3 invalidPos(-1, -1, -1); if (wf->singleIntersection != invalidPos) { if (mFurthestPickingDistance == 0 || mResult.empty()) { EntityPickResult result; result.entity = findTerrainEntity(); result.position = wf->singleIntersection; result.distance = entry.distance; result.isTransparent = false; mResult.push_back(result); mContinuePickingThisContext = false; } else { if (entry.distance < mResult[mResult.size() - 1].distance) { //If the last result is transparent, add another result, but if it's not replace it. if (mResult.size() && !mResult[mResult.size() - 1].isTransparent) { mResult.pop_back(); } EntityPickResult result; result.entity = findTerrainEntity(); result.position = wf->singleIntersection; result.distance = entry.distance; result.isTransparent = false; mResult.push_back(result); mContinuePickingThisContext = false; } } } /* std::stringstream ss; ss << wf->singleIntersection; S_LOG_VERBOSE("Picked in terrain: " << ss.str() << " distance: " << mResult.distance);*/ } else if (entry.movable) { Ogre::MovableObject* pickedMovable = entry.movable; if (pickedMovable->isVisible() && pickedMovable->getUserObjectBindings().getUserAny().getType() == typeid(EmberEntityUserObject::SharedPtr)) { EmberEntityUserObject* anUserObject = Ogre::any_cast<EmberEntityUserObject::SharedPtr>(pickedMovable->getUserObjectBindings().getUserAny()).get(); //refit the opcode mesh to adjust for changes in the mesh (for example animations) anUserObject->refit(); ICollisionDetector* collisionDetector = anUserObject->getCollisionDetector(); if (collisionDetector) { CollisionResult collisionResult; collisionResult.collided = false; collisionResult.isTransparent = false; collisionDetector->testCollision(cameraRay, collisionResult); if (collisionResult.collided) { if (mFurthestPickingDistance == 0) { //If the current collision is transparent, also check for entities which are further away. if (!collisionResult.isTransparent) { //test all objects that fall into this distance mFurthestPickingDistance = (pickedMovable->getParentNode()->_getDerivedPosition() - cameraRay.getOrigin()).length() + pickedMovable->getBoundingRadius(); } } else { if (collisionResult.distance > mFurthestPickingDistance) { mContinuePickingThisContext = false; return; } else { if (!mResult.empty() && mResult[mResult.size() - 1].distance > collisionResult.distance) { //If the last result is transparent, add another result, but if it's not replace it. if (!mResult[mResult.size() - 1].isTransparent) { mResult.pop_back(); } } else { return; } } } EmberEntity& pickedEntity = anUserObject->getEmberEntity(); std::list<EmberEntity*> entities; entities.push_front(&pickedEntity); EmberEntity* entity = pickedEntity.getEmberLocation(); while (entity) { if (entity->getCompositionMode() == EmberEntity::CM_COMPOSITION) { entities.push_front(entity); } else if (entity->getCompositionMode() == EmberEntity::CM_COMPOSITION_EXCLUSIVE) { entities.clear(); entities.push_front(entity); } entity = entity->getEmberLocation(); } for (std::list<EmberEntity*>::const_iterator I = entities.begin(); I != entities.end(); ++I) { EntityPickResult result; result.entity = *I; result.position = collisionResult.position; result.distance = collisionResult.distance; result.isTransparent = collisionResult.isTransparent; mResult.push_back(result); } } } } } }
void TerrainEntityManager::topLevelEntityChanged() { EmberEntity* entity = static_cast<EmberEntity*>(mView.getTopLevel()); entity->setAttachment(nullptr); entity->setAttachment(new WorldAttachment(*entity, mSceneManager.getRootSceneNode()->createChildSceneNode("entity_" + entity->getId()))); }
SimpleEntityVisualization::SimpleEntityVisualization(EmberEntity& entity, Ogre::SceneNode* sceneNode) : mEntity(entity), mSceneNode(sceneNode), mErisEntityBoundingBox(OGRE_NEW Ogre::OOBBWireBoundingBox()), mBboxConnection(entity.observe("bbox", sigc::mem_fun(*this, &SimpleEntityVisualization::entity_BboxChanged))) { try { mErisEntityBoundingBox->setMaterial(BboxMaterialName); } catch (const std::exception& ex) { S_LOG_FAILURE("Error when setting Ogre material for bounding box."); OGRE_DELETE mErisEntityBoundingBox; mErisEntityBoundingBox = 0; throw Exception("Error when setting Ogre material for bounding box."); } mSceneNode->attachObject(mErisEntityBoundingBox); mErisEntityBoundingBox->setVisible(true); updateBbox(); updatePositionAndOrientation(); mEntity.Moved.connect(sigc::mem_fun(*this, &SimpleEntityVisualization::entity_Moved)); }