Beispiel #1
0
void PhaseClose :: begin  (){
    message().format(255, 0, 39, 0);
    Tool::sendToAll(entities(), message());
    for(auto e : entities()){
        e->wait();
    }
    finish();
}
Beispiel #2
0
QComponent::~QComponent()
{
    Q_ASSERT_X(QNodePrivate::get(this)->m_wasCleanedUp, Q_FUNC_INFO, "QNode::cleanup should have been called by now. A Qt3DCore::QComponent subclass didn't call QNode::cleanup in its destructor");

    Q_FOREACH (QEntity *entity, entities()) {
        QEntityPrivate *entityPimpl = static_cast<QEntityPrivate *>(QEntityPrivate::get(entity));
        if (entityPimpl)
            entityPimpl->m_components.removeAll(this);
    }
void EntityModel::setEntityScale(float value)
{
	Lumix::StackAllocator<256> allocator;
	Lumix::Array<Lumix::Entity> entities(allocator);
	Lumix::Array<float> scales(allocator);
	entities.push(m_entity);
	scales.push(value);
	m_editor.setEntitiesScales(entities, scales);
}
void EntityModel::setEntityPosition(int index, float value)
{
	Lumix::Vec3 v = getUniverse()->getPosition(m_entity);
	((float*)&v)[index] = value;
	Lumix::StackAllocator<256> allocator;
	Lumix::Array<Lumix::Entity> entities(allocator);
	Lumix::Array<Lumix::Vec3> positions(allocator);
	entities.push(m_entity);
	positions.push(v);
	m_editor.setEntitiesPositions(entities, positions);
}
void EntityModel::setEntityRotation(int index, float value)
{
	auto axis_angle = getUniverse()->getRotation(m_entity).getAxisAngle();
	((float*)&axis_angle)[index] = value;
	axis_angle.axis.normalize();
	Lumix::StackAllocator<256> allocator;
	Lumix::Array<Lumix::Entity> entities(allocator);
	Lumix::Array<Lumix::Quat> rotations(allocator);
	entities.push(m_entity);
	rotations.push(Lumix::Quat(axis_angle.axis, axis_angle.angle));
	m_editor.setEntitiesRotations(entities, rotations);
}
Beispiel #6
0
void EmberEntityLoader::loadPage(::Forests::PageInfo & page)
{
	static Ogre::ColourValue colour(1, 1, 1, 1);

#if EMBERENTITYLOADER_USEBATCH
	const int batchX = static_cast<int>(Ogre::Math::Floor(page.bounds.left/ mBatchSize));
	const int batchY = static_cast<int>(Ogre::Math::Floor(page.bounds.top / mBatchSize));
	EntityMap& entities(mEntities[batchX][batchY]);
#else
	EntityMap& entities(mEntities);
#endif

	for (EntityMap::iterator I = entities.begin(); I != entities.end(); ++I) {
		ModelRepresentationInstance& instance(I->second);
		Model::ModelRepresentation* modelRepresentation(instance.modelRepresentation);
		EmberEntity& emberEntity = modelRepresentation->getEntity();
		if (emberEntity.isVisible()) {
			WFMath::Point<3> viewPos = emberEntity.getViewPosition();
			if (viewPos.isValid()) {
				Ogre::Vector3 pos(Convert::toOgre(viewPos));
				Model::Model& model(modelRepresentation->getModel());
				Ogre::Node* node = model.getParentNode();
				if (node) {
					const Ogre::Vector3& pos = node->_getDerivedPosition();
					if (pos.x > page.bounds.left && pos.x < page.bounds.right && pos.z > page.bounds.top && pos.z < page.bounds.bottom) {
						for (Model::Model::SubModelSet::const_iterator J = model.getSubmodels().begin(); J != model.getSubmodels().end(); ++J) {
							// 				if (!(*J)->getEntity()->getParentSceneNode()) {
							// 					model->getParentSceneNode()->attachObject((*J)->getEntity());
							// 				}
							//  				if ((*J)->getEntity()->isVisible()) {
							addEntity((*J)->getEntity(), pos, node->_getDerivedOrientation(), modelRepresentation->getScale(), colour);
							// 					(*J)->getEntity()->setVisible(false);
							//  				}
						}
					}
				}
			}
		}
	}
}
Beispiel #7
0
void EmberEntityLoader::addEmberEntity(Model::ModelRepresentation* modelRepresentation)
{
	if (!modelRepresentation) {
		S_LOG_WARNING("Tried to add a null ref entity to the paged geometry.");
		return;
	}
	EmberEntity& entity = modelRepresentation->getEntity();
	ModelRepresentationInstance instance;
	instance.movedConnection = entity.Moved.connect(sigc::bind(sigc::mem_fun(*this, &EmberEntityLoader::EmberEntity_Moved), &entity));
	instance.beingDeletedConnection = entity.BeingDeleted.connect(sigc::bind(sigc::mem_fun(*this, &EmberEntityLoader::EmberEntity_BeingDeleted), &entity));
	instance.visibilityChangedConnection = entity.VisibilityChanged.connect(sigc::bind(sigc::mem_fun(*this, &EmberEntityLoader::EmberEntity_VisibilityChanged), &entity));
	instance.modelRepresentation = modelRepresentation;

	WFMath::Point<3> viewPosition = entity.getViewPosition();
	Ogre::Vector3 position(std::numeric_limits<Ogre::Real>::quiet_NaN(), std::numeric_limits<Ogre::Real>::quiet_NaN(), std::numeric_limits<Ogre::Real>::quiet_NaN());

	bool isValidPos = false;
	if (viewPosition.isValid()) {
		isValidPos = true;
		position = Convert::toOgre(viewPosition);
	}
	instance.lastPosition = position;
#if EMBERENTITYLOADER_USEBATCH
	const int batchX = Ogre::Math::Floor(position.x / mBatchSize);
	const int batchY = Ogre::Math::Floor(position.y / mBatchSize);
	mEntityLookup[entity] = std::pair<int, int>(batchX, batchY);

	EntityMap& entities(mEntities[batchX][batchY]);
#else
	EntityMap& entities(mEntities);
#endif
	entities[entity.getId()] = instance;

	if (isValidPos) {
		//Rebuild geometry if necessary
		mGeom.reloadGeometryPage(position);
	}

}
Beispiel #8
0
CJsonNode g_GenericStatToJson(CNetServer server,
        ENetScheduleStatTopic topic, bool verbose)
{
    string stat_cmd(s_StatTopics[topic].command);
    CTempString prefix(s_StatTopics[topic].record_prefix);
    CTempString entity_name(s_StatTopics[topic].entity_name);

    if (verbose)
        stat_cmd.append(" VERBOSE");

    CNetServerMultilineCmdOutput output(server.ExecWithRetry(stat_cmd, true));

    CJsonNode entities(CJsonNode::NewArrayNode());
    CJsonNode entity_info;
    CJsonNode array_value;

    string line;

    while (output.ReadLine(line)) {
        if (NStr::StartsWith(line, prefix)) {
            if (entity_info)
                entities.Append(entity_info);
            entity_info = CJsonNode::NewObjectNode();
            entity_info.SetString(entity_name, UnquoteIfQuoted(
                    CTempString(line.data() + prefix.length(),
                    line.length() - prefix.length())));
        } else if (entity_info && NStr::StartsWith(line, "  ")) {
            if (NStr::StartsWith(line, "    ") && array_value) {
                array_value.AppendString(UnquoteIfQuoted(
                        NStr::TruncateSpaces(line, NStr::eTrunc_Begin)));
            } else {
                if (array_value)
                    array_value = NULL;
                CTempString key, value;
                NStr::SplitInTwo(line, ":", key, value);
                NormalizeStatKeyName(key);
                string key_norm(key);
                value = NStr::TruncateSpaces_Unsafe(value, NStr::eTrunc_Begin);
                if (value.empty())
                    entity_info.SetByKey(key_norm, array_value =
                            CJsonNode::NewArrayNode());
                else
                    entity_info.SetByKey(key_norm, CJsonNode::GuessType(value));
            }
        }
    }
    if (entity_info)
        entities.Append(entity_info);

    return entities;
}
vector_ptr<entity_ptr> EntityEngine::getEntities(ComponentFamily& family)
{
    auto familyIt = familyEntities.find(family);
    if (familyIt != familyEntities.end()) {
        return familyIt->second;
    }

    vector_ptr<entity_ptr> entities(new vector<entity_ptr>());
    familyEntities[family] = entities;

    updateFamilyMembershipAll();

    return entities;
}
Beispiel #10
0
	void savePrefab(const Path& path) override
	{
		auto& selected_entities = m_editor.getSelectedEntities();
		if (selected_entities.size() != 1) return;

		Entity entity = selected_entities[0];
		u64 prefab = getPrefab(entity);
		if (prefab != 0) entity = getPrefabRoot(entity);

		FS::OsFile file;
		if (!file.open(path.c_str(), FS::Mode::CREATE_AND_WRITE))
		{
			g_log_error.log("Editor") << "Failed to create " << path.c_str();
			return;
		}

		Array<Entity> entities(m_editor.getAllocator());
		gatherHierarchy(entity, true, entities);
		OutputBlob blob(m_editor.getAllocator());
		SaveEntityGUIDMap entity_map(entities);
		TextSerializer serializer(blob, entity_map);

		serializePrefab(m_universe, entities[0], path, serializer);

		file.write(blob.getData(), blob.getPos());

		file.close();

		if (prefab == 0)
		{
			m_editor.beginCommandGroup(crc32("save_prefab"));

			Transform tr = m_universe->getTransform(entity);
			m_editor.destroyEntities(&entities[0], entities.size());
			auto* resource_manager = m_editor.getEngine().getResourceManager().get(PrefabResource::TYPE);
			auto* res = (PrefabResource*)resource_manager->load(path);
			FS::FileSystem& fs = m_editor.getEngine().getFileSystem();
			while (fs.hasWork()) fs.updateAsyncTransactions();
			instantiatePrefab(*res, tr.pos, tr.rot, tr.scale);

			m_editor.endCommandGroup();
		}
	}
void PendingLoggerEntitiesImpl::operationFinished(KTp::PendingLoggerOperation* op)
{
    Q_ASSERT(mRunningOps.contains(op));
    mRunningOps.removeAll(op);

    KTp::PendingLoggerEntities *operation = qobject_cast<KTp::PendingLoggerEntities*>(op);
    Q_ASSERT(operation);

    const QList<KTp::LogEntity> newEntities = operation->entities();
    qCDebug(KTP_LOGGER) << "Plugin" << op->parent() << "returned" << newEntities.count() << "entities";
    Q_FOREACH (const KTp::LogEntity &entity, newEntities) {
        if (!entities().contains(entity)) {
            appendEntity(entity);
        }
    }

    if (mRunningOps.isEmpty()) {
        emitFinished();
    }
}
MojErr ResourceContainer::ToJson(MojObject& rep) const
{
	MojErr err = rep.putString(_T("name"), m_name.c_str());
	MojErrCheck(err);

	err = rep.putString(_T("priority"), ActivityPriorityNames[GetPriority()]);
	MojErrCheck(err);

	err = rep.putBool(_T("focused"), IsFocused());
	MojErrCheck(err);

	MojObject entities(MojObject::TypeArray);

	std::for_each(m_entities.begin(), m_entities.end(),
		boost::bind(&BusEntity::PushJson, _1, boost::ref(entities), false));

	err = rep.put(_T("entities"), entities);
	MojErrCheck(err);

	return MojErrNone;
}
Beispiel #13
0
void Reader::do_read_mesh_into(const common::URI& path, Mesh& mesh)
{
  boost::shared_ptr<common::XML::XmlDoc> doc = common::XML::parse_file(path);
  common::XML::XmlNode mesh_node(doc->content->first_node("mesh"));

  common::PE::Comm& comm = common::PE::Comm::instance();
  
  if(!mesh_node.is_valid())
    throw common::FileFormatError(FromHere(), "File " + path.path() + " has no mesh node");
  
  if(mesh_node.attribute_value("version") != "1")
    throw common::FileFormatError(FromHere(), "File " + path.path() + " has incorrect version " + mesh_node.attribute_value("version") + "(expected 1)");

  if(common::from_str<Uint>(mesh_node.attribute_value("nb_procs")) != comm.size())
    throw common::FileFormatError(FromHere(), "File " + path.path() + " has was created for " + mesh_node.attribute_value("nb_procs") + " processes and can't load on " + common::to_str(comm.size()) + " processors");
  
  boost::shared_ptr<common::BinaryDataReader> data_reader = common::allocate_component<common::BinaryDataReader>("DataReader");
  data_reader->options().set("file", common::URI(mesh_node.attribute_value("binary_file")));
  
  common::XML::XmlNode topology_node = mesh_node.content->first_node("topology");
  if(!topology_node.is_valid())
    throw common::FileFormatError(FromHere(), "File " + path.path() + " does has no topology node");
  
  common::XML::XmlNode region_node(topology_node.content->first_node("region"));
  typedef std::map<Handle< common::List<Uint> >, std::string> PeriodicMapT;
  PeriodicMapT periodic_links_map; // Collect a map of the periodic links to create, if any
  for(; region_node.is_valid(); region_node.content = region_node.content->next_sibling("region"))
  {
    Region& region = mesh.topology().create_region(region_node.attribute_value("name"));
    common::XML::XmlNode elements_node(region_node.content->first_node("elements"));
    for(; elements_node.is_valid(); elements_node.content = elements_node.content->next_sibling("elements"))
    {
      Elements& elems = region.create_elements(elements_node.attribute_value("element_type"), mesh.geometry_fields());
      data_reader->read_list(elems.glb_idx(), common::from_str<Uint>(elements_node.attribute_value("global_indices")));
      data_reader->read_list(elems.rank(), common::from_str<Uint>(elements_node.attribute_value("ranks")));
      common::XML::XmlNode periodic_node(elements_node.content->first_node("periodic_links_elements"));
      if(periodic_node.is_valid())
      {
        Handle< common::List<Uint> > periodic_links_elements = elems.create_component< common::List<Uint> >("periodic_links_elements");
        data_reader->read_list(*periodic_links_elements, common::from_str<Uint>(periodic_node.attribute_value("index")));
        periodic_links_map.insert(std::make_pair(periodic_links_elements, periodic_node.attribute_value("periodic_link")));
      }
    }
  }

  // Link the periodic elements, now all elements have been created
  for(PeriodicMapT::const_iterator it = periodic_links_map.begin(); it != periodic_links_map.end(); ++it)
  {
    Handle<common::Link> link = it->first->create_component<common::Link>("periodic_link");
    Handle<Elements> elements_to_link(mesh.access_component(common::URI(it->second, common::URI::Scheme::CPATH)));
    if(is_null(elements_to_link))
      throw common::FileFormatError(FromHere(), "Invalid periodic link: " + it->second);

    link->link_to(*elements_to_link);
  }
  
  common::XML::XmlNode dictionaries_node(mesh_node.content->first_node("dictionaries"));
  if(!dictionaries_node.is_valid())
    throw common::FileFormatError(FromHere(), "File " + path.path() + " does has no dictionaries node");
  
  common::XML::XmlNode dictionary_node(dictionaries_node.content->first_node("dictionary"));
  for(; dictionary_node.is_valid(); dictionary_node.content = dictionary_node.content->next_sibling("dictionary"))
  {
    const std::string dict_name = dictionary_node.attribute_value("name");
    // Add the coordinates first
    if(dict_name == "geometry")
    {
      common::XML::XmlNode field_node(dictionary_node.content->first_node("field"));
      for(; field_node.is_valid(); field_node.content = field_node.content->next_sibling("field"))
      {
        if(field_node.attribute_value("name") == "coordinates")
        {
          const Uint table_idx = common::from_str<Uint>(field_node.attribute_value("table_idx"));
          mesh.initialize_nodes(data_reader->block_rows(table_idx), data_reader->block_cols(table_idx));
          data_reader->read_table(mesh.geometry_fields().coordinates(), table_idx);
        }
      }
      
      // Periodic links
      if(is_not_null(dictionary_node.content->first_attribute("periodic_links_nodes")) && is_not_null(dictionary_node.content->first_attribute("periodic_links_active")))
      {
        cf3_assert(is_null(mesh.geometry_fields().get_child("periodic_links_nodes")));
        cf3_assert(is_null(mesh.geometry_fields().get_child("periodic_links_active")));
        Handle< common::List<Uint> >  periodic_links_nodes = mesh.geometry_fields().create_component< common::List<Uint> >("periodic_links_nodes");
        Handle< common::List<bool> > periodic_links_active = mesh.geometry_fields().create_component< common::List<bool> >("periodic_links_active");
        data_reader->read_list(*periodic_links_nodes, common::from_str<Uint>(dictionary_node.attribute_value("periodic_links_nodes")));
        data_reader->read_list(*periodic_links_active, common::from_str<Uint>(dictionary_node.attribute_value("periodic_links_active")));
      }
    }
  }
  
  dictionary_node.content = dictionaries_node.content->first_node("dictionary");
  for(; dictionary_node.is_valid(); dictionary_node.content = dictionary_node.content->next_sibling("dictionary"))
  {
    const std::string dict_name = dictionary_node.attribute_value("name");
    const std::string space_lib_name = dictionary_node.attribute_value("space_lib_name");
    const bool continuous = common::from_str<bool>(dictionary_node.attribute_value("continuous"));
    
    // The entities used by this dictionary
    std::vector< Handle<Entities> > entities_list;
    std::vector<Uint> entities_binary_file_indices;
    common::XML::XmlNode entities_node = dictionary_node.content->first_node("entities");
    for(; entities_node.is_valid(); entities_node.content = entities_node.content->next_sibling("entities"))
    {
      Handle<Entities> entities(mesh.access_component(common::URI(entities_node.attribute_value("path"), common::URI::Scheme::CPATH)));
      if(is_null(entities))
        throw common::FileFormatError(FromHere(), "Referred entities " + entities_node.attribute_value("path") + " doesn't exist in mesh");
      entities_list.push_back(entities);
      entities_binary_file_indices.push_back(common::from_str<Uint>(entities_node.attribute_value("table_idx")));
    }
    
    Dictionary& dictionary = dict_name == "geometry" ? mesh.geometry_fields() :
      (continuous ? mesh.create_continuous_space(dict_name, space_lib_name, entities_list) : mesh.create_discontinuous_space(dict_name, space_lib_name, entities_list));
      
    // Read the global indices
    data_reader->read_list(dictionary.glb_idx(), common::from_str<Uint>(dictionary_node.attribute_value("global_indices")));
    data_reader->read_list(dictionary.rank(), common::from_str<Uint>(dictionary_node.attribute_value("ranks")));
    
    // Read the fields
    common::XML::XmlNode field_node(dictionary_node.content->first_node("field"));
    for(; field_node.is_valid(); field_node.content = field_node.content->next_sibling("field"))
    {
      if(field_node.attribute_value("name") == "coordinates")
        continue;
      const Uint table_idx = common::from_str<Uint>(field_node.attribute_value("table_idx"));
      Field& field = dictionary.create_field(field_node.attribute_value("name"), field_node.attribute_value("description"));
      common::XML::XmlNode tag_node = field_node.content->first_node("tag");
      for(; tag_node.is_valid(); tag_node.content = tag_node.content->next_sibling("tag"))
        field.add_tag(tag_node.attribute_value("name"));
      
      data_reader->read_table(field, table_idx);
    }
    
    // Read in the connectivity tables
    for(Uint i = 0; i != entities_list.size(); ++i)
    {
      data_reader->read_table(entities_list[i]->space(dictionary).connectivity(), entities_binary_file_indices[i]);
    }
  }
}
Beispiel #14
0
  // And Bob has a blonde wife
  s.addObject("blonde", {}, "Bob");

  SECTION("Bob can't have a second wife") {
    // When Bob logs in,
    auto c = TestClient::WithUsernameAndData("Bob", "wives");
    s.waitForUsers(1);

    // And tries to get a readhead wife
    c.sendMessage(CL_CONSTRUCT, makeArgs("redhead", 10, 15));

    // Then Bob receives an error message,
    c.waitForMessage(WARNING_UNIQUE_OBJECT);

    // And there is still only one in the world
    CHECK(s.entities().size() == 1);
  }

  SECTION("Charlie can have a wife too") {
    // When Charlie logs in,
    auto c = TestClient::WithUsernameAndData("Charlie", "wives");
    s.waitForUsers(1);
    auto &user = s.getFirstUser();

    // And tries to get a readhead wife
    c.sendMessage(CL_CONSTRUCT, makeArgs("redhead", 15, 15));
    REPEAT_FOR_MS(100);

    // Then there are now two (one each)
    CHECK(s.entities().size() == 2);
  }
Beispiel #15
0
	Entity doInstantiatePrefab(PrefabResource& prefab_res, const Vec3& pos, const Quat& rot, float scale)
	{
		if (!prefab_res.isReady()) return INVALID_ENTITY;
		if (!m_resources.find(prefab_res.getPath().getHash()).isValid())
		{
			m_resources.insert(prefab_res.getPath().getHash(), &prefab_res);
			prefab_res.getResourceManager().load(prefab_res);
		}
		InputBlob blob(prefab_res.blob.getData(), prefab_res.blob.getPos());
		Array<Entity> entities(m_editor.getAllocator());
		LoadEntityGUIDMap entity_map(entities);
		TextDeserializer deserializer(blob, entity_map);
		u32 version;
		deserializer.read(&version);
		if (version > (int)PrefabVersion::LAST)
		{
			g_log_error.log("Editor") << "Prefab " << prefab_res.getPath() << " has unsupported version.";
			return INVALID_ENTITY;
		}
		int count;
		deserializer.read(&count);
		entities.reserve(count);
		for (int i = 0; i < count; ++i)
		{
			entities.push(m_universe->createEntity({0, 0, 0}, {0, 0, 0, 1}));
		}

		int entity_idx = 0;
		while (blob.getPosition() < blob.getSize() && entity_idx < count)
		{
			u64 prefab;
			deserializer.read(&prefab);
			Entity entity = entities[entity_idx];
			m_universe->setTransform(entity, {pos, rot, scale});
			reserve(entity);
			m_prefabs[entity.index].prefab = prefab;
			link(entity, prefab);
			
			if (version > (int)PrefabVersion::WITH_HIERARCHY)
			{
				Entity parent;
				deserializer.read(&parent);
				if (parent.isValid())
				{
					RigidTransform local_tr;
					deserializer.read(&local_tr);
					float scale;
					deserializer.read(&scale);
					m_universe->setParent(parent, entity);
					m_universe->setLocalTransform(entity, {local_tr.pos, local_tr.rot, scale});
				}
			}
			u32 cmp_type_hash;
			deserializer.read(&cmp_type_hash);
			while (cmp_type_hash != 0)
			{
				ComponentType cmp_type = Reflection::getComponentTypeFromHash(cmp_type_hash);
				int scene_version;
				deserializer.read(&scene_version);
				m_universe->deserializeComponent(deserializer, entity, cmp_type, scene_version);
				deserializer.read(&cmp_type_hash);
			}
			++entity_idx;
		}
		return entities[0];
	}
Beispiel #16
0
bool BulkData::internal_sort_kernel_entities()
{
  bool change = false ;

  for ( unsigned type = 0 ; type < EntityTypeEnd ; ++type ) {
    KernelSet & ks = m_kernels[type] ;

    // bk == first kernel in the family
    KernelSet::iterator bk = ks.begin();

    while ( bk != ks.end() ) {

      KernelSet::iterator ik_vacant = bk->m_kernel ; // Last kernel
      unsigned            ie_vacant = ik_vacant->size();

      if ( ik_vacant->capacity() <= ie_vacant ) {
        // Have to create a kernel just for the scratch space...
        const unsigned * const key = bk->key();
        ik_vacant = declare_kernel( (EntityType) type, key[0]-1 , key+1 );
        ie_vacant = 0 ;
      }

      ik_vacant->m_entities[ ie_vacant ] = NULL ;

      // ek == end kernel for the family
      KernelSet::iterator ek = bk->m_kernel ; ++ek ;

      unsigned count = 0 ;
      for ( KernelSet::iterator ik = bk ; ik != ek ; ++ik ) {
        count += ik->size();
      }

      std::vector<Entity*> entities( count );

      std::vector<Entity*>::iterator j = entities.begin();

      for ( KernelSet::iterator ik = bk ; ik != ek ; ++ik ) {
        const unsigned n = ik->size();
        for ( unsigned i = 0 ; i < n ; ++i , ++j ) {
          *j = ik->m_entities[i] ;
        }
      }

      std::sort( entities.begin() , entities.end() , LessEntityPointer() );

      j = entities.begin();

      bool change_this_family = false ;

      for ( KernelSet::iterator ik = bk ; ik != ek ; ++ik ) {
        const unsigned n = ik->size();
        for ( unsigned i = 0 ; i < n ; ++i , ++j ) {
          Entity * const current = ik->m_entities[i] ;

          if ( current != *j ) {

            if ( current ) {
              // Move current entity to the vacant spot
              Kernel::copy_fields( *ik_vacant , ie_vacant , *ik, i );
              current->m_kernel     = ik_vacant ;
              current->m_kernel_ord = ie_vacant ;
              ik_vacant->m_entities[ ie_vacant ] = current ;
            }

            // Set the vacant spot to where the required entity is now.
            ik_vacant = (*j)->m_kernel ;
            ie_vacant = (*j)->m_kernel_ord ;
            ik_vacant->m_entities[ ie_vacant ] = NULL ;

            // Move required entity to the required spot
            Kernel::copy_fields( *ik, i, *ik_vacant , ie_vacant );
            (*j)->m_kernel     = ik ;
            (*j)->m_kernel_ord = i ;
            ik->m_entities[i] = *j ;

            change_this_family = true ;
          }

          // Once a change has occured then need to propagate the
          // relocation for the remainder of the family.
          // This allows the propagation to be performed once per
          // entity as opposed to both times the entity is moved.

          if ( change_this_family ) { internal_propagate_relocation( **j ); }
        }
      }

      if ( change_this_family ) { change = true ; }

      bk = ek ;
    }
  }

  return change ;
}