Example #1
0
int ETHScriptWrapper::AddEntity(const str_type::string &file, const Vector3 &v3Pos, const float angle, ETHEntity **ppOutEntity,
								const str_type::string &alternativeName, const float scale)
{
	if (WarnIfRunsInMainFunction(GS_L("AddEntity")))
		return -1;

	const str_type::string resourceDirectory = m_provider->GetFileIOHub()->GetResourceDirectory();
	const ETHEntityProperties* props = m_entityCache.Get(file, resourceDirectory + ETHDirectories::GetEntityDirectory(),
														 m_provider->GetFileManager());

	if (!props)
	{
		return -1;
	}

	const float globalScale = m_provider->GetGlobalScaleManager()->GetScale();

	ETHRenderEntity* entity = new ETHRenderEntity(m_provider, *props, angle, scale * globalScale);
	entity->SetOrphanPosition(v3Pos);
	entity->SetAngle(angle);

	if (ppOutEntity)
	{
		entity->AddRef();
		*ppOutEntity = entity;
	}

	return m_pScene->AddEntity(entity, alternativeName);
}
Example #2
0
void ETHScene::FillMultimapAndClearPersistenList(
	const std::list<Vector2>& currentBucketList,
	const ETHBackBufferTargetManagerPtr& backBuffer)
{
	if (m_persistentEntities.empty())
		return;

	for (std::list<ETHRenderEntity*>::iterator iter = m_persistentEntities.begin();
		iter != m_persistentEntities.end(); ++iter)
	{
		ETHRenderEntity* entity = *iter;
		const Vector2& currentBucket = entity->GetCurrentBucket(m_buckets);
		const bool bucketNotProcessed = std::find(currentBucketList.begin(), currentBucketList.end(), currentBucket) == currentBucketList.end();
		if (bucketNotProcessed)
		{
			m_renderingManager.AddDecomposedPieces(
				entity,
				m_minSceneHeight,
				m_maxSceneHeight,
				backBuffer,
				m_sceneProps);

			m_nRenderedEntities++;
		}
		entity->Release();
	}
	m_persistentEntities.clear();
}
Example #3
0
// moves an entity from a bucket to another
bool ETHBucketManager::MoveEntity(const int id, const Vector2 &currentBucket, const Vector2 &destBucket)
{
    // if the destiny bucket is the current bucket, don't need to do anything
    if (currentBucket == destBucket)
        return true;

    // remove the entity from its current bucket
    ETHBucketMap::iterator bucketIter = Find(currentBucket);

    if (bucketIter == GetLastBucket())
    {
        ETH_STREAM_DECL(ss) << GS_L("The current bucket doesn't exist: (") << currentBucket.x << GS_L(",") << currentBucket.y << GS_L(")");
        m_provider->Log(ss.str(), Platform::Logger::ERROR);
        return false;
    }

    ETHRenderEntity* entity = 0;
    ETHEntityList& entityList = bucketIter->second;
    for (ETHEntityList::iterator iter = entityList.begin(); iter != entityList.end(); ++iter)
    {
        if ((*iter)->GetID() == id)
        {
            entity = *iter;
            entityList.erase(iter);
            break;
        }
    }

    // if the entity hasn't been found
    if (!entity)
    {
        ETH_STREAM_DECL(ss) << GS_L("Couldn't find entity ID ") << id << GS_L(" to move");
        m_provider->Log(ss.str(), Platform::Logger::ERROR);
        return false;
    }

    // adds the entity to the destiny bucket
    if (entity->GetType() == ETHEntityProperties::ET_HORIZONTAL)
    {
        m_entities[destBucket].push_front(entity);
    }
    else
    {
        m_entities[destBucket].push_back(entity);
    }

#if defined(_DEBUG) || defined(DEBUG)
    ETH_STREAM_DECL(ss)
            << entity->GetEntityName() << GS_L("(") << entity->GetID() << GS_L(")")
            << GS_L(" moved from bucket (") << currentBucket.x << GS_L(",") << currentBucket.y << GS_L(") to bucket (")
            << destBucket.x << GS_L(",") << destBucket.y << GS_L(")");
    m_provider->Log(ss.str(), Platform::Logger::INFO);
#endif
    return true;
}
void ETHActiveEntityHandler::TestEntityLists() const
{
	for (std::list<ETHRenderEntity*>::const_iterator a = m_dynamicOrTempEntities.begin(); a != m_dynamicOrTempEntities.end(); ++a)
	{
		for (std::list<ETHRenderEntity*>::const_iterator b = m_lastFrameCallbacks.begin(); b != m_lastFrameCallbacks.end(); ++b)
		{
			ETHRenderEntity* entityA = (*a);
			ETHRenderEntity* entityB = (*b);
			const int idA = entityA->GetID();
			const int idB = entityB->GetID();
			bool idAssert;
			idAssert = (idA != idB);
			assert(idAssert);
		}
	}
}
Example #5
0
bool ETHScene::RenderParticleList(std::list<ETHRenderEntity*> &particles)
{
	if (m_provider->GetShaderManager()->BeginParticlePass())
	{
		for (std::list<ETHRenderEntity*>::iterator iter = particles.begin(); iter != particles.end();)
		{
			ETHRenderEntity *pRenderEntity = (*iter);

			if (!m_tempEntities.IsTempEntityEligible(pRenderEntity))
			{
				pRenderEntity->UpdateParticleSystems(GetZAxisDirection());
			}
			for (std::size_t t=0; t<pRenderEntity->GetNumParticleSystems(); t++)
			{
				pRenderEntity->DrawParticles(t, m_maxSceneHeight, m_minSceneHeight, m_sceneProps);
			}
			iter++;
		}
		m_provider->GetShaderManager()->EndParticlePass();
	}
	// seed the random number generator
	Randomizer::Seed(m_provider->GetVideo()->GetElapsedTime());
	return true;
}
void ETHTempEntityHandler::CheckTemporaryEntities(const Vector2& zAxisDir, ETHBucketManager& buckets, const unsigned long lastFrameElapsedTime)
{
	#ifdef _DEBUG
	TestEntityLists();
	#endif

	for (std::list<ETHRenderEntity*>::iterator iter = m_dynamicOrTempEntities.begin(); iter != m_dynamicOrTempEntities.end();)
	{
		ETHRenderEntity* pRenderEntity = *iter;

		pRenderEntity->Update(lastFrameElapsedTime, zAxisDir, buckets);

		// if the particle system is finished, erase it
		if ((pRenderEntity->IsTemporary() && pRenderEntity->AreParticlesOver()))
		{
			const Vector2 v2Bucket = ETHGlobal::GetBucket(pRenderEntity->GetPositionXY(), buckets.GetBucketSize());
			ETHBucketMap::iterator bucketIter = buckets.Find(v2Bucket);

			if (bucketIter == buckets.GetLastBucket())
			{
				iter++;
				continue;
			}

			// Remove from main bucket map
			buckets.DeleteEntity(pRenderEntity->GetID(), v2Bucket, false);

			#ifdef _DEBUG
			ETH_STREAM_DECL(ss) << GS_L("Entity ") << (*iter)->GetEntityName() << GS_L(" (ID#") << pRenderEntity->GetID() << GS_L(") removed from dynamic entity list (particle effects over)");
			m_provider->Log(ss.str(), Platform::Logger::INFO);
			#endif
			(*iter)->Release();
			iter = m_dynamicOrTempEntities.erase(iter);
			continue;
		}
		iter++;
	}
}
int ETHScriptWrapper::AddEntity(const str_type::string &file, const Vector3 &v3Pos, const float angle, ETHEntity **ppOutEntity,
								const str_type::string &alternativeName, const float scale)
{
	if (WarnIfRunsInMainFunction(GS_L("AddEntity")))
		return -1;

	const ETHEntityProperties* props = m_entityCache.Get(file, m_provider->GetResourcePath() + ETHDirectories::GetEntityPath(),
														 m_provider->GetVideo()->GetFileManager());

	if (!props)
	{
		return -1;
	}

	const float globalScale = m_provider->GetGlobalScaleManager()->GetScale();

	ETHRenderEntity* entity = new ETHRenderEntity(m_provider, *props, angle, scale * globalScale);
	entity->SetOrphanPosition(v3Pos);
	entity->SetAngle(angle);

	if (entity->IsStatic() && entity->IsApplyLight())
	{
		str_type::stringstream ss;
		ss << GS_L("AddEntity - This is a static entity and its lightmap has not been rendered yet. ") << 
			  GS_L("It might be incorrectly lit: ") << m_provider->GetResourcePath() << ETHDirectories::GetEntityPath() << file;
		ShowMessage(ss.str(), ETH_WARNING);
	}

	if (ppOutEntity)
	{
		entity->AddRef();
		*ppOutEntity = entity;
	}

	return m_pScene->AddEntity(entity, alternativeName);
}
Example #8
0
void ETHScene::MapEntitiesToBeRendered(
	float &minHeight,
	float &maxHeight,
	const ETHBackBufferTargetManagerPtr& backBuffer)
{
	// store the max and min height to assign when everything is drawn
	maxHeight = m_maxSceneHeight;
	minHeight = m_minSceneHeight;

	m_nRenderedEntities = 0;

	const VideoPtr& video = m_provider->GetVideo();

	// don't let bucket size equal to 0
	assert(GetBucketSize().x != 0 || GetBucketSize().y != 0);

	// Gets the list of visible buckets
	std::list<Vector2> bucketList;
	const Vector2& camPos = video->GetCameraPos(); //for debugging purposes
	m_buckets.GetIntersectingBuckets(bucketList, camPos, backBuffer->GetBufferSize(), IsDrawingBorderBuckets(), IsDrawingBorderBuckets());

	assert(m_activeEntityHandler.IsCallbackListEmpty());

	// Loop through all visible Buckets
	for (std::list<Vector2>::iterator bucketPositionIter = bucketList.begin(); bucketPositionIter != bucketList.end(); ++bucketPositionIter)
	{
		ETHBucketMap::iterator bucketIter = m_buckets.Find(*bucketPositionIter);

		if (bucketIter == m_buckets.GetLastBucket())
			continue;

		ETHEntityList& entityList = bucketIter->second;
		if (entityList.empty())
			continue;

		ETHEntityList::const_iterator iEnd = entityList.end();
		for (ETHEntityList::iterator iter = entityList.begin(); iter != iEnd; ++iter)
		{
			ETHRenderEntity *entity = (*iter);

			// update scene bounding for depth buffer
			maxHeight = Max(maxHeight, entity->GetMaxHeight());
			minHeight = Min(minHeight, entity->GetMinHeight());

			if (entity->IsHidden())
				continue;

			// fill the callback list
			m_activeEntityHandler.AddStaticCallbackWhenEligible(entity);

			m_renderingManager.AddDecomposedPieces(entity, minHeight, maxHeight, backBuffer, m_sceneProps);

			m_nRenderedEntities++;
		}
	}

	// Add persistent entities (the ones the user wants to force to render)
	FillMultimapAndClearPersistenList(bucketList, backBuffer);

	m_nCurrentLights = m_renderingManager.GetNumLights();
}
Example #9
0
bool ETHScene::GenerateLightmaps(const int id)
{
	if (!m_provider->IsRichLightingEnabled())
	{
		return false;
	}

	// save current global scale and temporarily set it to 1
	const ETHGlobalScaleManagerPtr& scaleManager = m_provider->GetGlobalScaleManager();
	const float globalScale = scaleManager->GetScale();
	scaleManager->SetScaleFactor(1.0f);

	const ETHSpriteEntity *pRender = (id >= 0) ? m_buckets.SeekEntity(id) : 0;
	const Vector2 v2Bucket = (pRender) ? ETHBucketManager::GetBucket(pRender->GetPositionXY(), GetBucketSize()) : Vector2(0,0);

	for (ETHBucketMap::iterator bucketIter = m_buckets.GetFirstBucket(); bucketIter != m_buckets.GetLastBucket(); ++bucketIter)
	{
		// if we're lighting only one entity and it is not in this bucket, skip it.
		// I know we could have used the find method to go directly to that bucket
		// but this function os not that critical to make the effort worth it.
		if (id >= 0) 
			if (v2Bucket != bucketIter->first)
				continue;

		// iterate over all entities in this bucket
		ETHEntityList& entityList = bucketIter->second;
		ETHEntityList::const_iterator iEnd = entityList.end();
		for (ETHEntityList::iterator iter = entityList.begin(); iter != iEnd; ++iter)
		{
			ETHRenderEntity* entity = (*iter);
			// if nID is valid, let's try to generate the lightmap for this one and only entity
			if (id >= 0)
				if (id != entity->GetID())
					continue;

			Vector2 v2Size(1,1);
			Vector2 v2AbsoluteOrigin(0,0);
			if (entity->GetSprite())
			{
				v2Size = entity->GetCurrentSize();
				v2AbsoluteOrigin = entity->ComputeAbsoluteOrigin(v2Size);
			}

			// Place the current entity at the top-left corner to align
			// it to the render target
			const Vector3 oldPos = entity->GetPosition();
			const Vector3 newPos = Vector3(v2AbsoluteOrigin.x, v2AbsoluteOrigin.y, 0);

			std::list<ETHLight> lights;

			// fill the light list
			for (ETHBucketMap::iterator lbucketIter = m_buckets.GetFirstBucket(); lbucketIter != m_buckets.GetLastBucket(); ++lbucketIter)
			{
				ETHEntityList& lEntityList = lbucketIter->second;
				ETHEntityList::const_iterator liEnd = lEntityList.end();
				for (ETHEntityList::iterator liter = lEntityList.begin(); liter != liEnd; ++liter)
				{
					ETHRenderEntity* lightEntity = (*liter);
					if (lightEntity->IsStatic() && lightEntity->HasLightSource())
					{
						lights.push_back(
							ETHEntityRenderingManager::BuildChildLight(
								*(lightEntity->GetLight()),
								newPos - oldPos + lightEntity->GetPosition(),
								lightEntity->GetScale()));
					}
				}
			}

			if (lights.size() > 0)
			{
				ETHLightmapGen((*iter), m_provider->GetShaderManager(), lights.begin(), lights.end(),
					m_buckets, oldPos, newPos, m_minSceneHeight, m_maxSceneHeight, m_sceneProps);
			}
			else
			{
				entity->ReleaseLightmap();
			}

			entity->SetOrphanPosition(oldPos);
			lights.clear();
		}
	}
	#if defined(_DEBUG) || defined(DEBUG)
	ETH_STREAM_DECL(ss) << GS_L("Lightmaps created... ");
	m_provider->Log(ss.str(), Platform::FileLogger::INFO);
	#endif

	// go back to the previous global scale
	scaleManager->SetScaleFactor(globalScale);
	return true;
}
Example #10
0
ETHLightmapGen::ETHLightmapGen(
	ETHRenderEntity* entity,
	boost::shared_ptr<ETHShaderManager> shaderManager,
	std::list<ETHLight>::iterator iBegin,
	std::list<ETHLight>::iterator iEnd,
	ETHBucketManager& buckets,
	const Vector3& oldPos,
	const Vector3& newPos,
	const float minHeight,
	const float maxHeight,
	const ETHSceneProperties &sceneProps)
{
	entity->m_pLightmap.reset();
	const SpritePtr& sprite = entity->m_pSprite;
	const ETHEntityProperties& props = entity->m_properties;
	if (!sprite || !props.staticEntity || !props.applyLight)
	{
		return;
	}

	const VideoPtr& video = entity->m_provider->GetVideo();
	const Platform::FileLogger* logger = entity->m_provider->GetLogger();

	if (video->Rendering())
	{
		ETH_STREAM_DECL(ss) << GS_L("Entity ID #") << entity->GetID() << GS_L(": lightmaps can't be generated during application render.");
		logger->Log(ss.str(), Platform::FileLogger::ERROR);
		return;
	}

	const Vector2 v2Size = (sprite->GetNumRects() <= 1) ? sprite->GetBitmapSizeF() : sprite->GetRect().size;
	if (!(entity->m_pLightmap = video->CreateRenderTarget(static_cast<unsigned int>(v2Size.x), static_cast<unsigned int>(v2Size.y))))
	{
		ETH_STREAM_DECL(ss) << GS_L("ETHRenderEntity::GenerateLightmap: coudn't create the render target.");
		logger->Log(ss.str(), Platform::FileLogger::ERROR);
		entity->m_pLightmap.reset();
		return;
	}

	const bool zBuffer = video->GetZBuffer();
	const bool zWrite = video->GetZWrite();

	video->SetZBuffer(false); video->SetZWrite(false);

	// Paint it black
	video->SetRenderTarget(entity->m_pLightmap);
	if (!video->BeginTargetScene(gs2d::constant::BLACK, true))
	{
		ETH_STREAM_DECL(ss) << GS_L("ETHRenderEntity::GenerateLightmap: coudn't render to target.");
		logger->Log(ss.str(), Platform::FileLogger::ERROR);
		entity->m_pLightmap.reset();
		return;
	}
	video->EndTargetScene();

	entity->m_controller->SetPos(newPos / Vector3(entity->GetScale(), 1));
	Vector2 v2CamPos = video->GetCameraPos();
	video->SetCameraPos(Vector2(0,0));

	for (std::list<ETHLight>::iterator iter = iBegin; iter != iEnd; ++iter)
	{
		if (!iter->staticLight)
			continue;

		SpritePtr tempTarget;
		if (!(tempTarget = video->CreateRenderTarget(static_cast<unsigned int>(v2Size.x), static_cast<unsigned int>(v2Size.y))))
		{
			ETH_STREAM_DECL(ss) << GS_L("ETHRenderEntity::GenerateLightmap: coudn't create temporary render target.");
			logger->Log(ss.str(), Platform::FileLogger::ERROR);
			entity->m_pLightmap.reset();
			return;
		}

		if (!video->SetRenderTarget(tempTarget))
		{
			ETH_STREAM_DECL(ss) << GS_L("ETHRenderEntity::GenerateLightmap: coudn't set render target.");
			logger->Log(ss.str(), Platform::FileLogger::ERROR);
			entity->m_pLightmap.reset();
			return;
		}

		if (!video->BeginTargetScene(gs2d::constant::BLACK, true))
		{
			ETH_STREAM_DECL(ss) << GS_L("ETHRenderEntity::GenerateLightmap: coudn't render to temporary target.");
			logger->Log(ss.str(), Platform::FileLogger::ERROR);
			entity->m_pLightmap.reset();
			return;
		}

		// draw light
		const Vector2 tmpScale(entity->GetScale());
		entity->SetScale(Vector2(1, 1));
		iter->pos /= tmpScale.y;
		iter->range /= tmpScale.y;
		if (shaderManager->BeginLightPass(entity, &(*iter), video->GetScreenSizeF().y, 0.0f, sceneProps.lightIntensity, 0, true))
		{
			entity->DrawLightPass(sceneProps.zAxisDirection, 0.0f, true);
			shaderManager->EndLightPass();
		}

		// draw shadows
		if (entity->GetType() != ETHEntityProperties::ET_VERTICAL)
		{
			for (ETHBucketMap::iterator bucketIter = buckets.GetFirstBucket(); bucketIter != buckets.GetLastBucket(); ++bucketIter)
			{
				for (ETHEntityList::iterator entityIter = bucketIter->second.begin();
					entityIter != bucketIter->second.end(); ++entityIter)
				{
					ETHRenderEntity* ent = (*entityIter);
					if (!ent->IsStatic())
						continue;
					Vector3 oldPos2 = ent->GetPosition();
					Vector3 newPos2 = oldPos2-(oldPos-newPos);
					ent->SetOrphanPosition(newPos2 / Vector3(ent->GetScale(), 1));

					const Vector2 tmpScale(ent->GetScale());
					ent->SetScale(Vector2(1, 1));
					if (shaderManager->BeginShadowPass(ent, &(*iter), maxHeight, minHeight))
					{
						ent->DrawShadow(maxHeight, minHeight, sceneProps, *iter, 0, true, true, entity->GetAngle(), entity->GetPosition());
						shaderManager->EndShadowPass();
					}
					ent->SetScale(tmpScale);
					ent->SetOrphanPosition(oldPos2);
				}
			}
		}
		video->EndTargetScene();

		iter->pos *= tmpScale.y;
		iter->range *= tmpScale.y;
		entity->SetScale(tmpScale);

		// draw the shadowed light by adding it to the final lightmap
		video->SetRenderTarget(entity->m_pLightmap);
		video->BeginTargetScene(gs2d::constant::BLACK, false);
		const Video::ALPHA_MODE oldAM = video->GetAlphaMode();
		video->SetAlphaMode(Video::AM_ADD);
		tempTarget->Draw(Vector2(0,0));
		video->SetAlphaMode(oldAM);
		video->EndTargetScene();
	}

	video->SetZBuffer(zBuffer); video->SetZWrite(zWrite);

	entity->m_pLightmap->GenerateBackup();
	video->SetRenderTarget(SpritePtr());
	video->SetCameraPos(v2CamPos);
}
Example #11
0
// TODO-TO-DO: this method is too large...
bool ETHScene::RenderList(float &minHeight, float &maxHeight, SpritePtr pOutline, SpritePtr pInvisibleEntSymbol,
						  std::list<ETHRenderEntity*> &outParticles, std::list<ETHRenderEntity*> &outHalos, const bool roundUp)
{
	// This multimap will store all entities contained in the visible buckets
	// It will automatically sort entities to draw them in an "alpha friendly" order
	std::multimap<float, ETHRenderEntity*> mmEntities;

	// store the max and min height to assign when everything is drawn
	maxHeight = m_maxSceneHeight;
	minHeight = m_minSceneHeight;

	m_nRenderedEntities = 0;

	// don't let bucket size be equal to 0
	assert(GetBucketSize().x != 0 || GetBucketSize().y != 0);

	// Gets the list of visible buckets
	std::list<Vector2> bucketList;
	const Vector2& v2CamPos = m_provider->GetVideo()->GetCameraPos(); //for debugging pourposes
	ETHGlobal::GetIntersectingBuckets(bucketList, v2CamPos,
									m_provider->GetVideo()->GetScreenSizeF(), GetBucketSize(),
									IsDrawingBorderBuckets(), IsDrawingBorderBuckets());

	// Loop through all visible Buckets
	for (std::list<Vector2>::iterator bucketPositionIter = bucketList.begin(); bucketPositionIter != bucketList.end(); bucketPositionIter++)
	{
		ETHBucketMap::iterator bucketIter = m_buckets.Find(*bucketPositionIter);

		if (bucketIter == m_buckets.GetLastBucket())
			continue;

		if (bucketIter->second.empty())
			continue;

		ETHEntityList::const_iterator iEnd = bucketIter->second.end();
		for (ETHEntityList::iterator iter = bucketIter->second.begin(); iter != iEnd; iter++)
		{
			ETHSpriteEntity *pRenderEntity = (*iter);

			// update scene bounding for depth buffer
			maxHeight = Max(maxHeight, pRenderEntity->GetMaxHeight());
			minHeight = Min(minHeight, pRenderEntity->GetMinHeight());

			if (pRenderEntity->IsHidden())
				continue;

			// fill the light list for this frame
			// const ETHEntityFile &entity = pRenderEntity->GetData()->entity;
			if (pRenderEntity->HasLightSource())
			{
				ETHLight light = *(pRenderEntity->GetLight());
				// if it has a particle system in the first slot, adjust the light
				// brightness according to the number os active particles
				if (pRenderEntity->GetParticleManager(0) && !pRenderEntity->IsStatic())
				{
					boost::shared_ptr<ETHParticleManager> paticleManager = pRenderEntity->GetParticleManager(0);
					light.color *= 
						static_cast<float>(paticleManager->GetNumActiveParticles()) /
						static_cast<float>(paticleManager->GetNumParticles());
				}
				AddLight(light, pRenderEntity->GetPosition());
			}

			// add this entity to the multimap to sort it for an alpha-friendly rendering list
			const Vector3& v3Pos = pRenderEntity->GetPosition();
			const ETH_ENTITY_TYPE type = pRenderEntity->GetType();
			const float depth = pRenderEntity->ComputeDepth(maxHeight, minHeight);
			const float drawHash = ComputeDrawHash(depth, v2CamPos, v3Pos, type);

			// add the entity to the render map
			mmEntities.insert(std::pair<float, ETHRenderEntity*>(drawHash, *iter));
			m_nRenderedEntities++;
		}
	}

	// Draw visible entities ordered in an alpha-friendly map
	for (std::multimap<float, ETHRenderEntity*>::iterator iter = mmEntities.begin(); iter != mmEntities.end(); iter++)
	{
		ETHRenderEntity *pRenderEntity = (iter->second);

		m_provider->GetShaderManager()->BeginAmbientPass(pRenderEntity, maxHeight, minHeight);

		// draws the ambient pass and if we're at the editor, draw the collision box if it's an invisible entity
		#ifdef _ETHANON_EDITOR
		if (pOutline && pRenderEntity->IsInvisible() && pRenderEntity->Collidable())
		{
			pRenderEntity->DrawCollisionBox(true, pOutline, GS_WHITE, maxHeight, minHeight, m_sceneProps.zAxisDirection);
		}
		#endif

		m_provider->GetVideo()->RoundUpPosition(roundUp);
		pRenderEntity->DrawAmbientPass(m_maxSceneHeight, m_minSceneHeight, (m_enableLightmaps && m_showingLightmaps), m_sceneProps);

		// draw "invisible entity symbol" if we're in the editor
		#ifdef _ETHANON_EDITOR
		if (pOutline)
		{
			if (pRenderEntity->IsInvisible() && pRenderEntity->Collidable())
			{
				pRenderEntity->DrawCollisionBox(false, pOutline, GS_WHITE, maxHeight, minHeight, m_sceneProps.zAxisDirection);
			}
			if (pRenderEntity->IsInvisible() && !pRenderEntity->Collidable())
			{
				const float depth = m_provider->GetVideo()->GetSpriteDepth();
				m_provider->GetVideo()->SetSpriteDepth(1.0f);
				pInvisibleEntSymbol->Draw(pRenderEntity->GetPositionXY());
				m_provider->GetVideo()->SetSpriteDepth(depth);
			}
		}
		#endif

		// fill the halo list
		// const ETHEntityFile &entity = pRenderEntity->GetData()->entity;
		if (pRenderEntity->HasLightSource() && pRenderEntity->GetHalo())
		{
			outHalos.push_back(pRenderEntity);
		}

		// fill the particle list for this frame
		if (pRenderEntity->HasParticleSystems())
		{
			outParticles.push_back(pRenderEntity);
		}

		// fill the callback list
		m_tempEntities.AddCallbackWhenEligible(pRenderEntity);

		m_provider->GetShaderManager()->EndAmbientPass();

		//draw light pass
		for (std::list<ETHLight>::iterator iter = m_lights.begin(); iter != m_lights.end(); iter++)
		{
			if (!pRenderEntity->IsHidden())
			{
				if (!(pRenderEntity->IsStatic() && iter->staticLight && m_enableLightmaps))
				{
					m_provider->GetVideo()->RoundUpPosition(roundUp);
					if (m_provider->GetShaderManager()->BeginLightPass(pRenderEntity, &(*iter), m_maxSceneHeight, m_minSceneHeight, GetLightIntensity()))
					{
						pRenderEntity->DrawLightPass(GetZAxisDirection());
						m_provider->GetShaderManager()->EndLightPass();

						m_provider->GetVideo()->RoundUpPosition(false);
						if (AreRealTimeShadowsEnabled())
						{
							if (m_provider->GetShaderManager()->BeginShadowPass(pRenderEntity, &(*iter), m_maxSceneHeight, m_minSceneHeight))
							{
								pRenderEntity->DrawShadow(m_maxSceneHeight, m_minSceneHeight, m_sceneProps, *iter, 0);
								m_provider->GetShaderManager()->EndShadowPass();
							}
						}
						m_provider->GetVideo()->RoundUpPosition(roundUp);
					}
				}
			}
		}
	}

	mmEntities.clear();
	m_nCurrentLights = m_lights.size();

	// Show the buckets outline in debug mode
	#if defined _DEBUG || defined _ETHANON_EDITOR
	if (m_provider->GetInput()->IsKeyDown(GSK_PAUSE))
	{
		DrawBucketOutlines();
	}
	#endif

	return true;
}
void ETHActiveEntityHandler::UpdateActiveEntities(const Vector2& zAxisDir, ETHBucketManager& buckets, const unsigned long lastFrameElapsedTime)
{
	#if defined(_DEBUG) || defined(DEBUG)
	TestEntityLists();
	#endif

	for (std::list<ETHRenderEntity*>::iterator iter = m_dynamicOrTempEntities.begin(); iter != m_dynamicOrTempEntities.end();)
	{
		ETHRenderEntity* entity = (*iter);

		if (!(entity->IsAlive()) || RemoveFinishedTemporaryEntity(entity, buckets))
		{
			#if defined(_DEBUG) || defined(DEBUG)
			 ETH_STREAM_DECL(ss) << GS_L("Entity removed from dynamic entity list: ") << entity->GetEntityName();
			 m_provider->Log(ss.str(), Platform::Logger::INFO);
			#endif
			entity->Release();
			iter = m_dynamicOrTempEntities.erase(iter);
			continue;
		}

		entity->Update(lastFrameElapsedTime, zAxisDir, buckets);

		if (entity->HasAnyCallbackFunction())
		{
			entity->RunCallbackScript();
		}

		++iter;
	}

	// todo/to-do remove duplicate code
	for (std::list<ETHRenderEntity*>::iterator iter = m_lastFrameCallbacks.begin(); iter != m_lastFrameCallbacks.end();)
	{
		ETHRenderEntity* entity = (*iter);

		if (!(entity->IsAlive()))
		{
			#if defined(_DEBUG) || defined(DEBUG)
			 ETH_STREAM_DECL(ss) << GS_L("Entity callback removed: ") << entity->GetEntityName();
			 m_provider->Log(ss.str(), Platform::Logger::INFO);
			#endif
			entity->Release();
			iter = m_lastFrameCallbacks.erase(iter);
			continue;
		}
		else
		{
			entity->Update(lastFrameElapsedTime, zAxisDir, buckets);

			if (entity->HasAnyCallbackFunction())
			{
				entity->RunCallbackScript();
			}

			entity->Release();

			++iter;
		}
	}
	m_lastFrameCallbacks.clear();
}