Browse Source

Some refactoring and optimizations in the scenegraph

Panagiotis Christopoulos Charitos 5 years ago
parent
commit
5b3567de87

+ 2 - 2
anki/scene/BodyNode.cpp

@@ -27,11 +27,11 @@ public:
 	{
 		updated = false;
 
-		BodyComponent& bodyc = node.getComponent<BodyComponent>();
+		BodyComponent& bodyc = node.getFirstComponentOfType<BodyComponent>();
 
 		if(bodyc.getTimestamp() == node.getGlobalTimestamp())
 		{
-			MoveComponent& move = node.getComponent<MoveComponent>();
+			MoveComponent& move = node.getFirstComponentOfType<MoveComponent>();
 			move.setLocalTransform(bodyc.getTransform());
 		}
 

+ 37 - 6
anki/scene/CameraNode.cpp

@@ -25,7 +25,7 @@ public:
 	{
 		updated = false;
 
-		MoveComponent& move = node.getComponent<MoveComponent>();
+		MoveComponent& move = node.getFirstComponentOfType<MoveComponent>();
 		if(move.getTimestamp() == node.getGlobalTimestamp())
 		{
 			CameraNode& cam = static_cast<CameraNode&>(node);
@@ -49,7 +49,7 @@ public:
 	{
 		updated = false;
 
-		FrustumComponent& fr = node.getComponent<FrustumComponent>();
+		FrustumComponent& fr = node.getFirstComponentOfType<FrustumComponent>();
 		if(fr.getTimestamp() == node.getGlobalTimestamp())
 		{
 			CameraNode& cam = static_cast<CameraNode&>(node);
@@ -71,6 +71,8 @@ CameraNode::~CameraNode()
 
 Error CameraNode::init(FrustumType frustumType)
 {
+	constexpr F32 defaultFar = 500.0f;
+
 	// Move component
 	newComponent<MoveComponent>();
 
@@ -89,12 +91,22 @@ Error CameraNode::init(FrustumType frustumType)
 		| FrustumComponentVisibilityTestFlag::ALL_SHADOWS_ENABLED
 		| FrustumComponentVisibilityTestFlag::GENERIC_COMPUTE_JOB_COMPONENTS;
 	frc->setEnabledVisibilityTests(visibilityFlags);
+	if(frustumType == FrustumType::PERSPECTIVE)
+	{
+		frc->setPerspective(0.1f, defaultFar, toRad(45.0f), toRad(45.0f));
+	}
+	else
+	{
+		frc->setOrthographic(0.1f, defaultFar, 5.0f, -5.0f, 5.0f, -5.0f);
+	}
 
-	// One more component for RT
+	// Extended frustum for RT
 	if(getSceneGraph().getRayTracedShadowsEnabled())
 	{
 		FrustumComponent* rtFrustumComponent = newComponent<FrustumComponent>(this, FrustumType::ORTHOGRAPHIC);
 		rtFrustumComponent->setEnabledVisibilityTests(FrustumComponentVisibilityTestFlag::RAY_TRACING_SHADOWS);
+
+		rtFrustumComponent->setOrthographic(0.1f, defaultFar * 2.0f, defaultFar, -defaultFar, defaultFar, -defaultFar);
 	}
 
 	// Feedback component #2
@@ -119,21 +131,40 @@ Error CameraNode::init(FrustumType frustumType)
 void CameraNode::onFrustumComponentUpdate(FrustumComponent& fr)
 {
 	// Spatial
-	SpatialComponent& sp = getComponent<SpatialComponent>();
+	SpatialComponent& sp = getFirstComponentOfType<SpatialComponent>();
 	sp.markForUpdate();
 }
 
 void CameraNode::onMoveComponentUpdate(MoveComponent& move)
 {
+	const Transform& worldTransform = move.getWorldTransform();
+
 	// Frustum
+	U count = 0;
 	const Error err = iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& fc) {
-		fc.setTransform(move.getWorldTransform());
+		if(count == 0)
+		{
+			fc.setTransform(worldTransform);
+		}
+		else
+		{
+			// Extended RT frustum, re-align it so the frustum is positioned at the center of the camera eye
+			ANKI_ASSERT(fc.getFrustumType() == FrustumType::ORTHOGRAPHIC);
+			const F32 far = fc.getFar();
+			Transform extendedFrustumTransform = Transform::getIdentity();
+			Vec3 newOrigin = worldTransform.getOrigin().xyz();
+			newOrigin.z() += far / 2.0f;
+			extendedFrustumTransform.setOrigin(newOrigin.xyz0());
+		}
+
+		++count;
 		return Error::NONE;
 	});
 	(void)err;
+	ANKI_ASSERT(count == 2);
 
 	// Spatial
-	SpatialComponent& sp = getComponent<SpatialComponent>();
+	SpatialComponent& sp = getFirstComponentOfType<SpatialComponent>();
 	sp.setSpatialOrigin(move.getWorldTransform().getOrigin());
 	sp.markForUpdate();
 }

+ 6 - 6
anki/scene/DecalNode.cpp

@@ -25,7 +25,7 @@ public:
 	{
 		updated = false;
 
-		MoveComponent& movec = node.getComponent<MoveComponent>();
+		MoveComponent& movec = node.getFirstComponentOfType<MoveComponent>();
 
 		if(movec.getTimestamp() == node.getGlobalTimestamp())
 		{
@@ -49,7 +49,7 @@ public:
 	{
 		updated = false;
 
-		DecalComponent& decalc = node.getComponent<DecalComponent>();
+		DecalComponent& decalc = node.getFirstComponentOfType<DecalComponent>();
 
 		if(decalc.getTimestamp() == node.getGlobalTimestamp())
 		{
@@ -81,17 +81,17 @@ Error DecalNode::init()
 
 void DecalNode::onMove(MoveComponent& movec)
 {
-	SpatialComponent& sc = getComponent<SpatialComponent>();
+	SpatialComponent& sc = getFirstComponentOfType<SpatialComponent>();
 	sc.setSpatialOrigin(movec.getWorldTransform().getOrigin());
 	sc.markForUpdate();
 
-	DecalComponent& decalc = getComponent<DecalComponent>();
+	DecalComponent& decalc = getFirstComponentOfType<DecalComponent>();
 	decalc.updateTransform(movec.getWorldTransform());
 }
 
 void DecalNode::onDecalUpdated()
 {
-	SpatialComponent& sc = getComponent<SpatialComponent>();
+	SpatialComponent& sc = getFirstComponentOfType<SpatialComponent>();
 	sc.markForUpdate();
 }
 
@@ -102,7 +102,7 @@ void DecalNode::drawCallback(RenderQueueDrawContext& ctx, ConstWeakArray<void*>
 	for(U32 i = 0; i < userData.getSize(); ++i)
 	{
 		const DecalNode& self = *static_cast<const DecalNode*>(userData[i]);
-		const DecalComponent& decalComp = self.getComponent<DecalComponent>();
+		const DecalComponent& decalComp = self.getFirstComponentOfType<DecalComponent>();
 
 		const Mat3 rot = decalComp.getBoundingVolume().getRotation().getRotationPart();
 		const Vec4 tsl = decalComp.getBoundingVolume().getCenter().xyz1();

+ 4 - 4
anki/scene/FogDensityNode.cpp

@@ -23,7 +23,7 @@ public:
 	{
 		updated = false;
 
-		const MoveComponent& movec = node.getComponent<MoveComponent>();
+		const MoveComponent& movec = node.getFirstComponentOfType<MoveComponent>();
 		if(movec.getTimestamp() == node.getGlobalTimestamp())
 		{
 			static_cast<FogDensityNode&>(node).moveUpdated(movec);
@@ -50,11 +50,11 @@ FogDensityNode::~FogDensityNode()
 void FogDensityNode::moveUpdated(const MoveComponent& movec)
 {
 	// Update the fog component
-	FogDensityComponent& fogc = getComponent<FogDensityComponent>();
+	FogDensityComponent& fogc = getFirstComponentOfType<FogDensityComponent>();
 	fogc.updatePosition(movec.getWorldTransform().getOrigin());
 
 	// Update the spatial component
-	SpatialComponent& spatialc = getComponent<SpatialComponent>();
+	SpatialComponent& spatialc = getFirstComponentOfType<SpatialComponent>();
 
 	Vec4 min, max;
 	if(fogc.isAabb())
@@ -80,4 +80,4 @@ void FogDensityNode::moveUpdated(const MoveComponent& movec)
 	spatialc.markForUpdate();
 }
 
-} // end namespace anki
+} // end namespace anki

+ 8 - 7
anki/scene/GlobalIlluminationProbeNode.cpp

@@ -32,7 +32,7 @@ public:
 	{
 		updated = false;
 
-		MoveComponent& move = node.getComponent<MoveComponent>();
+		MoveComponent& move = node.getFirstComponentOfType<MoveComponent>();
 		if(move.getTimestamp() == node.getGlobalTimestamp())
 		{
 			// Move updated
@@ -57,7 +57,7 @@ public:
 	{
 		updated = false;
 
-		GlobalIlluminationProbeComponent& probec = node.getComponent<GlobalIlluminationProbeComponent>();
+		GlobalIlluminationProbeComponent& probec = node.getFirstComponentOfType<GlobalIlluminationProbeComponent>();
 		if(probec.getTimestamp() == node.getGlobalTimestamp() || probec.getMarkedForRendering())
 		{
 			// Move updated
@@ -139,13 +139,13 @@ void GlobalIlluminationProbeNode::onMoveUpdate(MoveComponent& move)
 	const Vec4 displacement = move.getWorldTransform().getOrigin() - m_previousPosition;
 	m_previousPosition = move.getWorldTransform().getOrigin();
 
-	GlobalIlluminationProbeComponent& gic = getComponent<GlobalIlluminationProbeComponent>();
+	GlobalIlluminationProbeComponent& gic = getFirstComponentOfType<GlobalIlluminationProbeComponent>();
 	gic.setBoundingBox(gic.getAlignedBoundingBoxMin() + displacement, gic.getAlignedBoundingBoxMax() + displacement);
 }
 
 void GlobalIlluminationProbeNode::onShapeUpdateOrProbeNeedsRendering()
 {
-	GlobalIlluminationProbeComponent& gic = getComponent<GlobalIlluminationProbeComponent>();
+	GlobalIlluminationProbeComponent& gic = getFirstComponentOfType<GlobalIlluminationProbeComponent>();
 
 	// Update the frustum component if the shape needs rendering
 	if(gic.getMarkedForRendering())
@@ -181,7 +181,7 @@ void GlobalIlluminationProbeNode::onShapeUpdateOrProbeNeedsRendering()
 	{
 		// Update only when the shape was actually update
 
-		SpatialComponent& sp = getComponent<SpatialComponent>();
+		SpatialComponent& sp = getFirstComponentOfType<SpatialComponent>();
 		sp.markForUpdate();
 		sp.setSpatialOrigin((m_spatialAabb.getMax() + m_spatialAabb.getMin()) / 2.0f);
 		m_spatialAabb.setMin(gic.getAlignedBoundingBoxMin());
@@ -192,7 +192,7 @@ void GlobalIlluminationProbeNode::onShapeUpdateOrProbeNeedsRendering()
 Error GlobalIlluminationProbeNode::frameUpdate(Second prevUpdateTime, Second crntTime)
 {
 	// Check the reflection probe component and if it's marked for rendering enable the frustum components
-	const GlobalIlluminationProbeComponent& gic = getComponent<GlobalIlluminationProbeComponent>();
+	const GlobalIlluminationProbeComponent& gic = getFirstComponentOfType<GlobalIlluminationProbeComponent>();
 
 	const FrustumComponentVisibilityTestFlag testFlags =
 		gic.getMarkedForRendering() ? FRUSTUM_TEST_FLAGS : FrustumComponentVisibilityTestFlag::NONE;
@@ -213,7 +213,8 @@ void GlobalIlluminationProbeNode::debugDrawCallback(RenderQueueDrawContext& ctx,
 	for(U32 i = 0; i < userData.getSize(); ++i)
 	{
 		const GlobalIlluminationProbeNode& self = *static_cast<const GlobalIlluminationProbeNode*>(userData[i]);
-		const GlobalIlluminationProbeComponent& giComp = self.getComponent<GlobalIlluminationProbeComponent>();
+		const GlobalIlluminationProbeComponent& giComp =
+			self.getFirstComponentOfType<GlobalIlluminationProbeComponent>();
 
 		const Vec3 tsl = (giComp.getAlignedBoundingBoxMin().xyz() + giComp.getAlignedBoundingBoxMax().xyz()) / 2.0f;
 		const Vec3 scale = (tsl - giComp.getAlignedBoundingBoxMin().xyz());

+ 3 - 3
anki/scene/GpuParticleEmitterNode.cpp

@@ -27,7 +27,7 @@ public:
 	{
 		updated = false;
 
-		const MoveComponent& move = node.getComponent<MoveComponent>();
+		const MoveComponent& move = node.getFirstComponentOfType<MoveComponent>();
 		if(move.getTimestamp() == node.getGlobalTimestamp())
 		{
 			GpuParticleEmitterNode& mnode = static_cast<GpuParticleEmitterNode&>(node);
@@ -168,7 +168,7 @@ void GpuParticleEmitterNode::onMoveComponentUpdate(const MoveComponent& movec)
 	// Update the AABB
 	m_spatialVolume.setMin((pos - m_maxDistanceAParticleCanGo).xyz());
 	m_spatialVolume.setMax((pos + m_maxDistanceAParticleCanGo).xyz());
-	SpatialComponent& spatialc = getComponent<SpatialComponent>();
+	SpatialComponent& spatialc = getFirstComponentOfType<SpatialComponent>();
 	spatialc.markForUpdate();
 	spatialc.setSpatialOrigin(pos);
 
@@ -221,7 +221,7 @@ void GpuParticleEmitterNode::draw(RenderQueueDrawContext& ctx) const
 
 		// Resources
 		static const Mat4 identity = Mat4::getIdentity();
-		static_cast<const MaterialRenderComponent&>(getComponent<RenderComponent>())
+		static_cast<const MaterialRenderComponent&>(getFirstComponentOfType<RenderComponent>())
 			.allocateAndSetupUniforms(ctx, ConstWeakArray<Mat4>(&identity, 1), ConstWeakArray<Mat4>(&identity, 1),
 									  *ctx.m_stagingGpuAllocator);
 

+ 13 - 13
anki/scene/LightNode.cpp

@@ -52,7 +52,7 @@ public:
 	{
 		updated = false;
 
-		LightComponent& light = node.getComponent<LightComponent>();
+		LightComponent& light = node.getFirstComponentOfType<LightComponent>();
 		if(light.getTimestamp() == node.getGlobalTimestamp())
 		{
 			// Shape updated
@@ -94,7 +94,7 @@ Error LightNode::initCommon(LightComponentType lightType)
 void LightNode::frameUpdateCommon()
 {
 	// Update frustum comps shadow info
-	const LightComponent& lc = getComponent<LightComponent>();
+	const LightComponent& lc = getFirstComponentOfType<LightComponent>();
 	const Bool castsShadow = lc.getShadowEnabled();
 
 	const Error err = iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& frc) -> Error {
@@ -115,24 +115,24 @@ void LightNode::frameUpdateCommon()
 void LightNode::onMoveUpdateCommon(const MoveComponent& move)
 {
 	// Update the spatial
-	SpatialComponent& sp = getComponent<SpatialComponent>();
+	SpatialComponent& sp = getFirstComponentOfType<SpatialComponent>();
 	sp.markForUpdate();
 	sp.setSpatialOrigin(move.getWorldTransform().getOrigin());
 
 	// Update the lens flare
-	LensFlareComponent* lf = tryGetComponent<LensFlareComponent>();
+	LensFlareComponent* lf = tryGetFirstComponentOfType<LensFlareComponent>();
 	if(lf)
 	{
 		lf->setWorldPosition(move.getWorldTransform().getOrigin());
 	}
 
 	// Update light component
-	getComponent<LightComponent>().updateWorldTransform(move.getWorldTransform());
+	getFirstComponentOfType<LightComponent>().updateWorldTransform(move.getWorldTransform());
 }
 
 Error LightNode::loadLensFlare(const CString& filename)
 {
-	ANKI_ASSERT(tryGetComponent<LensFlareComponent>() == nullptr);
+	ANKI_ASSERT(tryGetFirstComponentOfType<LensFlareComponent>() == nullptr);
 
 	LensFlareComponent* flareComp = newComponent<LensFlareComponent>(this);
 
@@ -151,7 +151,7 @@ void LightNode::drawCallback(RenderQueueDrawContext& ctx, ConstWeakArray<void*>
 	for(const void* plight : userData)
 	{
 		const LightNode& self = *static_cast<const LightNode*>(plight);
-		const LightComponent& lcomp = self.getComponent<LightComponent>();
+		const LightComponent& lcomp = self.getFirstComponentOfType<LightComponent>();
 
 		const Bool enableDepthTest = ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DEPTH_TEST_ON);
 		if(enableDepthTest)
@@ -247,7 +247,7 @@ void PointLightNode::onShapeUpdate(LightComponent& light)
 
 Error PointLightNode::frameUpdate(Second prevUpdateTime, Second crntTime)
 {
-	if(getComponent<LightComponent>().getShadowEnabled() && m_shadowData.isEmpty())
+	if(getFirstComponentOfType<LightComponent>().getShadowEnabled() && m_shadowData.isEmpty())
 	{
 		m_shadowData.create(getAllocator(), 6);
 
@@ -270,7 +270,7 @@ Error PointLightNode::frameUpdate(Second prevUpdateTime, Second crntTime)
 		rot = Mat3(Euler(0.0, 0.0, PI));
 		m_shadowData[5].m_localTrf.setRotation(Mat3x4(Vec3(0.0f), rot));
 
-		const Vec4& origin = getComponent<MoveComponent>().getWorldTransform().getOrigin();
+		const Vec4& origin = getFirstComponentOfType<MoveComponent>().getWorldTransform().getOrigin();
 		for(U32 i = 0; i < 6; i++)
 		{
 			Transform trf = m_shadowData[i].m_localTrf;
@@ -335,11 +335,11 @@ void SpotLightNode::onMoveUpdate(const MoveComponent& move)
 void SpotLightNode::onShapeUpdate(LightComponent& light)
 {
 	// Update the frustum first
-	FrustumComponent& frc = getComponent<FrustumComponent>();
+	FrustumComponent& frc = getFirstComponentOfType<FrustumComponent>();
 	frc.setPerspective(LIGHT_FRUSTUM_NEAR_PLANE, light.getDistance(), light.getOuterAngle(), light.getOuterAngle());
 
 	// Mark the spatial for update
-	SpatialComponent& sp = getComponent<SpatialComponent>();
+	SpatialComponent& sp = getFirstComponentOfType<SpatialComponent>();
 	sp.markForUpdate();
 }
 
@@ -363,10 +363,10 @@ public:
 		if(move.getTimestamp() == node.getGlobalTimestamp())
 		{
 			// Move updated
-			LightComponent& lightc = node.getComponent<LightComponent>();
+			LightComponent& lightc = node.getFirstComponentOfType<LightComponent>();
 			lightc.updateWorldTransform(move.getWorldTransform());
 
-			SpatialComponent& spatialc = node.getComponent<SpatialComponent>();
+			SpatialComponent& spatialc = node.getFirstComponentOfType<SpatialComponent>();
 			spatialc.setSpatialOrigin(move.getWorldTransform().getOrigin());
 			spatialc.markForUpdate();
 		}

+ 9 - 8
anki/scene/ModelNode.cpp

@@ -30,8 +30,8 @@ public:
 	{
 		updated = false;
 
-		const MoveComponent& move = node.getComponent<MoveComponent>();
-		const SkinComponent* skin = node.tryGetComponent<SkinComponent>();
+		const MoveComponent& move = node.getFirstComponentOfType<MoveComponent>();
+		const SkinComponent* skin = node.tryGetFirstComponentOfType<SkinComponent>();
 		if(move.getTimestamp() == node.getGlobalTimestamp()
 		   || (skin && skin->getTimestamp() == node.getGlobalTimestamp()))
 		{
@@ -56,7 +56,7 @@ public:
 	{
 		updated = false;
 
-		const SkinComponent& skin = node.getComponent<SkinComponent>();
+		const SkinComponent& skin = node.getFirstComponentOfType<SkinComponent>();
 		if(skin.getTimestamp() == node.getGlobalTimestamp())
 		{
 			ModelNode& mnode = static_cast<ModelNode&>(node);
@@ -141,7 +141,7 @@ void ModelNode::updateSpatialComponent(const MoveComponent& move)
 {
 	m_obbWorld = m_obbLocal.getTransformed(move.getWorldTransform());
 
-	SpatialComponent& sp = getComponent<SpatialComponent>();
+	SpatialComponent& sp = getFirstComponentOfType<SpatialComponent>();
 	sp.markForUpdate();
 	sp.setSpatialOrigin(move.getWorldTransform().getOrigin());
 }
@@ -164,14 +164,14 @@ void ModelNode::draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData
 		// Transforms
 		Array<Mat4, MAX_INSTANCES> trfs;
 		Array<Mat4, MAX_INSTANCES> prevTrfs;
-		const MoveComponent& movec = getComponent<MoveComponent>();
+		const MoveComponent& movec = getFirstComponentOfType<MoveComponent>();
 		trfs[0] = Mat4(movec.getWorldTransform());
 		prevTrfs[0] = Mat4(movec.getPreviousWorldTransform());
 		Bool moved = trfs[0] != prevTrfs[0];
 		for(U32 i = 1; i < userData.getSize(); ++i)
 		{
 			const ModelNode& self2 = *static_cast<const ModelNode*>(userData[i]);
-			const MoveComponent& movec = self2.getComponent<MoveComponent>();
+			const MoveComponent& movec = self2.getFirstComponentOfType<MoveComponent>();
 			trfs[i] = Mat4(movec.getWorldTransform());
 			prevTrfs[i] = Mat4(movec.getPreviousWorldTransform());
 
@@ -210,7 +210,7 @@ void ModelNode::draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData
 		cmdb->bindShaderProgram(modelInf.m_program);
 
 		// Uniforms
-		static_cast<const MaterialRenderComponent&>(getComponent<RenderComponent>())
+		static_cast<const MaterialRenderComponent&>(getFirstComponentOfType<RenderComponent>())
 			.allocateAndSetupUniforms(ctx, ConstWeakArray<Mat4>(&trfs[0], userData.getSize()),
 									  ConstWeakArray<Mat4>(&prevTrfs[0], userData.getSize()),
 									  *ctx.m_stagingGpuAllocator);
@@ -314,7 +314,8 @@ void ModelNode::draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData
 				}
 			}
 
-			const Mat4 mvp = ctx.m_viewProjectionMatrix * Mat4(getComponent<MoveComponent>().getWorldTransform());
+			const Mat4 mvp =
+				ctx.m_viewProjectionMatrix * Mat4(getFirstComponentOfType<MoveComponent>().getWorldTransform());
 			m_dbgDrawer.drawLines(ConstWeakArray<Mat4>(&mvp, 1), Vec4(1.0f), 20.0f,
 								  ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DITHERED_DEPTH_TEST_ON), lines,
 								  *ctx.m_stagingGpuAllocator, cmdb);

+ 2 - 2
anki/scene/OccluderNode.cpp

@@ -25,7 +25,7 @@ public:
 	{
 		updated = false;
 
-		MoveComponent& move = node.getComponent<MoveComponent>();
+		MoveComponent& move = node.getFirstComponentOfType<MoveComponent>();
 		if(move.getTimestamp() == node.getGlobalTimestamp())
 		{
 			OccluderNode& mnode = static_cast<OccluderNode&>(node);
@@ -79,7 +79,7 @@ void OccluderNode::onMoveComponentUpdate(MoveComponent& movec)
 		m_vertsW[count] = trf.transform(m_vertsL[count]);
 	}
 
-	getComponent<OccluderComponent>().setVertices(&m_vertsW[0], m_vertsW.getSize(), sizeof(m_vertsW[0]));
+	getFirstComponentOfType<OccluderComponent>().setVertices(&m_vertsW[0], m_vertsW.getSize(), sizeof(m_vertsW[0]));
 }
 
 } // end namespace anki

+ 5 - 5
anki/scene/ParticleEmitterNode.cpp

@@ -212,7 +212,7 @@ public:
 	{
 		updated = false; // Don't care about updates for this component
 
-		MoveComponent& move = node.getComponent<MoveComponent>();
+		MoveComponent& move = node.getFirstComponentOfType<MoveComponent>();
 		if(move.getTimestamp() == node.getGlobalTimestamp())
 		{
 			static_cast<ParticleEmitterNode&>(node).onMoveComponentUpdate(move);
@@ -321,7 +321,7 @@ void ParticleEmitterNode::drawCallback(RenderQueueDrawContext& ctx, ConstWeakArr
 
 		// Uniforms
 		Array<Mat4, 1> trf = {Mat4::getIdentity()};
-		static_cast<const MaterialRenderComponent&>(self.getComponent<RenderComponent>())
+		static_cast<const MaterialRenderComponent&>(self.getFirstComponentOfType<RenderComponent>())
 			.allocateAndSetupUniforms(ctx, trf, trf, *ctx.m_stagingGpuAllocator);
 
 		// Draw
@@ -337,7 +337,7 @@ void ParticleEmitterNode::onMoveComponentUpdate(MoveComponent& move)
 {
 	m_identityRotation = move.getWorldTransform().getRotation() == Mat3x4::getIdentity();
 
-	SpatialComponent& sp = getComponent<SpatialComponent>();
+	SpatialComponent& sp = getFirstComponentOfType<SpatialComponent>();
 	sp.setSpatialOrigin(move.getWorldTransform().getOrigin());
 	sp.markForUpdate();
 }
@@ -449,14 +449,14 @@ Error ParticleEmitterNode::frameUpdate(Second prevUpdateTime, Second crntTime)
 		m_verts = nullptr;
 	}
 
-	getComponent<SpatialComponent>().markForUpdate();
+	getFirstComponentOfType<SpatialComponent>().markForUpdate();
 
 	//
 	// Emit new particles
 	//
 	if(m_timeLeftForNextEmission <= 0.0)
 	{
-		MoveComponent& move = getComponent<MoveComponent>();
+		MoveComponent& move = getFirstComponentOfType<MoveComponent>();
 
 		U particlesCount = 0; // How many particles I am allowed to emmit
 		for(ParticleBase* pp : m_particles)

+ 4 - 4
anki/scene/PlayerNode.cpp

@@ -27,7 +27,7 @@ public:
 	{
 		updated = false;
 
-		PlayerControllerComponent& playerc = node.getComponent<PlayerControllerComponent>();
+		PlayerControllerComponent& playerc = node.getFirstComponentOfType<PlayerControllerComponent>();
 		const Input& in = node.getSceneGraph().getInput();
 		const F32 ang = toRad(7.0f);
 
@@ -35,7 +35,7 @@ public:
 		F32 x = in.getMousePosition().x();
 		if(playerc.getTimestamp() == node.getGlobalTimestamp() || y != 0.0 || x != 0.0)
 		{
-			MoveComponent& move = node.getComponent<MoveComponent>();
+			MoveComponent& move = node.getFirstComponentOfType<MoveComponent>();
 
 			// Set origin
 			Vec4 origin = playerc.getTransform().getOrigin();
@@ -73,8 +73,8 @@ public:
 	{
 		updated = false;
 
-		PlayerControllerComponent& playerc = node.getComponent<PlayerControllerComponent>();
-		MoveComponent& move = node.getComponent<MoveComponent>();
+		PlayerControllerComponent& playerc = node.getFirstComponentOfType<PlayerControllerComponent>();
+		MoveComponent& move = node.getFirstComponentOfType<MoveComponent>();
 		const Input& in = node.getSceneGraph().getInput();
 
 		const F32 speed = 0.5;

+ 5 - 5
anki/scene/ReflectionProbeNode.cpp

@@ -33,7 +33,7 @@ public:
 	{
 		updated = false;
 
-		MoveComponent& move = node.getComponent<MoveComponent>();
+		MoveComponent& move = node.getFirstComponentOfType<MoveComponent>();
 		if(move.getTimestamp() == node.getGlobalTimestamp())
 		{
 			// Move updated
@@ -133,7 +133,7 @@ void ReflectionProbeNode::onMoveUpdate(MoveComponent& move)
 	(void)err;
 
 	// Update the spatial comp
-	SpatialComponent& sp = getComponent<SpatialComponent>();
+	SpatialComponent& sp = getFirstComponentOfType<SpatialComponent>();
 	sp.markForUpdate();
 	sp.setSpatialOrigin(move.getWorldTransform().getOrigin());
 	const Vec3 aabbMinWSpace = m_aabbMinLSpace + move.getWorldTransform().getOrigin().xyz();
@@ -142,7 +142,7 @@ void ReflectionProbeNode::onMoveUpdate(MoveComponent& move)
 	m_spatialAabb.setMax(aabbMaxWSpace);
 
 	// Update the refl comp
-	ReflectionProbeComponent& reflc = getComponent<ReflectionProbeComponent>();
+	ReflectionProbeComponent& reflc = getFirstComponentOfType<ReflectionProbeComponent>();
 	reflc.setPosition(move.getWorldTransform().getOrigin());
 	reflc.setBoundingBox(aabbMinWSpace.xyz0(), aabbMaxWSpace.xyz0());
 }
@@ -150,7 +150,7 @@ void ReflectionProbeNode::onMoveUpdate(MoveComponent& move)
 Error ReflectionProbeNode::frameUpdate(Second prevUpdateTime, Second crntTime)
 {
 	// Check the reflection probe component and if it's marked for rendering enable the frustum components
-	const ReflectionProbeComponent& reflc = getComponent<ReflectionProbeComponent>();
+	const ReflectionProbeComponent& reflc = getFirstComponentOfType<ReflectionProbeComponent>();
 
 	const FrustumComponentVisibilityTestFlag testFlags =
 		reflc.getMarkedForRendering() ? FRUSTUM_TEST_FLAGS : FrustumComponentVisibilityTestFlag::NONE;
@@ -171,7 +171,7 @@ void ReflectionProbeNode::drawCallback(RenderQueueDrawContext& ctx, ConstWeakArr
 	for(U32 i = 0; i < userData.getSize(); ++i)
 	{
 		const ReflectionProbeNode& self = *static_cast<const ReflectionProbeNode*>(userData[i]);
-		const ReflectionProbeComponent& rComp = self.getComponent<ReflectionProbeComponent>();
+		const ReflectionProbeComponent& rComp = self.getFirstComponentOfType<ReflectionProbeComponent>();
 
 		const Vec3 tsl = (rComp.getBoundingBoxMin().xyz() + rComp.getBoundingBoxMax().xyz()) / 2.0f;
 		const Vec3 scale = (tsl - rComp.getBoundingBoxMin().xyz());

+ 2 - 2
anki/scene/SceneGraph.cpp

@@ -81,8 +81,8 @@ Error SceneGraph::init(AllocAlignedCallback allocCb, void* allocCbData, ThreadHi
 
 	// Init the default main camera
 	ANKI_CHECK(newSceneNode<PerspectiveCameraNode>("mainCamera", m_defaultMainCam));
-	m_defaultMainCam->getComponent<FrustumComponent>().setPerspective(0.1f, 1000.0f, toRad(60.0f),
-																	  (1080.0f / 1920.0f) * toRad(60.0f));
+	m_defaultMainCam->getFirstComponentOfType<FrustumComponent>().setPerspective(0.1f, 1000.0f, toRad(60.0f),
+																				 (1080.0f / 1920.0f) * toRad(60.0f));
 	m_mainCam = m_defaultMainCam;
 
 	// Create a special node for debugging the physics world

+ 147 - 39
anki/scene/SceneNode.h

@@ -96,100 +96,156 @@ public:
 		return Error::NONE;
 	}
 
-	/// Iterate all components
-	template<typename Func>
-	ANKI_USE_RESULT Error iterateComponents(Func func) const
+	/// Iterate all components.
+	template<typename TFunct>
+	ANKI_USE_RESULT Error iterateComponents(TFunct func) const
 	{
 		Error err = Error::NONE;
 		auto it = m_components.getBegin();
 		auto end = m_components.getEnd();
 		for(; !err && it != end; ++it)
 		{
-			err = func(*(*it));
+			const SceneComponent* c = *it;
+			err = func(*c);
+		}
+
+		return err;
+	}
+
+	/// Iterate all components.
+	template<typename TFunct>
+	ANKI_USE_RESULT Error iterateComponents(TFunct func)
+	{
+		Error err = Error::NONE;
+		auto it = m_components.getBegin();
+		auto end = m_components.getEnd();
+		for(; !err && it != end; ++it)
+		{
+			SceneComponent* c = *it;
+			err = func(*c);
 		}
 
 		return err;
 	}
 
 	/// Iterate all components of a specific type
-	template<typename Component, typename Func>
-	ANKI_USE_RESULT Error iterateComponentsOfType(Func func) const
+	template<typename TComponent, typename TFunct>
+	ANKI_USE_RESULT Error iterateComponentsOfType(TFunct func) const
 	{
 		Error err = Error::NONE;
 		auto it = m_components.getBegin();
 		auto end = m_components.getEnd();
 		for(; !err && it != end; ++it)
 		{
-			auto* comp = *it;
-			if(comp->getType() == Component::CLASS_TYPE)
+			if(it->m_type == TComponent::CLASS_TYPE)
 			{
-				err = func(*static_cast<Component*>(comp));
+				const SceneComponent* comp = *it;
+				err = func(static_cast<const TComponent&>(*comp));
 			}
 		}
 
 		return err;
 	}
 
-	/// Try geting a pointer to the first component of the requested type
-	template<typename Component>
-	Component* tryGetComponent()
+	/// Iterate all components of a specific type
+	template<typename TComponent, typename TFunct>
+	ANKI_USE_RESULT Error iterateComponentsOfType(TFunct func)
 	{
-		for(SceneComponent* comp : m_components)
+		Error err = Error::NONE;
+		auto it = m_components.getBegin();
+		auto end = m_components.getEnd();
+		for(; !err && it != end; ++it)
 		{
-			if(comp->getType() == Component::CLASS_TYPE)
+			if(it->m_type == TComponent::CLASS_TYPE)
 			{
-				return static_cast<Component*>(comp);
+				SceneComponent* comp = *it;
+				err = func(static_cast<TComponent&>(*comp));
 			}
 		}
-		return nullptr;
+
+		return err;
 	}
 
 	/// Try geting a pointer to the first component of the requested type
-	template<typename Component>
-	const Component* tryGetComponent() const
+	template<typename TComponent>
+	const TComponent* tryGetFirstComponentOfType() const
 	{
-		for(const SceneComponent* comp : m_components)
+		for(const ComponentsArrayElement& el : m_components)
 		{
-			if(comp->getType() == Component::CLASS_TYPE)
+			if(el.m_type == TComponent::CLASS_TYPE)
 			{
-				return static_cast<const Component*>(comp);
+				const SceneComponent* comp = el;
+				return static_cast<const TComponent*>(comp);
 			}
 		}
 		return nullptr;
 	}
 
+	/// Try geting a pointer to the first component of the requested type
+	template<typename TComponent>
+	TComponent* tryGetFirstComponentOfType()
+	{
+		const TComponent* c = static_cast<const SceneNode*>(this)->tryGetFirstComponentOfType<TComponent>();
+		return const_cast<TComponent*>(c);
+	}
+
 	/// Get a pointer to the first component of the requested type
-	template<typename Component>
-	Component& getComponent()
+	template<typename TComponent>
+	const TComponent& getFirstComponentOfType() const
 	{
-		Component* out = tryGetComponent<Component>();
+		const TComponent* out = tryGetFirstComponentOfType<TComponent>();
 		ANKI_ASSERT(out != nullptr);
 		return *out;
 	}
 
 	/// Get a pointer to the first component of the requested type
-	template<typename Component>
-	const Component& getComponent() const
+	template<typename TComponent>
+	TComponent& getFirstComponentOfType()
 	{
-		const Component* out = tryGetComponent<Component>();
-		ANKI_ASSERT(out != nullptr);
-		return *out;
+		const TComponent& c = static_cast<const SceneNode*>(this)->getFirstComponentOfType<TComponent>();
+		return const_cast<TComponent&>(c);
+	}
+
+	/// Try geting a pointer to the nth component of the requested type.
+	template<typename TComponent>
+	const TComponent* tryGetNthComponentOfType(U32 nth) const
+	{
+		I32 inth = I32(nth);
+		for(const ComponentsArrayElement& el : m_components)
+		{
+			if(el.m_type == TComponent::CLASS_TYPE && inth-- == 0)
+			{
+				const SceneComponent* comp = el;
+				return static_cast<const TComponent*>(comp);
+			}
+		}
+		return nullptr;
+	}
+
+	/// Try geting a pointer to the nth component of the requested type.
+	template<typename TComponent>
+	TComponent* tryGetNthComponentOfType(U32 nth)
+	{
+		const TComponent* c = static_cast<const SceneNode*>(this)->tryGetNthComponentOfType<TComponent>(nth);
+		return const_cast<TComponent*>(c);
 	}
 
 	/// Get the nth component.
-	template<typename Component>
-	Component& getComponentAt(U32 idx)
+	template<typename TComponent>
+	TComponent& getComponentAt(U32 idx)
 	{
-		ANKI_ASSERT(m_components[idx]->getType() == Component::CLASS_TYPE);
-		return *static_cast<Component*>(m_components[idx]);
+		ANKI_ASSERT(m_components[idx].m_type == TComponent::CLASS_TYPE);
+		SceneComponent* c = m_components[idx];
+		return *static_cast<TComponent*>(c);
 	}
 
 	/// Get the nth component.
-	template<typename Component>
-	const Component& getComponentAt(U32 idx) const
+	template<typename TComponent>
+	const TComponent& getComponentAt(U32 idx) const
 	{
-		ANKI_ASSERT(m_components[idx]->getType() == Component::CLASS_TYPE);
-		return *static_cast<const Component*>(m_components[idx]);
+		ANKI_ASSERT(m_components[idx].m_type == TComponent::CLASS_TYPE);
+		const SceneComponent* c = m_components[idx];
+		return *static_cast<const TComponent*>(c);
 	}
 
 	U32 getComponentCount() const
@@ -210,11 +266,63 @@ protected:
 	ResourceManager& getResourceManager();
 
 private:
+	/// This class packs a pointer to a SceneComponent and its type at the same 64bit value. Used to avoid cache misses
+	/// when iterating the m_components.
+	class ComponentsArrayElement
+	{
+	public:
+		SceneComponentType m_type : 8;
+		PtrSize m_ptr : 56;
+
+		ComponentsArrayElement(SceneComponent* comp)
+			: m_type(comp->getType())
+			, m_ptr(ptrToNumber(comp))
+		{
+			ANKI_ASSERT((ptrToNumber(comp) & (PtrSize(0xFF) << PtrSize(56))) == 0);
+		}
+
+		ComponentsArrayElement(const ComponentsArrayElement& b)
+			: m_type(b.m_type)
+			, m_ptr(b.m_ptr)
+		{
+		}
+
+		ComponentsArrayElement& operator=(const ComponentsArrayElement& b)
+		{
+			m_type = b.m_type;
+			m_ptr = b.m_ptr;
+			return *this;
+		}
+
+		operator SceneComponent*()
+		{
+			return numberToPtr<SceneComponent*>(m_ptr);
+		}
+
+		operator const SceneComponent*() const
+		{
+			return numberToPtr<const SceneComponent*>(m_ptr);
+		}
+
+		const SceneComponent* operator->() const
+		{
+			return numberToPtr<const SceneComponent*>(m_ptr);
+		}
+
+		SceneComponent* operator->()
+		{
+			return numberToPtr<SceneComponent*>(m_ptr);
+		}
+	};
+
+	static_assert(sizeof(SceneComponentType) == 1, "Wrong size");
+	static_assert(sizeof(ComponentsArrayElement) == sizeof(void*), "Wrong size");
+
 	SceneGraph* m_scene = nullptr;
 	U64 m_uuid;
-	String m_name; ///< A unique name
+	String m_name; ///< A unique name.
 
-	DynamicArray<SceneComponent*> m_components;
+	DynamicArray<ComponentsArrayElement> m_components;
 
 	Timestamp m_maxComponentTimestamp = 0;
 

+ 2 - 2
anki/scene/TriggerNode.cpp

@@ -26,7 +26,7 @@ public:
 	{
 		updated = false;
 
-		const MoveComponent& move = node.getComponent<MoveComponent>();
+		const MoveComponent& move = node.getFirstComponentOfType<MoveComponent>();
 		if(move.getTimestamp() == node.getGlobalTimestamp())
 		{
 			static_cast<TriggerNode&>(node).m_trigger->setTransform(move.getWorldTransform());
@@ -58,4 +58,4 @@ Error TriggerNode::init(F32 sphereRadius)
 	return Error::NONE;
 }
 
-} // end namespace anki
+} // end namespace anki

+ 12 - 11
anki/scene/Visibility.cpp

@@ -283,32 +283,33 @@ void VisibilityTestTask::test(ThreadHive& hive, U32 taskId)
 		Bool wantNode = false;
 
 		const RenderComponent* rc = nullptr;
-		wantNode |= wantsRenderComponents && (rc = node.tryGetComponent<RenderComponent>());
+		wantNode |= wantsRenderComponents && (rc = node.tryGetFirstComponentOfType<RenderComponent>());
 
-		wantNode |= wantsShadowCasters && (rc = node.tryGetComponent<RenderComponent>())
+		wantNode |= wantsShadowCasters && (rc = node.tryGetFirstComponentOfType<RenderComponent>())
 					&& !!(rc->getFlags() & RenderComponentFlag::CASTS_SHADOW);
 
 		const LightComponent* lc = nullptr;
-		wantNode |= wantsLightComponents && (lc = node.tryGetComponent<LightComponent>());
+		wantNode |= wantsLightComponents && (lc = node.tryGetFirstComponentOfType<LightComponent>());
 
 		const LensFlareComponent* lfc = nullptr;
-		wantNode |= wantsFlareComponents && (lfc = node.tryGetComponent<LensFlareComponent>());
+		wantNode |= wantsFlareComponents && (lfc = node.tryGetFirstComponentOfType<LensFlareComponent>());
 
 		const ReflectionProbeComponent* reflc = nullptr;
-		wantNode |= wantsReflectionProbes && (reflc = node.tryGetComponent<ReflectionProbeComponent>());
+		wantNode |= wantsReflectionProbes && (reflc = node.tryGetFirstComponentOfType<ReflectionProbeComponent>());
 
 		DecalComponent* decalc = nullptr;
-		wantNode |= wantsDecals && (decalc = node.tryGetComponent<DecalComponent>());
+		wantNode |= wantsDecals && (decalc = node.tryGetFirstComponentOfType<DecalComponent>());
 
 		const FogDensityComponent* fogc = nullptr;
-		wantNode |= wantsFogDensityComponents && (fogc = node.tryGetComponent<FogDensityComponent>());
+		wantNode |= wantsFogDensityComponents && (fogc = node.tryGetFirstComponentOfType<FogDensityComponent>());
 
 		GlobalIlluminationProbeComponent* giprobec = nullptr;
-		wantNode |= wantsGiProbeCoponents && (giprobec = node.tryGetComponent<GlobalIlluminationProbeComponent>());
+		wantNode |=
+			wantsGiProbeCoponents && (giprobec = node.tryGetFirstComponentOfType<GlobalIlluminationProbeComponent>());
 
 		GenericGpuComputeJobComponent* computec = nullptr;
-		wantNode |=
-			wantsGenericComputeJobCoponents && (computec = node.tryGetComponent<GenericGpuComputeJobComponent>());
+		wantNode |= wantsGenericComputeJobCoponents
+					&& (computec = node.tryGetFirstComponentOfType<GenericGpuComputeJobComponent>());
 
 		if(ANKI_UNLIKELY(!wantNode))
 		{
@@ -822,7 +823,7 @@ void SceneGraph::doVisibilityTests(SceneNode& fsn, SceneGraph& scene, RenderQueu
 	VisibilityContext ctx;
 	ctx.m_scene = &scene;
 	ctx.m_earlyZDist = scene.getLimits().m_earlyZDistance;
-	ctx.submitNewWork(fsn.getComponent<FrustumComponent>(), rqueue, hive);
+	ctx.submitNewWork(fsn.getFirstComponentOfType<FrustumComponent>(), rqueue, hive);
 
 	hive.waitAllTasks();
 	ctx.m_testedFrcs.destroy(scene.getFrameAllocator());

+ 4 - 4
anki/scene/components/JointComponent.cpp

@@ -58,7 +58,7 @@ Vec3 JointComponent::computeLocalPivotFromFactors(const PhysicsBodyPtr& body, co
 template<typename TJoint, typename... TArgs>
 void JointComponent::newJoint(const Vec3& relPosFactor, F32 breakingImpulse, TArgs&&... args)
 {
-	BodyComponent* bodyc = m_node->tryGetComponent<BodyComponent>();
+	BodyComponent* bodyc = m_node->tryGetFirstComponentOfType<BodyComponent>();
 
 	if(bodyc)
 	{
@@ -85,11 +85,11 @@ void JointComponent::newPoint2PointJoint(const Vec3& relPosFactor, F32 breakingI
 
 void JointComponent::newPoint2PointJoint2(const Vec3& relPosFactorA, const Vec3& relPosFactorB, F32 breakingImpulse)
 {
-	BodyComponent* bodycA = m_node->tryGetComponent<BodyComponent>();
+	BodyComponent* bodycA = m_node->tryGetFirstComponentOfType<BodyComponent>();
 	BodyComponent* bodycB = nullptr;
 	if(m_node->getParent())
 	{
-		bodycB = m_node->getParent()->tryGetComponent<BodyComponent>();
+		bodycB = m_node->getParent()->tryGetFirstComponentOfType<BodyComponent>();
 	}
 
 	if(bodycA && bodycB)
@@ -146,4 +146,4 @@ Error JointComponent::update(SceneNode& node, Second prevTime, Second crntTime,
 	return Error::NONE;
 }
 
-} // end namespace anki
+} // end namespace anki

+ 1 - 1
anki/scene/components/MoveComponent.cpp

@@ -38,7 +38,7 @@ Bool MoveComponent::updateWorldTransform(SceneNode& node)
 
 		if(parent)
 		{
-			const MoveComponent* parentMove = parent->tryGetComponent<MoveComponent>();
+			const MoveComponent* parentMove = parent->tryGetFirstComponentOfType<MoveComponent>();
 
 			if(parentMove == nullptr)
 			{

+ 1 - 1
anki/scene/components/SceneComponent.h

@@ -16,7 +16,7 @@ namespace anki
 /// @{
 
 // The type of the components
-enum class SceneComponentType : U16
+enum class SceneComponentType : U8
 {
 	NONE,
 	FRUSTUM,

+ 1 - 1
anki/scene/events/AnimationEvent.cpp

@@ -40,7 +40,7 @@ Error AnimationEvent::update(Second prevUpdateTime, Second crntTime)
 	trf.setRotation(Mat3x4(Vec3(0.0f), rot));
 	trf.setScale(scale);
 
-	MoveComponent& move = m_associatedNodes[0]->getComponent<MoveComponent>();
+	MoveComponent& move = m_associatedNodes[0]->getFirstComponentOfType<MoveComponent>();
 	move.setLocalTransform(trf);
 
 	return Error::NONE;

+ 2 - 2
anki/scene/events/JitterMoveEvent.cpp

@@ -17,7 +17,7 @@ Error JitterMoveEvent::init(Second startTime, Second duration, SceneNode* node)
 	Event::init(startTime, duration);
 	m_associatedNodes.emplaceBack(getAllocator(), node);
 
-	const MoveComponent& move = node->getComponent<MoveComponent>();
+	const MoveComponent& move = node->getFirstComponentOfType<MoveComponent>();
 
 	m_originalPos = move.getLocalTransform().getOrigin();
 
@@ -39,7 +39,7 @@ Error JitterMoveEvent::update(Second prevUpdateTime, Second crntTime)
 {
 	SceneNode* node = m_associatedNodes[0];
 
-	MoveComponent& move = node->getComponent<MoveComponent>();
+	MoveComponent& move = node->getFirstComponentOfType<MoveComponent>();
 
 	Transform trf = move.getLocalTransform();
 

+ 3 - 3
anki/scene/events/LightEvent.cpp

@@ -15,7 +15,7 @@ Error LightEvent::init(Second startTime, Second duration, SceneNode* light)
 	Event::init(startTime, duration);
 	m_associatedNodes.emplaceBack(getAllocator(), light);
 
-	LightComponent& lightc = light->getComponent<LightComponent>();
+	LightComponent& lightc = light->getFirstComponentOfType<LightComponent>();
 
 	switch(lightc.getLightComponentType())
 	{
@@ -40,7 +40,7 @@ Error LightEvent::update(Second prevUpdateTime, Second crntTime)
 	const F32 freq = getRandomRange(m_freq - m_freqDeviation, m_freq + m_freqDeviation);
 
 	F32 factor = F32(sin(crntTime * freq * PI)) / 2.0f + 0.5f;
-	LightComponent& lightc = m_associatedNodes[0]->getComponent<LightComponent>();
+	LightComponent& lightc = m_associatedNodes[0]->getFirstComponentOfType<LightComponent>();
 
 	// Update radius
 	if(m_radiusMultiplier != 0.0)
@@ -64,7 +64,7 @@ Error LightEvent::update(Second prevUpdateTime, Second crntTime)
 	{
 		Vec4 outCol = m_originalDiffColor + factor * m_intensityMultiplier;
 
-		LensFlareComponent* lfc = m_associatedNodes[0]->tryGetComponent<LensFlareComponent>();
+		LensFlareComponent* lfc = m_associatedNodes[0]->tryGetFirstComponentOfType<LensFlareComponent>();
 
 		if(lfc && lfc->getColorMultiplier().xyz() == lightc.getDiffuseColor().xyz())
 		{

+ 52 - 52
anki/script/Scene.cpp

@@ -62,7 +62,7 @@ static EventManager* getEventManager(lua_State* l)
 using WeakArraySceneNodePtr = WeakArray<SceneNode*>;
 
 LuaUserDataTypeInfo luaUserDataTypeInfoWeakArraySceneNodePtr = {
-	-2441124622021862484, "WeakArraySceneNodePtr", LuaUserData::computeSizeForGarbageCollected<WeakArraySceneNodePtr>(),
+	-7803856304390433192, "WeakArraySceneNodePtr", LuaUserData::computeSizeForGarbageCollected<WeakArraySceneNodePtr>(),
 	nullptr, nullptr};
 
 template<>
@@ -187,7 +187,7 @@ static inline void wrapWeakArraySceneNodePtr(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo luaUserDataTypeInfoMoveComponent = {-7419644190497561468, "MoveComponent",
+LuaUserDataTypeInfo luaUserDataTypeInfoMoveComponent = {-4954964769395972691, "MoveComponent",
 														LuaUserData::computeSizeForGarbageCollected<MoveComponent>(),
 														nullptr, nullptr};
 
@@ -609,7 +609,7 @@ static inline void wrapMoveComponent(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo luaUserDataTypeInfoLightComponent = {3108888612844103952, "LightComponent",
+LuaUserDataTypeInfo luaUserDataTypeInfoLightComponent = {-2465694465014111240, "LightComponent",
 														 LuaUserData::computeSizeForGarbageCollected<LightComponent>(),
 														 nullptr, nullptr};
 
@@ -1209,7 +1209,7 @@ static inline void wrapLightComponent(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo luaUserDataTypeInfoDecalComponent = {1291169002255374933, "DecalComponent",
+LuaUserDataTypeInfo luaUserDataTypeInfoDecalComponent = {2056814406591907591, "DecalComponent",
 														 LuaUserData::computeSizeForGarbageCollected<DecalComponent>(),
 														 nullptr, nullptr};
 
@@ -1431,7 +1431,7 @@ static inline void wrapDecalComponent(lua_State* l)
 }
 
 LuaUserDataTypeInfo luaUserDataTypeInfoLensFlareComponent = {
-	-5589129522631427243, "LensFlareComponent", LuaUserData::computeSizeForGarbageCollected<LensFlareComponent>(),
+	2254908652583381035, "LensFlareComponent", LuaUserData::computeSizeForGarbageCollected<LensFlareComponent>(),
 	nullptr, nullptr};
 
 template<>
@@ -1554,7 +1554,7 @@ static inline void wrapLensFlareComponent(lua_State* l)
 }
 
 LuaUserDataTypeInfo luaUserDataTypeInfoTriggerComponent = {
-	-2242991378023808398, "TriggerComponent", LuaUserData::computeSizeForGarbageCollected<TriggerComponent>(), nullptr,
+	-725997510931751156, "TriggerComponent", LuaUserData::computeSizeForGarbageCollected<TriggerComponent>(), nullptr,
 	nullptr};
 
 template<>
@@ -1623,7 +1623,7 @@ static inline void wrapTriggerComponent(lua_State* l)
 }
 
 LuaUserDataTypeInfo luaUserDataTypeInfoFogDensityComponent = {
-	392554151834897438, "FogDensityComponent", LuaUserData::computeSizeForGarbageCollected<FogDensityComponent>(),
+	-4216538413369385171, "FogDensityComponent", LuaUserData::computeSizeForGarbageCollected<FogDensityComponent>(),
 	nullptr, nullptr};
 
 template<>
@@ -1848,7 +1848,7 @@ static inline void wrapFogDensityComponent(lua_State* l)
 }
 
 LuaUserDataTypeInfo luaUserDataTypeInfoFrustumComponent = {
-	7182008102835508526, "FrustumComponent", LuaUserData::computeSizeForGarbageCollected<FrustumComponent>(), nullptr,
+	1685454671119522630, "FrustumComponent", LuaUserData::computeSizeForGarbageCollected<FrustumComponent>(), nullptr,
 	nullptr};
 
 template<>
@@ -2034,7 +2034,7 @@ static inline void wrapFrustumComponent(lua_State* l)
 }
 
 LuaUserDataTypeInfo luaUserDataTypeInfoGlobalIlluminationProbeComponent = {
-	-6350545502588513051, "GlobalIlluminationProbeComponent",
+	6593269886846506122, "GlobalIlluminationProbeComponent",
 	LuaUserData::computeSizeForGarbageCollected<GlobalIlluminationProbeComponent>(), nullptr, nullptr};
 
 template<>
@@ -2411,7 +2411,7 @@ static inline void wrapGlobalIlluminationProbeComponent(lua_State* l)
 }
 
 LuaUserDataTypeInfo luaUserDataTypeInfoSceneNode = {
-	-7469182284925083427, "SceneNode", LuaUserData::computeSizeForGarbageCollected<SceneNode>(), nullptr, nullptr};
+	-4596567984428317122, "SceneNode", LuaUserData::computeSizeForGarbageCollected<SceneNode>(), nullptr, nullptr};
 
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<SceneNode>()
@@ -2558,7 +2558,7 @@ static int wrapSceneNodesetMarkedForDeletion(lua_State* l)
 	return 0;
 }
 
-/// Pre-wrap method SceneNode::tryGetComponent<MoveComponent>.
+/// Pre-wrap method SceneNode::tryGetFirstComponentOfType<MoveComponent>.
 static inline int pwrapSceneNodegetMoveComponent(lua_State* l)
 {
 	LuaUserData* ud;
@@ -2582,7 +2582,7 @@ static inline int pwrapSceneNodegetMoveComponent(lua_State* l)
 	SceneNode* self = ud->getData<SceneNode>();
 
 	// Call the method
-	MoveComponent* ret = self->tryGetComponent<MoveComponent>();
+	MoveComponent* ret = self->tryGetFirstComponentOfType<MoveComponent>();
 
 	// Push return value
 	if(ANKI_UNLIKELY(ret == nullptr))
@@ -2600,7 +2600,7 @@ static inline int pwrapSceneNodegetMoveComponent(lua_State* l)
 	return 1;
 }
 
-/// Wrap method SceneNode::tryGetComponent<MoveComponent>.
+/// Wrap method SceneNode::tryGetFirstComponentOfType<MoveComponent>.
 static int wrapSceneNodegetMoveComponent(lua_State* l)
 {
 	int res = pwrapSceneNodegetMoveComponent(l);
@@ -2613,7 +2613,7 @@ static int wrapSceneNodegetMoveComponent(lua_State* l)
 	return 0;
 }
 
-/// Pre-wrap method SceneNode::tryGetComponent<LightComponent>.
+/// Pre-wrap method SceneNode::tryGetFirstComponentOfType<LightComponent>.
 static inline int pwrapSceneNodegetLightComponent(lua_State* l)
 {
 	LuaUserData* ud;
@@ -2637,7 +2637,7 @@ static inline int pwrapSceneNodegetLightComponent(lua_State* l)
 	SceneNode* self = ud->getData<SceneNode>();
 
 	// Call the method
-	LightComponent* ret = self->tryGetComponent<LightComponent>();
+	LightComponent* ret = self->tryGetFirstComponentOfType<LightComponent>();
 
 	// Push return value
 	if(ANKI_UNLIKELY(ret == nullptr))
@@ -2655,7 +2655,7 @@ static inline int pwrapSceneNodegetLightComponent(lua_State* l)
 	return 1;
 }
 
-/// Wrap method SceneNode::tryGetComponent<LightComponent>.
+/// Wrap method SceneNode::tryGetFirstComponentOfType<LightComponent>.
 static int wrapSceneNodegetLightComponent(lua_State* l)
 {
 	int res = pwrapSceneNodegetLightComponent(l);
@@ -2668,7 +2668,7 @@ static int wrapSceneNodegetLightComponent(lua_State* l)
 	return 0;
 }
 
-/// Pre-wrap method SceneNode::tryGetComponent<LensFlareComponent>.
+/// Pre-wrap method SceneNode::tryGetFirstComponentOfType<LensFlareComponent>.
 static inline int pwrapSceneNodegetLensFlareComponent(lua_State* l)
 {
 	LuaUserData* ud;
@@ -2692,7 +2692,7 @@ static inline int pwrapSceneNodegetLensFlareComponent(lua_State* l)
 	SceneNode* self = ud->getData<SceneNode>();
 
 	// Call the method
-	LensFlareComponent* ret = self->tryGetComponent<LensFlareComponent>();
+	LensFlareComponent* ret = self->tryGetFirstComponentOfType<LensFlareComponent>();
 
 	// Push return value
 	if(ANKI_UNLIKELY(ret == nullptr))
@@ -2710,7 +2710,7 @@ static inline int pwrapSceneNodegetLensFlareComponent(lua_State* l)
 	return 1;
 }
 
-/// Wrap method SceneNode::tryGetComponent<LensFlareComponent>.
+/// Wrap method SceneNode::tryGetFirstComponentOfType<LensFlareComponent>.
 static int wrapSceneNodegetLensFlareComponent(lua_State* l)
 {
 	int res = pwrapSceneNodegetLensFlareComponent(l);
@@ -2723,7 +2723,7 @@ static int wrapSceneNodegetLensFlareComponent(lua_State* l)
 	return 0;
 }
 
-/// Pre-wrap method SceneNode::tryGetComponent<DecalComponent>.
+/// Pre-wrap method SceneNode::tryGetFirstComponentOfType<DecalComponent>.
 static inline int pwrapSceneNodegetDecalComponent(lua_State* l)
 {
 	LuaUserData* ud;
@@ -2747,7 +2747,7 @@ static inline int pwrapSceneNodegetDecalComponent(lua_State* l)
 	SceneNode* self = ud->getData<SceneNode>();
 
 	// Call the method
-	DecalComponent* ret = self->tryGetComponent<DecalComponent>();
+	DecalComponent* ret = self->tryGetFirstComponentOfType<DecalComponent>();
 
 	// Push return value
 	if(ANKI_UNLIKELY(ret == nullptr))
@@ -2765,7 +2765,7 @@ static inline int pwrapSceneNodegetDecalComponent(lua_State* l)
 	return 1;
 }
 
-/// Wrap method SceneNode::tryGetComponent<DecalComponent>.
+/// Wrap method SceneNode::tryGetFirstComponentOfType<DecalComponent>.
 static int wrapSceneNodegetDecalComponent(lua_State* l)
 {
 	int res = pwrapSceneNodegetDecalComponent(l);
@@ -2778,7 +2778,7 @@ static int wrapSceneNodegetDecalComponent(lua_State* l)
 	return 0;
 }
 
-/// Pre-wrap method SceneNode::tryGetComponent<TriggerComponent>.
+/// Pre-wrap method SceneNode::tryGetFirstComponentOfType<TriggerComponent>.
 static inline int pwrapSceneNodegetTriggerComponent(lua_State* l)
 {
 	LuaUserData* ud;
@@ -2802,7 +2802,7 @@ static inline int pwrapSceneNodegetTriggerComponent(lua_State* l)
 	SceneNode* self = ud->getData<SceneNode>();
 
 	// Call the method
-	TriggerComponent* ret = self->tryGetComponent<TriggerComponent>();
+	TriggerComponent* ret = self->tryGetFirstComponentOfType<TriggerComponent>();
 
 	// Push return value
 	if(ANKI_UNLIKELY(ret == nullptr))
@@ -2820,7 +2820,7 @@ static inline int pwrapSceneNodegetTriggerComponent(lua_State* l)
 	return 1;
 }
 
-/// Wrap method SceneNode::tryGetComponent<TriggerComponent>.
+/// Wrap method SceneNode::tryGetFirstComponentOfType<TriggerComponent>.
 static int wrapSceneNodegetTriggerComponent(lua_State* l)
 {
 	int res = pwrapSceneNodegetTriggerComponent(l);
@@ -2833,7 +2833,7 @@ static int wrapSceneNodegetTriggerComponent(lua_State* l)
 	return 0;
 }
 
-/// Pre-wrap method SceneNode::tryGetComponent<FogDensityComponent>.
+/// Pre-wrap method SceneNode::tryGetFirstComponentOfType<FogDensityComponent>.
 static inline int pwrapSceneNodegetFogDensityComponent(lua_State* l)
 {
 	LuaUserData* ud;
@@ -2857,7 +2857,7 @@ static inline int pwrapSceneNodegetFogDensityComponent(lua_State* l)
 	SceneNode* self = ud->getData<SceneNode>();
 
 	// Call the method
-	FogDensityComponent* ret = self->tryGetComponent<FogDensityComponent>();
+	FogDensityComponent* ret = self->tryGetFirstComponentOfType<FogDensityComponent>();
 
 	// Push return value
 	if(ANKI_UNLIKELY(ret == nullptr))
@@ -2875,7 +2875,7 @@ static inline int pwrapSceneNodegetFogDensityComponent(lua_State* l)
 	return 1;
 }
 
-/// Wrap method SceneNode::tryGetComponent<FogDensityComponent>.
+/// Wrap method SceneNode::tryGetFirstComponentOfType<FogDensityComponent>.
 static int wrapSceneNodegetFogDensityComponent(lua_State* l)
 {
 	int res = pwrapSceneNodegetFogDensityComponent(l);
@@ -2888,7 +2888,7 @@ static int wrapSceneNodegetFogDensityComponent(lua_State* l)
 	return 0;
 }
 
-/// Pre-wrap method SceneNode::tryGetComponent<FrustumComponent>.
+/// Pre-wrap method SceneNode::tryGetFirstComponentOfType<FrustumComponent>.
 static inline int pwrapSceneNodegetFrustumComponent(lua_State* l)
 {
 	LuaUserData* ud;
@@ -2912,7 +2912,7 @@ static inline int pwrapSceneNodegetFrustumComponent(lua_State* l)
 	SceneNode* self = ud->getData<SceneNode>();
 
 	// Call the method
-	FrustumComponent* ret = self->tryGetComponent<FrustumComponent>();
+	FrustumComponent* ret = self->tryGetFirstComponentOfType<FrustumComponent>();
 
 	// Push return value
 	if(ANKI_UNLIKELY(ret == nullptr))
@@ -2930,7 +2930,7 @@ static inline int pwrapSceneNodegetFrustumComponent(lua_State* l)
 	return 1;
 }
 
-/// Wrap method SceneNode::tryGetComponent<FrustumComponent>.
+/// Wrap method SceneNode::tryGetFirstComponentOfType<FrustumComponent>.
 static int wrapSceneNodegetFrustumComponent(lua_State* l)
 {
 	int res = pwrapSceneNodegetFrustumComponent(l);
@@ -2943,7 +2943,7 @@ static int wrapSceneNodegetFrustumComponent(lua_State* l)
 	return 0;
 }
 
-/// Pre-wrap method SceneNode::tryGetComponent<GlobalIlluminationProbeComponent>.
+/// Pre-wrap method SceneNode::tryGetFirstComponentOfType<GlobalIlluminationProbeComponent>.
 static inline int pwrapSceneNodegetGlobalIlluminationProbeComponent(lua_State* l)
 {
 	LuaUserData* ud;
@@ -2967,7 +2967,7 @@ static inline int pwrapSceneNodegetGlobalIlluminationProbeComponent(lua_State* l
 	SceneNode* self = ud->getData<SceneNode>();
 
 	// Call the method
-	GlobalIlluminationProbeComponent* ret = self->tryGetComponent<GlobalIlluminationProbeComponent>();
+	GlobalIlluminationProbeComponent* ret = self->tryGetFirstComponentOfType<GlobalIlluminationProbeComponent>();
 
 	// Push return value
 	if(ANKI_UNLIKELY(ret == nullptr))
@@ -2986,7 +2986,7 @@ static inline int pwrapSceneNodegetGlobalIlluminationProbeComponent(lua_State* l
 	return 1;
 }
 
-/// Wrap method SceneNode::tryGetComponent<GlobalIlluminationProbeComponent>.
+/// Wrap method SceneNode::tryGetFirstComponentOfType<GlobalIlluminationProbeComponent>.
 static int wrapSceneNodegetGlobalIlluminationProbeComponent(lua_State* l)
 {
 	int res = pwrapSceneNodegetGlobalIlluminationProbeComponent(l);
@@ -3019,7 +3019,7 @@ static inline void wrapSceneNode(lua_State* l)
 }
 
 LuaUserDataTypeInfo luaUserDataTypeInfoModelNode = {
-	1550727051611601233, "ModelNode", LuaUserData::computeSizeForGarbageCollected<ModelNode>(), nullptr, nullptr};
+	-450705026354471566, "ModelNode", LuaUserData::computeSizeForGarbageCollected<ModelNode>(), nullptr, nullptr};
 
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<ModelNode>()
@@ -3085,7 +3085,7 @@ static inline void wrapModelNode(lua_State* l)
 }
 
 LuaUserDataTypeInfo luaUserDataTypeInfoPerspectiveCameraNode = {
-	4336357556756945336, "PerspectiveCameraNode", LuaUserData::computeSizeForGarbageCollected<PerspectiveCameraNode>(),
+	5203874346323105211, "PerspectiveCameraNode", LuaUserData::computeSizeForGarbageCollected<PerspectiveCameraNode>(),
 	nullptr, nullptr};
 
 template<>
@@ -3151,7 +3151,7 @@ static inline void wrapPerspectiveCameraNode(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo luaUserDataTypeInfoPointLightNode = {1041276040139896217, "PointLightNode",
+LuaUserDataTypeInfo luaUserDataTypeInfoPointLightNode = {5481907254599316993, "PointLightNode",
 														 LuaUserData::computeSizeForGarbageCollected<PointLightNode>(),
 														 nullptr, nullptr};
 
@@ -3277,7 +3277,7 @@ static inline void wrapPointLightNode(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo luaUserDataTypeInfoSpotLightNode = {1618463592957166120, "SpotLightNode",
+LuaUserDataTypeInfo luaUserDataTypeInfoSpotLightNode = {-4171144965887956516, "SpotLightNode",
 														LuaUserData::computeSizeForGarbageCollected<SpotLightNode>(),
 														nullptr, nullptr};
 
@@ -3345,7 +3345,7 @@ static inline void wrapSpotLightNode(lua_State* l)
 }
 
 LuaUserDataTypeInfo luaUserDataTypeInfoDirectionalLightNode = {
-	-8374966293987052340, "DirectionalLightNode", LuaUserData::computeSizeForGarbageCollected<DirectionalLightNode>(),
+	-5947638574932730667, "DirectionalLightNode", LuaUserData::computeSizeForGarbageCollected<DirectionalLightNode>(),
 	nullptr, nullptr};
 
 template<>
@@ -3412,7 +3412,7 @@ static inline void wrapDirectionalLightNode(lua_State* l)
 }
 
 LuaUserDataTypeInfo luaUserDataTypeInfoStaticCollisionNode = {
-	2715940926837664885, "StaticCollisionNode", LuaUserData::computeSizeForGarbageCollected<StaticCollisionNode>(),
+	7611855183596540382, "StaticCollisionNode", LuaUserData::computeSizeForGarbageCollected<StaticCollisionNode>(),
 	nullptr, nullptr};
 
 template<>
@@ -3479,7 +3479,7 @@ static inline void wrapStaticCollisionNode(lua_State* l)
 }
 
 LuaUserDataTypeInfo luaUserDataTypeInfoParticleEmitterNode = {
-	7384430295490764399, "ParticleEmitterNode", LuaUserData::computeSizeForGarbageCollected<ParticleEmitterNode>(),
+	-4528616999498906935, "ParticleEmitterNode", LuaUserData::computeSizeForGarbageCollected<ParticleEmitterNode>(),
 	nullptr, nullptr};
 
 template<>
@@ -3546,7 +3546,7 @@ static inline void wrapParticleEmitterNode(lua_State* l)
 }
 
 LuaUserDataTypeInfo luaUserDataTypeInfoGpuParticleEmitterNode = {
-	-7315973565018991013, "GpuParticleEmitterNode",
+	-1474617733666958838, "GpuParticleEmitterNode",
 	LuaUserData::computeSizeForGarbageCollected<GpuParticleEmitterNode>(), nullptr, nullptr};
 
 template<>
@@ -3613,7 +3613,7 @@ static inline void wrapGpuParticleEmitterNode(lua_State* l)
 }
 
 LuaUserDataTypeInfo luaUserDataTypeInfoReflectionProbeNode = {
-	-8329116766593565158, "ReflectionProbeNode", LuaUserData::computeSizeForGarbageCollected<ReflectionProbeNode>(),
+	7820862353662459657, "ReflectionProbeNode", LuaUserData::computeSizeForGarbageCollected<ReflectionProbeNode>(),
 	nullptr, nullptr};
 
 template<>
@@ -3679,7 +3679,7 @@ static inline void wrapReflectionProbeNode(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo luaUserDataTypeInfoOccluderNode = {-7280020184797189665, "OccluderNode",
+LuaUserDataTypeInfo luaUserDataTypeInfoOccluderNode = {-8953939426134655474, "OccluderNode",
 													   LuaUserData::computeSizeForGarbageCollected<OccluderNode>(),
 													   nullptr, nullptr};
 
@@ -3747,7 +3747,7 @@ static inline void wrapOccluderNode(lua_State* l)
 }
 
 LuaUserDataTypeInfo luaUserDataTypeInfoDecalNode = {
-	-8170576609024446608, "DecalNode", LuaUserData::computeSizeForGarbageCollected<DecalNode>(), nullptr, nullptr};
+	8416942623307160724, "DecalNode", LuaUserData::computeSizeForGarbageCollected<DecalNode>(), nullptr, nullptr};
 
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<DecalNode>()
@@ -3813,7 +3813,7 @@ static inline void wrapDecalNode(lua_State* l)
 }
 
 LuaUserDataTypeInfo luaUserDataTypeInfoTriggerNode = {
-	-3086882463183440318, "TriggerNode", LuaUserData::computeSizeForGarbageCollected<TriggerNode>(), nullptr, nullptr};
+	2501977285852887294, "TriggerNode", LuaUserData::computeSizeForGarbageCollected<TriggerNode>(), nullptr, nullptr};
 
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<TriggerNode>()
@@ -3878,7 +3878,7 @@ static inline void wrapTriggerNode(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo luaUserDataTypeInfoFogDensityNode = {-8876559879318375617, "FogDensityNode",
+LuaUserDataTypeInfo luaUserDataTypeInfoFogDensityNode = {-4989050962579528993, "FogDensityNode",
 														 LuaUserData::computeSizeForGarbageCollected<FogDensityNode>(),
 														 nullptr, nullptr};
 
@@ -3946,7 +3946,7 @@ static inline void wrapFogDensityNode(lua_State* l)
 }
 
 LuaUserDataTypeInfo luaUserDataTypeInfoGlobalIlluminationProbeNode = {
-	5041818919735575380, "GlobalIlluminationProbeNode",
+	710930745580002886, "GlobalIlluminationProbeNode",
 	LuaUserData::computeSizeForGarbageCollected<GlobalIlluminationProbeNode>(), nullptr, nullptr};
 
 template<>
@@ -4013,7 +4013,7 @@ static inline void wrapGlobalIlluminationProbeNode(lua_State* l)
 }
 
 LuaUserDataTypeInfo luaUserDataTypeInfoSceneGraph = {
-	-8935190560851135504, "SceneGraph", LuaUserData::computeSizeForGarbageCollected<SceneGraph>(), nullptr, nullptr};
+	4017435066089144029, "SceneGraph", LuaUserData::computeSizeForGarbageCollected<SceneGraph>(), nullptr, nullptr};
 
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<SceneGraph>()
@@ -4963,7 +4963,7 @@ static inline void wrapSceneGraph(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo luaUserDataTypeInfoEvent = {3243578489496433103, "Event",
+LuaUserDataTypeInfo luaUserDataTypeInfoEvent = {8747813287410577862, "Event",
 												LuaUserData::computeSizeForGarbageCollected<Event>(), nullptr, nullptr};
 
 template<>
@@ -5032,7 +5032,7 @@ static inline void wrapEvent(lua_State* l)
 }
 
 LuaUserDataTypeInfo luaUserDataTypeInfoLightEvent = {
-	5568228196412666234, "LightEvent", LuaUserData::computeSizeForGarbageCollected<LightEvent>(), nullptr, nullptr};
+	8003708600719537087, "LightEvent", LuaUserData::computeSizeForGarbageCollected<LightEvent>(), nullptr, nullptr};
 
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<LightEvent>()
@@ -5156,7 +5156,7 @@ static inline void wrapLightEvent(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo luaUserDataTypeInfoEventManager = {-8139401118670242711, "EventManager",
+LuaUserDataTypeInfo luaUserDataTypeInfoEventManager = {-2344492732810723892, "EventManager",
 													   LuaUserData::computeSizeForGarbageCollected<EventManager>(),
 													   nullptr, nullptr};
 

+ 8 - 8
anki/script/Scene.xml

@@ -311,28 +311,28 @@ using WeakArraySceneNodePtr = WeakArray<SceneNode*>;
 					</args>
 				</method>
 				<method name="setMarkedForDeletion"></method>
-				<method name="tryGetComponent&lt;MoveComponent&gt;" alias="getMoveComponent">
+				<method name="tryGetFirstComponentOfType&lt;MoveComponent&gt;" alias="getMoveComponent">
 					<return>MoveComponent*</return>
 				</method>
-				<method name="tryGetComponent&lt;LightComponent&gt;" alias="getLightComponent">
+				<method name="tryGetFirstComponentOfType&lt;LightComponent&gt;" alias="getLightComponent">
 					<return>LightComponent*</return>
 				</method>
-				<method name="tryGetComponent&lt;LensFlareComponent&gt;" alias="getLensFlareComponent">
+				<method name="tryGetFirstComponentOfType&lt;LensFlareComponent&gt;" alias="getLensFlareComponent">
 					<return>LensFlareComponent*</return>
 				</method>
-				<method name="tryGetComponent&lt;DecalComponent&gt;" alias="getDecalComponent">
+				<method name="tryGetFirstComponentOfType&lt;DecalComponent&gt;" alias="getDecalComponent">
 					<return>DecalComponent*</return>
 				</method>
-				<method name="tryGetComponent&lt;TriggerComponent&gt;" alias="getTriggerComponent">
+				<method name="tryGetFirstComponentOfType&lt;TriggerComponent&gt;" alias="getTriggerComponent">
 					<return>TriggerComponent*</return>
 				</method>
-				<method name="tryGetComponent&lt;FogDensityComponent&gt;" alias="getFogDensityComponent">
+				<method name="tryGetFirstComponentOfType&lt;FogDensityComponent&gt;" alias="getFogDensityComponent">
 					<return>FogDensityComponent*</return>
 				</method>
-				<method name="tryGetComponent&lt;FrustumComponent&gt;" alias="getFrustumComponent">
+				<method name="tryGetFirstComponentOfType&lt;FrustumComponent&gt;" alias="getFrustumComponent">
 					<return>FrustumComponent*</return>
 				</method>
-				<method name="tryGetComponent&lt;GlobalIlluminationProbeComponent&gt;" alias="getGlobalIlluminationProbeComponent">
+				<method name="tryGetFirstComponentOfType&lt;GlobalIlluminationProbeComponent&gt;" alias="getGlobalIlluminationProbeComponent">
 					<return>GlobalIlluminationProbeComponent*</return>
 				</method>
 			</methods>

+ 2 - 2
samples/common/Framework.cpp

@@ -96,11 +96,11 @@ Error SampleApp::userMainLoop(Bool& quit, Second elapsedTime)
 		in.lockCursor(true);
 
 		// move the camera
-		static MoveComponent* mover = &scene.getActiveCameraNode().getComponent<MoveComponent>();
+		static MoveComponent* mover = &scene.getActiveCameraNode().getFirstComponentOfType<MoveComponent>();
 
 		if(in.getKey(KeyCode::_1) == 1)
 		{
-			mover = &scene.getActiveCameraNode().getComponent<MoveComponent>();
+			mover = &scene.getActiveCameraNode().getFirstComponentOfType<MoveComponent>();
 		}
 
 		if(in.getKey(KeyCode::F1) == 1)

+ 21 - 19
samples/physics_playground/Main.cpp

@@ -115,12 +115,12 @@ Error MyApp::sampleExtraInit()
 	if(1)
 	{
 		SceneNode& cam = getSceneGraph().getActiveCameraNode();
-		cam.getComponent<MoveComponent>().setLocalTransform(
+		cam.getFirstComponentOfType<MoveComponent>().setLocalTransform(
 			Transform(Vec4(0.0, 0.0, 5.0, 0.0), Mat3x4::getIdentity(), 1.0));
 
 		PlayerNode* player;
 		ANKI_CHECK(getSceneGraph().newSceneNode("player", player, Vec4(0.0f, 2.5f, 0.0f, 0.0f)));
-		PlayerControllerComponent& pcomp = player->getComponent<PlayerControllerComponent>();
+		PlayerControllerComponent& pcomp = player->getFirstComponentOfType<PlayerControllerComponent>();
 		pcomp.getPhysicsPlayerController()->setMaterialMask(PhysicsMaterialBit::STATIC_GEOMETRY);
 
 		player->addChild(&cam);
@@ -134,12 +134,12 @@ Error MyApp::sampleExtraInit()
 
 		BodyNode* body;
 		ANKI_CHECK(getSceneGraph().newSceneNode<BodyNode>("bmonkey_p2p", body, "assets/Suzanne.ankicl"));
-		body->getComponent<BodyComponent>().setTransform(
+		body->getFirstComponentOfType<BodyComponent>().setTransform(
 			Transform(Vec4(-0.0f, 4.0f, -3.0f, 0.0f), Mat3x4::getIdentity(), 1.0f));
 
 		body->addChild(monkey);
 
-		body->getComponent<JointComponent>().newHingeJoint(Vec3(0.2f, 1.0f, 0.0f), Vec3(1, 0, 0));
+		body->getFirstComponentOfType<JointComponent>().newHingeJoint(Vec3(0.2f, 1.0f, 0.0f), Vec3(1, 0, 0));
 	}
 
 	// Create a chain
@@ -158,15 +158,15 @@ Error MyApp::sampleExtraInit()
 			trf.getOrigin().y() -= F32(i) * 1.25f;
 			// trf.getOrigin().x() -= i * 0.25f;
 
-			// monkey->getComponent<MoveComponent>().setLocalTransform(trf);
+			// monkey->getFirstComponentOfType<MoveComponent>().setLocalTransform(trf);
 
 			BodyNode* body;
 			ANKI_CHECK(getSceneGraph().newSceneNode<BodyNode>(
 				StringAuto(getAllocator()).sprintf("bmonkey_chain%u", i).toCString(), body, "assets/Suzanne.ankicl"));
-			body->getComponent<BodyComponent>().setTransform(trf);
+			body->getFirstComponentOfType<BodyComponent>().setTransform(trf);
 
 			// Create joint
-			JointComponent& jointc = body->getComponent<JointComponent>();
+			JointComponent& jointc = body->getFirstComponentOfType<JointComponent>();
 			if(prevBody == nullptr)
 			{
 				jointc.newPoint2PointJoint(Vec3(0, 1, 0));
@@ -187,7 +187,7 @@ Error MyApp::sampleExtraInit()
 		TriggerNode* node;
 		ANKI_CHECK(getSceneGraph().newSceneNode("trigger", node, 1.8f));
 
-		node->getComponent<MoveComponent>().setLocalOrigin(Vec4(1.0f, 0.5f, 0.0f, 0.0f));
+		node->getFirstComponentOfType<MoveComponent>().setLocalOrigin(Vec4(1.0f, 0.5f, 0.0f, 0.0f));
 	}
 
 	return Error::NONE;
@@ -227,7 +227,7 @@ Error MyApp::userMainLoop(Bool& quit, Second elapsedTime)
 	if(getInput().getKey(KeyCode::R))
 	{
 		SceneNode& player = getSceneGraph().findSceneNode("player");
-		player.getComponent<PlayerControllerComponent>().moveToPosition(Vec4(0.0f, 2.0f, 0.0f, 0.0f));
+		player.getFirstComponentOfType<PlayerControllerComponent>().moveToPosition(Vec4(0.0f, 2.0f, 0.0f, 0.0f));
 	}
 
 	if(getInput().getMouseButton(MouseButton::LEFT) == 1)
@@ -236,20 +236,21 @@ Error MyApp::userMainLoop(Bool& quit, Second elapsedTime)
 
 		static U instance = 0;
 
-		Transform camTrf = getSceneGraph().getActiveCameraNode().getComponent<MoveComponent>().getWorldTransform();
+		Transform camTrf =
+			getSceneGraph().getActiveCameraNode().getFirstComponentOfType<MoveComponent>().getWorldTransform();
 
 		ModelNode* monkey;
 		ANKI_CHECK(getSceneGraph().newSceneNode<ModelNode>(
 			StringAuto(getAllocator()).sprintf("monkey%u", instance++).toCString(), monkey,
 			"assets/Suzannedynamic-material.ankimdl"));
-		// monkey->getComponent<MoveComponent>().setLocalTransform(camTrf);
+		// monkey->getFirstComponentOfType<MoveComponent>().setLocalTransform(camTrf);
 
 		BodyNode* body;
 		ANKI_CHECK(getSceneGraph().newSceneNode<BodyNode>(
 			StringAuto(getAllocator()).sprintf("bmonkey%u", instance++).toCString(), body, "assets/Suzanne.ankicl"));
-		body->getComponent<BodyComponent>().setTransform(camTrf);
+		body->getFirstComponentOfType<BodyComponent>().setTransform(camTrf);
 
-		PhysicsBodyPtr pbody = body->getComponent<BodyComponent>().getPhysicsBody();
+		PhysicsBodyPtr pbody = body->getFirstComponentOfType<BodyComponent>().getPhysicsBody();
 		pbody->applyForce(camTrf.getRotation().getZAxis().xyz() * -1500.0f, Vec3(0.0f, 0.0f, 0.0f));
 
 		body->addChild(monkey);
@@ -260,7 +261,8 @@ Error MyApp::userMainLoop(Bool& quit, Second elapsedTime)
 
 	if(getInput().getMouseButton(MouseButton::RIGHT) == 1)
 	{
-		Transform camTrf = getSceneGraph().getActiveCameraNode().getComponent<MoveComponent>().getWorldTransform();
+		Transform camTrf =
+			getSceneGraph().getActiveCameraNode().getFirstComponentOfType<MoveComponent>().getWorldTransform();
 		Vec3 from = camTrf.getOrigin().xyz();
 		Vec3 to = from + -camTrf.getRotation().getZAxis() * 100.0f;
 
@@ -290,7 +292,7 @@ Error MyApp::userMainLoop(Bool& quit, Second elapsedTime)
 			ANKI_CHECK(getSceneGraph().newSceneNode(
 				StringAuto(getSceneGraph().getFrameAllocator()).sprintf("decal%u", id++).toCString(), monkey,
 				"assets/Suzannedynamic-material.ankimdl"));
-			monkey->getComponent<MoveComponent>().setLocalTransform(trf);
+			monkey->getFirstComponentOfType<MoveComponent>().setLocalTransform(trf);
 
 			createDestructionEvent(monkey);
 
@@ -300,7 +302,7 @@ Error MyApp::userMainLoop(Bool& quit, Second elapsedTime)
 			ANKI_CHECK(getSceneGraph().newSceneNode(
 				StringAuto(getSceneGraph().getFrameAllocator()).sprintf("parts%u", id++).toCString(), particles,
 				"assets/smoke.ankipart"));
-			particles->getComponent<MoveComponent>().setLocalTransform(trf);
+			particles->getFirstComponentOfType<MoveComponent>().setLocalTransform(trf);
 			createDestructionEvent(particles);
 #endif
 
@@ -313,11 +315,11 @@ Error MyApp::userMainLoop(Bool& quit, Second elapsedTime)
 
 				FogDensityNode* fogNode;
 				ANKI_CHECK(getSceneGraph().newSceneNode(name.toCString(), fogNode));
-				FogDensityComponent& fogComp = fogNode->getComponent<FogDensityComponent>();
+				FogDensityComponent& fogComp = fogNode->getFirstComponentOfType<FogDensityComponent>();
 				fogComp.setSphere(2.1f);
 				fogComp.setDensity(15.0f);
 
-				fogNode->getComponent<MoveComponent>().setLocalTransform(trf);
+				fogNode->getFirstComponentOfType<MoveComponent>().setLocalTransform(trf);
 
 				createDestructionEvent(fogNode);
 				createFogVolumeFadeEvent(fogNode);
@@ -328,7 +330,7 @@ Error MyApp::userMainLoop(Bool& quit, Second elapsedTime)
 	if(0)
 	{
 		SceneNode& node = getSceneGraph().findSceneNode("trigger");
-		TriggerComponent& comp = node.getComponent<TriggerComponent>();
+		TriggerComponent& comp = node.getFirstComponentOfType<TriggerComponent>();
 
 		for(U32 i = 0; i < comp.getContactSceneNodes().getSize(); ++i)
 		{

+ 2 - 2
samples/skeletal_animation/Main.cpp

@@ -28,7 +28,7 @@ public:
 		animInfo.m_repeatTimes = -1.0;
 		getSceneGraph()
 			.findSceneNode("droid.001")
-			.getComponent<SkinComponent>()
+			.getFirstComponentOfType<SkinComponent>()
 			.playAnimation(0, m_floatAnim, animInfo);
 
 		getMainRenderer().getOffscreenRenderer().getVolumetricFog().setFogParticleColor(Vec3(1.0f, 0.9f, 0.9f));
@@ -49,7 +49,7 @@ public:
 			animInfo.m_blendOutTime = 0.35;
 			getSceneGraph()
 				.findSceneNode("droid.001")
-				.getComponent<SkinComponent>()
+				.getFirstComponentOfType<SkinComponent>()
 				.playAnimation(1, m_waveAnim, animInfo);
 		}
 

+ 5 - 5
sandbox/Main.cpp

@@ -76,9 +76,9 @@ Error MyApp::init(int argc, char* argv[])
 
 	PlayerNode* pnode;
 	ANKI_CHECK(scene.newSceneNode<PlayerNode>(
-		"player", pnode, cam.getComponent<MoveComponent>().getLocalOrigin() - Vec4(0.0, 1.0, 0.0, 0.0)));
+		"player", pnode, cam.getFirstComponentOfType<MoveComponent>().getLocalOrigin() - Vec4(0.0, 1.0, 0.0, 0.0)));
 
-	cam.getComponent<MoveComponent>().setLocalTransform(
+	cam.getFirstComponentOfType<MoveComponent>().setLocalTransform(
 		Transform(Vec4(0.0, 0.0, 0.0, 0.0), Mat3x4::getIdentity(), 1.0));
 
 	pnode->addChild(&cam);
@@ -105,15 +105,15 @@ Error MyApp::userMainLoop(Bool& quit, Second elapsedTime)
 	}
 
 	// move the camera
-	static MoveComponent* mover = &scene.getActiveCameraNode().getComponent<MoveComponent>();
+	static MoveComponent* mover = &scene.getActiveCameraNode().getFirstComponentOfType<MoveComponent>();
 
 	if(in.getKey(KeyCode::_1))
 	{
-		mover = scene.getActiveCameraNode().tryGetComponent<MoveComponent>();
+		mover = scene.getActiveCameraNode().tryGetFirstComponentOfType<MoveComponent>();
 	}
 	if(in.getKey(KeyCode::_2))
 	{
-		mover = &scene.findSceneNode("Cylinder.049").getComponent<MoveComponent>();
+		mover = &scene.findSceneNode("Cylinder.049").getFirstComponentOfType<MoveComponent>();
 	}
 
 	if(in.getKey(KeyCode::L) == 1)