Browse Source

Refactor bitfields. Expose some additional funcs to lua

Panagiotis Christopoulos Charitos 9 years ago
parent
commit
d56b8f4944

+ 2 - 1
include/anki/Util.h

@@ -44,7 +44,8 @@
 #include <anki/util/Array.h>
 #include <anki/util/Assert.h>
 #include <anki/util/Atomic.h>
-#include <anki/util/Bitset.h>
+#include <anki/util/BitSet.h>
+#include <anki/util/BitMask.h>
 #include <anki/util/DArray.h>
 #include <anki/util/Dictionary.h>
 #include <anki/util/Enum.h>

+ 0 - 1
include/anki/physics/PhysicsDrawer.h

@@ -6,7 +6,6 @@
 #pragma once
 
 #include <anki/physics/Common.h>
-#include <anki/util/Bitset.h>
 
 // Forward
 class NewtonBody;

+ 1 - 0
include/anki/renderer/Common.h

@@ -31,6 +31,7 @@ class DownscaleBlur;
 class Volumetric;
 
 class RenderingContext;
+class DebugDrawer;
 
 /// @addtogroup renderer
 /// @{

+ 26 - 21
include/anki/renderer/Dbg.h

@@ -7,40 +7,31 @@
 
 #include <anki/renderer/RenderingPass.h>
 #include <anki/Gr.h>
-#include <anki/renderer/DebugDrawer.h>
-#include <anki/util/Bitset.h>
+#include <anki/util/BitMask.h>
 #include <anki/util/Enum.h>
 
 namespace anki
 {
 
-namespace detail
-{
+/// @addtogroup renderer
+/// @{
 
 /// Dbg flags. Define them first so they can be parameter to the bitset
-enum class DbgFlag
+enum class DbgFlag : U16
 {
 	NONE = 0,
-	SPATIAL = 1 << 0,
-	FRUSTUMABLE = 1 << 1,
-	SECTOR = 1 << 2,
-	OCTREE = 1 << 3,
-	PHYSICS = 1 << 4,
-	ALL = SPATIAL | FRUSTUMABLE | SECTOR | OCTREE | PHYSICS
+	SPATIAL_COMPONENT = 1 << 0,
+	FRUSTUM_COMPONENT = 1 << 1,
+	SECTOR_COMPONENT = 1 << 2,
+	PHYSICS = 1 << 3,
+	ALL = SPATIAL_COMPONENT | FRUSTUM_COMPONENT | SECTOR_COMPONENT | PHYSICS
 };
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(DbgFlag, inline)
 
-} // end namespace detail
-
-/// @addtogroup renderer
-/// @{
-
 /// Debugging stage
-class Dbg : public RenderingPass, public Bitset<detail::DbgFlag>
+class Dbg : public RenderingPass
 {
 public:
-	using Flag = detail::DbgFlag;
-
 	Bool getEnabled() const
 	{
 		return m_enabled;
@@ -55,6 +46,21 @@ public:
 	void setDepthTestEnabled(Bool enable);
 	void switchDepthTestEnabled();
 
+	void setFlags(DbgFlag flags)
+	{
+		m_flags.set(flags);
+	}
+
+	void unsetFlags(DbgFlag flags)
+	{
+		m_flags.unset(flags);
+	}
+
+	void flipFlags(DbgFlag flags)
+	{
+		m_flags.flip(flags);
+	}
+
 anki_internal:
 	Dbg(Renderer* r);
 
@@ -68,8 +74,7 @@ private:
 	Bool m_enabled = false;
 	FramebufferPtr m_fb;
 	DebugDrawer* m_drawer = nullptr;
-	// Have it as ptr because the constructor calls opengl
-	SceneDebugDrawer* m_sceneDrawer = nullptr;
+	BitMask<DbgFlag> m_flags;
 };
 /// @}
 

+ 3 - 16
include/anki/renderer/DebugDrawer.h

@@ -178,22 +178,6 @@ public:
 	{
 	}
 
-	~SceneDebugDrawer()
-	{
-	}
-
-	void draw(SceneNode& node);
-
-	// void draw(const Sector& sector);
-
-	void setViewProjectionMatrix(const Mat4& m)
-	{
-		m_dbg->setViewProjectionMatrix(m);
-	}
-
-private:
-	DebugDrawer* m_dbg;
-
 	void draw(FrustumComponent& fr) const;
 
 	void draw(SpatialComponent& sp) const;
@@ -203,6 +187,9 @@ private:
 	void drawPath(const Path& path) const;
 
 	void draw(const ReflectionProxyComponent& proxy) const;
+
+private:
+	DebugDrawer* m_dbg;
 };
 /// @}
 

+ 34 - 33
include/anki/scene/FrustumComponent.h

@@ -9,7 +9,7 @@
 #include <anki/scene/SpatialComponent.h>
 #include <anki/scene/Common.h>
 #include <anki/scene/SceneComponent.h>
-#include <anki/util/Bitset.h>
+#include <anki/util/BitMask.h>
 
 namespace anki
 {
@@ -20,6 +20,24 @@ class VisibilityTestResults;
 /// @addtogroup scene
 /// @{
 
+/// Flags that affect visibility tests.
+enum class FrustumComponentVisibilityTestFlag : U8
+{
+	NONE = 0,
+	RENDER_COMPONENTS = 1 << 0,
+	LIGHT_COMPONENTS = 1 << 1,
+	LENS_FLARE_COMPONENTS = 1 << 2,
+	SHADOW_CASTERS = 1 << 3,
+	REFLECTION_PROBES = 1 << 4,
+	REFLECTION_PROXIES = 1 << 5,
+
+	ALL_TESTS = RENDER_COMPONENTS | LIGHT_COMPONENTS | LENS_FLARE_COMPONENTS
+		| SHADOW_CASTERS
+		| REFLECTION_PROBES
+		| REFLECTION_PROXIES
+};
+ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(FrustumComponentVisibilityTestFlag, inline)
+
 /// Frustum component interface for scene nodes. Useful for nodes that are
 /// frustums like cameras and lights
 class FrustumComponent : public SceneComponent
@@ -31,25 +49,6 @@ public:
 		U32 m_lightsCount = 0;
 	};
 
-	/// Flags that affect visibility tests.
-	enum class VisibilityTestFlag : U8
-	{
-		TEST_NONE = 0,
-		TEST_RENDER_COMPONENTS = 1 << 0,
-		TEST_LIGHT_COMPONENTS = 1 << 1,
-		TEST_LENS_FLARE_COMPONENTS = 1 << 2,
-		TEST_SHADOW_CASTERS = 1 << 3,
-		TEST_REFLECTION_PROBES = 1 << 4,
-		TEST_REFLECTION_PROXIES = 1 << 5,
-
-		ALL_TESTS = TEST_RENDER_COMPONENTS | TEST_LIGHT_COMPONENTS
-			| TEST_LENS_FLARE_COMPONENTS
-			| TEST_SHADOW_CASTERS
-			| TEST_REFLECTION_PROBES
-			| TEST_REFLECTION_PROXIES
-	};
-	ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(VisibilityTestFlag, friend)
-
 	/// Pass the frustum here so we can avoid the virtuals
 	FrustumComponent(SceneNode* node, Frustum* frustum);
 
@@ -124,13 +123,13 @@ public:
 	/// Call when the shape of the frustum got changed.
 	void markShapeForUpdate()
 	{
-		m_flags.enableBits(SHAPE_MARKED_FOR_UPDATE);
+		m_flags.set(SHAPE_MARKED_FOR_UPDATE);
 	}
 
 	/// Call when the transformation of the frustum got changed.
 	void markTransformForUpdate()
 	{
-		m_flags.enableBits(TRANSFORM_MARKED_FOR_UPDATE);
+		m_flags.set(TRANSFORM_MARKED_FOR_UPDATE);
 	}
 
 	/// Is a spatial inside the frustum?
@@ -150,17 +149,19 @@ public:
 	ANKI_USE_RESULT Error update(SceneNode&, F32, F32, Bool& updated) override;
 	/// @}
 
-	void setEnabledVisibilityTests(VisibilityTestFlag bits)
+	void setEnabledVisibilityTests(FrustumComponentVisibilityTestFlag bits)
 	{
-		m_flags.disableBits(VisibilityTestFlag::ALL_TESTS);
-		m_flags.enableBits(bits, true);
+		m_flags.unset(FrustumComponentVisibilityTestFlag::ALL_TESTS);
+		m_flags.set(bits, true);
 
 #if ANKI_ASSERTS_ENABLED
-		if(m_flags.bitsEnabled(VisibilityTestFlag::TEST_RENDER_COMPONENTS)
-			|| m_flags.bitsEnabled(VisibilityTestFlag::TEST_SHADOW_CASTERS))
+		if(m_flags.get(FrustumComponentVisibilityTestFlag::RENDER_COMPONENTS)
+			|| m_flags.get(FrustumComponentVisibilityTestFlag::SHADOW_CASTERS))
 		{
-			if(m_flags.bitsEnabled(VisibilityTestFlag::TEST_RENDER_COMPONENTS)
-				== m_flags.bitsEnabled(VisibilityTestFlag::TEST_SHADOW_CASTERS))
+			if(m_flags.get(
+				   FrustumComponentVisibilityTestFlag::RENDER_COMPONENTS)
+				== m_flags.get(
+					   FrustumComponentVisibilityTestFlag::SHADOW_CASTERS))
 			{
 				ANKI_ASSERT(0 && "Cannot have them both");
 			}
@@ -168,14 +169,14 @@ public:
 #endif
 	}
 
-	Bool visibilityTestsEnabled(VisibilityTestFlag bits) const
+	Bool visibilityTestsEnabled(FrustumComponentVisibilityTestFlag bits) const
 	{
-		return m_flags.bitsEnabled(bits);
+		return m_flags.get(bits);
 	}
 
 	Bool anyVisibilityTestEnabled() const
 	{
-		return m_flags.anyBitsEnabled(VisibilityTestFlag::ALL_TESTS);
+		return m_flags.getAny(FrustumComponentVisibilityTestFlag::ALL_TESTS);
 	}
 
 	static Bool classof(const SceneComponent& c)
@@ -203,7 +204,7 @@ private:
 	VisibilityTestResults* m_visible = nullptr;
 	VisibilityStats m_stats;
 
-	Bitset<U8> m_flags;
+	BitMask<U8> m_flags;
 
 	void computeProjectionParams();
 };

+ 7 - 6
include/anki/scene/MoveComponent.h

@@ -7,7 +7,7 @@
 
 #include <anki/scene/Common.h>
 #include <anki/scene/SceneComponent.h>
-#include <anki/util/Bitset.h>
+#include <anki/util/BitMask.h>
 #include <anki/util/Enum.h>
 #include <anki/Math.h>
 
@@ -33,11 +33,9 @@ enum class MoveComponentFlag : U8
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(MoveComponentFlag, inline)
 
 /// Interface for movable scene nodes
-class MoveComponent : public SceneComponent, public Bitset<MoveComponentFlag>
+class MoveComponent : public SceneComponent
 {
 public:
-	using Flag = MoveComponentFlag;
-
 	static Bool classof(const SceneComponent& c)
 	{
 		return c.getType() == Type::MOVE;
@@ -46,7 +44,8 @@ public:
 	/// The one and only constructor
 	/// @param node The scene node to steal it's allocators
 	/// @param flags The flags
-	MoveComponent(SceneNode* node, Flag flags = Flag::NONE);
+	MoveComponent(
+		SceneNode* node, MoveComponentFlag flags = MoveComponentFlag::NONE);
 
 	~MoveComponent();
 
@@ -181,9 +180,11 @@ private:
 	/// Keep the previous transformation for checking if it moved
 	Transform m_prevWTrf = Transform::getIdentity();
 
+	BitMask<MoveComponentFlag> m_flags;
+
 	void markForUpdate()
 	{
-		enableBits(Flag::MARKED_FOR_UPDATE);
+		m_flags.set(MoveComponentFlag::MARKED_FOR_UPDATE);
 	}
 
 	/// Called every frame. It updates the @a m_wtrf if @a shouldUpdateWTrf

+ 4 - 4
include/anki/scene/SceneComponent.h

@@ -8,7 +8,7 @@
 #include <anki/scene/Common.h>
 #include <anki/core/Timestamp.h>
 #include <anki/util/Functions.h>
-#include <anki/util/Bitset.h>
+#include <anki/util/BitMask.h>
 
 namespace anki
 {
@@ -86,12 +86,12 @@ public:
 
 	void setAutomaticCleanup(Bool enable)
 	{
-		m_flags.enableBits(AUTOMATIC_CLEANUP, enable);
+		m_flags.set(AUTOMATIC_CLEANUP, enable);
 	}
 
 	Bool getAutomaticCleanup() const
 	{
-		return m_flags.bitsEnabled(AUTOMATIC_CLEANUP);
+		return m_flags.get(AUTOMATIC_CLEANUP);
 	}
 
 	SceneNode& getSceneNode()
@@ -120,7 +120,7 @@ private:
 	};
 
 	Type m_type;
-	Bitset<U8> m_flags;
+	BitMask<U8> m_flags;
 };
 /// @}
 

+ 5 - 5
include/anki/scene/SceneNode.h

@@ -8,7 +8,7 @@
 #include <anki/scene/Common.h>
 #include <anki/util/Hierarchy.h>
 #include <anki/util/Rtti.h>
-#include <anki/util/Bitset.h>
+#include <anki/util/BitMask.h>
 #include <anki/util/List.h>
 #include <anki/util/Enum.h>
 #include <anki/scene/SceneComponent.h>
@@ -57,7 +57,7 @@ public:
 
 	Bool getMarkedForDeletion() const
 	{
-		return m_flags.bitsEnabled(Flag::MARKED_FOR_DELETION);
+		return m_flags.get(Flag::MARKED_FOR_DELETION);
 	}
 
 	void setMarkedForDeletion();
@@ -90,13 +90,13 @@ public:
 	/// Inform if a sector has visited this node.
 	void setSectorVisited(Bool visited)
 	{
-		m_flags.enableBits(Flag::SECTOR_VISITED, visited);
+		m_flags.set(Flag::SECTOR_VISITED, visited);
 	}
 
 	/// Check if a sector has visited this node.
 	Bool getSectorVisited() const
 	{
-		return m_flags.bitsEnabled(Flag::SECTOR_VISITED);
+		return m_flags.get(Flag::SECTOR_VISITED);
 	}
 
 	/// Iterate all components
@@ -205,7 +205,7 @@ private:
 	U8 m_componentsCount = 0;
 
 	String m_name; ///< A unique name
-	Bitset<Flag> m_flags;
+	BitMask<Flag> m_flags;
 
 	void cacheImportantComponents();
 };

+ 7 - 7
include/anki/scene/SpatialComponent.h

@@ -8,7 +8,7 @@
 #include <anki/scene/Common.h>
 #include <anki/scene/SceneComponent.h>
 #include <anki/Collision.h>
-#include <anki/util/Bitset.h>
+#include <anki/util/BitMask.h>
 #include <anki/util/Enum.h>
 #include <anki/util/List.h>
 
@@ -72,13 +72,13 @@ public:
 	/// Check if it's confined in a single sector.
 	Bool getSingleSector() const
 	{
-		return m_bits.bitsEnabled(Flag::SINGLE_SECTOR);
+		return m_flags.get(Flag::SINGLE_SECTOR);
 	}
 
 	/// Confine it or not in a single sector.
 	void setSingleSector(Bool yes)
 	{
-		m_bits.enableBits(Flag::SINGLE_SECTOR, yes);
+		m_flags.set(Flag::SINGLE_SECTOR, yes);
 	}
 
 	/// Used for sorting spatials. In most object the origin is the center of
@@ -98,19 +98,19 @@ public:
 	/// shape got updated
 	void markForUpdate()
 	{
-		m_bits.enableBits(Flag::MARKED_FOR_UPDATE);
+		m_flags.set(Flag::MARKED_FOR_UPDATE);
 	}
 
 	/// Set if visible by a camera
 	void setVisibleByCamera(Bool visible)
 	{
-		m_bits.enableBits(Flag::VISIBLE_CAMERA, visible);
+		m_flags.set(Flag::VISIBLE_CAMERA, visible);
 	}
 
 	/// Check if visible by camera
 	Bool getVisibleByCamera() const
 	{
-		return m_bits.bitsEnabled(Flag::VISIBLE_CAMERA);
+		return m_flags.get(Flag::VISIBLE_CAMERA);
 	}
 
 	/// @name SceneComponent overrides
@@ -132,7 +132,7 @@ private:
 	ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(Flag, friend)
 
 	const CollisionShape* m_shape;
-	Bitset<Flag> m_bits;
+	BitMask<Flag> m_flags;
 	Aabb m_aabb; ///< A faster shape
 	Vec4 m_origin = Vec4(MAX_F32, MAX_F32, MAX_F32, 0.0);
 	List<Sector*> m_sectorInfo;

+ 12 - 3
include/anki/script/ScriptManager.h

@@ -12,6 +12,7 @@ namespace anki
 
 // Forward
 class SceneGraph;
+class MainRenderer;
 
 /// @addtogroup script
 /// @{
@@ -38,16 +39,24 @@ anki_internal:
 	~ScriptManager();
 
 	/// Create the script manager.
-	ANKI_USE_RESULT Error create(
-		AllocAlignedCallback allocCb, void* allocCbData, SceneGraph* scene);
+	ANKI_USE_RESULT Error init(AllocAlignedCallback allocCb,
+		void* allocCbData,
+		SceneGraph* scene,
+		MainRenderer* renderer);
 
-	SceneGraph& _getSceneGraph()
+	SceneGraph& getSceneGraph()
 	{
 		return *m_scene;
 	}
 
+	MainRenderer& getMainRenderer()
+	{
+		return *m_r;
+	}
+
 private:
 	SceneGraph* m_scene = nullptr;
+	MainRenderer* m_r = nullptr;
 	ChainAllocator<U8> m_alloc;
 	LuaBinder m_lua;
 };

+ 5 - 5
include/anki/ui/Widget.h

@@ -7,7 +7,7 @@
 
 #include <anki/ui/UiObject.h>
 #include <anki/util/Hierarchy.h>
-#include <anki/util/Bitset.h>
+#include <anki/util/BitMask.h>
 
 namespace anki
 {
@@ -40,7 +40,7 @@ public:
 
 	Bool isMarkedForDeletion() const
 	{
-		return m_flags.bitsEnabled(MARKED_FOR_DELETION);
+		return m_flags.get(MARKED_FOR_DELETION);
 	}
 
 	virtual void paint()
@@ -91,12 +91,12 @@ public:
 #ifdef ANKI_BUILD
 	void markForRepaint()
 	{
-		m_flags.enableBits(NEEDS_REPAINT, true);
+		m_flags.set(NEEDS_REPAINT, true);
 	}
 
 	Bool isMarkedForRepaint() const
 	{
-		return m_flags.bitsEnabled(NEEDS_REPAINT);
+		return m_flags.get(NEEDS_REPAINT);
 	}
 #endif
 
@@ -114,7 +114,7 @@ private:
 	UVec2 m_posLocal = UVec2(0u); ///< Local space.
 	UVec2 m_posCanvas = UVec2(0u); ///< World space.
 
-	Bitset<U8> m_flags;
+	BitMask<U8> m_flags;
 };
 /// @}
 

+ 89 - 0
include/anki/util/BitMask.h

@@ -0,0 +1,89 @@
+// Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <anki/util/StdTypes.h>
+
+namespace anki
+{
+
+/// @addtogroup util_containers
+/// @{
+
+/// Easy bit mask manipulation.
+template<typename T>
+class BitMask
+{
+public:
+	using Value = T;
+
+	/// Default contructor. Will zero the mask.
+	BitMask()
+		: m_bitmask(static_cast<Value>(0))
+	{
+	}
+
+	/// Construcor.
+	/// @param mask The bits to enable.
+	template<typename TInt>
+	BitMask(TInt mask)
+		: m_bitmask(static_cast<Value>(mask))
+	{
+	}
+
+	/// Copy.
+	BitMask(const BitMask& b) = default;
+
+	/// Copy.
+	BitMask& operator=(const BitMask& b) = default;
+
+	/// Set or unset a bit at the given position.
+	template<typename TInt>
+	void set(TInt mask, Bool setBits = true)
+	{
+		Value maski = static_cast<Value>(mask);
+		m_bitmask = (setBits) ? (m_bitmask | maski) : (m_bitmask & ~maski);
+	}
+
+	/// Unset a bit (set to zero) at the given position.
+	template<typename TInt>
+	void unset(TInt mask)
+	{
+		Value maski = static_cast<Value>(mask);
+		m_bitmask &= ~maski;
+	}
+
+	/// Flip the bits at the given position. It will go from 1 to 0 or from 0 to
+	/// 1.
+	template<typename TInt>
+	void flip(TInt mask)
+	{
+		Value maski = static_cast<Value>(mask);
+		m_bitmask ^= maski;
+	}
+
+	/// Return true if the bit is set or false if it's not.
+	template<typename TInt>
+	Bool get(TInt mask) const
+	{
+		Value maski = static_cast<Value>(mask);
+		return (m_bitmask & maski) == maski;
+	}
+
+	/// Given a mask check if any are enabled.
+	template<typename TInt>
+	Bool getAny(TInt mask) const
+	{
+		Value maski = static_cast<Value>(mask);
+		return (m_bitmask & maski) != static_cast<Value>(0);
+	}
+
+protected:
+	Value m_bitmask;
+};
+/// @}
+
+} // end namespace anki

+ 139 - 0
include/anki/util/BitSet.h

@@ -0,0 +1,139 @@
+// Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <anki/util/StdTypes.h>
+#include <initializer_list>
+#include <cstring>
+
+namespace anki
+{
+
+/// @addtogroup util_containers
+/// @{
+
+/// Easy bit manipulation.
+/// @tparam N The number of bits.
+/// @tparam TChunkType The type of the chunks that the bitset consists. By
+///         default it's U8.
+template<U N, typename TChunkType = U8>
+class BitSet
+{
+public:
+	/// Constructor. It will set all the bits or unset them.
+	BitSet(Bool set)
+	{
+		memset(m_chunks, (set) ? 0xFF : 0, sizeof(m_chunks));
+	}
+
+	/// Set or unset a bit at the given position.
+	template<typename TInt>
+	void set(TInt pos, Bool setBits = true)
+	{
+		U high, low;
+		position(static_cast<U>(pos), high, low);
+		ChunkType mask = MASK >> low;
+		m_chunks[high] =
+			(setBits) ? (m_chunks[high] | mask) : (m_chunks[high] & ~mask);
+	}
+
+	/// Set multiple bits.
+	template<typename TInt>
+	void set(std::initializer_list<TInt> list, Bool setBits = true)
+	{
+		for(auto it : list)
+		{
+			set(it, setBits);
+		}
+	}
+
+	/// Set all bits.
+	void setAll()
+	{
+		memset(m_chunks, 0xFF, sizeof(m_chunks));
+	}
+
+	/// Unset a bit (set to zero) at the given position.
+	template<typename TInt>
+	void unset(TInt pos)
+	{
+		set(pos, false);
+	}
+
+	/// Unset multiple bits.
+	template<typename TInt>
+	void unset(std::initializer_list<TInt> list)
+	{
+		set(list, false);
+	}
+
+	/// Unset all bits.
+	void unsetAll()
+	{
+		memset(m_chunks, 0, sizeof(m_chunks));
+	}
+
+	/// Flip the bits at the given position. It will go from 1 to 0 or from 0 to
+	/// 1.
+	template<typename TInt>
+	void flip(TInt pos)
+	{
+		U high, low;
+		position(static_cast<U>(pos), high, low);
+		ChunkType mask = MASK >> low;
+		m_chunks[high] ^= mask;
+	}
+
+	/// Return true if the bit is set or false if it's not.
+	template<typename TInt>
+	Bool get(TInt pos) const
+	{
+		U high, low;
+		position(static_cast<U>(pos), high, low);
+		ChunkType mask = MASK >> low;
+		return (m_chunks[high] & mask) != 0;
+	}
+
+	/// Any are enabled.
+	Bool getAny() const
+	{
+		for(U i = 0; i < CHUNK_COUNT; ++i)
+		{
+			if(m_chunks[i] != 0)
+			{
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+protected:
+	using ChunkType = TChunkType;
+
+	/// Number of bits a chunk holds.
+	static const U CHUNK_BIT_COUNT = sizeof(ChunkType) * 8;
+
+	/// Number of chunks.
+	static const U CHUNK_COUNT = (N + (CHUNK_BIT_COUNT - 1)) / CHUNK_BIT_COUNT;
+
+	/// A mask for some stuff.
+	static const U MASK = 1 << (CHUNK_BIT_COUNT - 1);
+
+	ChunkType m_chunks[CHUNK_COUNT];
+
+	static void position(U bit, U& high, U& low)
+	{
+		ANKI_ASSERT(bit < N);
+		high = bit / CHUNK_BIT_COUNT;
+		low = bit % CHUNK_BIT_COUNT;
+		ANKI_ASSERT(high < CHUNK_COUNT);
+		ANKI_ASSERT(low < CHUNK_BIT_COUNT);
+	}
+};
+/// @}
+
+} // end namespace anki

+ 0 - 88
include/anki/util/Bitset.h

@@ -1,88 +0,0 @@
-// Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <anki/util/StdTypes.h>
-
-namespace anki
-{
-
-/// @addtogroup util_containers
-/// @{
-
-/// Easy bit manipulation.
-template<typename T>
-class Bitset
-{
-public:
-	using Value = T;
-
-	Bitset()
-		: m_bitmask(static_cast<Value>(0))
-	{
-	}
-
-	Bitset(Value bitmask)
-		: m_bitmask(bitmask)
-	{
-	}
-
-	/// @name Bits manipulation
-	/// @{
-	template<typename Y>
-	void enableBits(Y mask)
-	{
-		Value maski = static_cast<Value>(mask);
-		m_bitmask |= maski;
-	}
-
-	template<typename Y>
-	void enableBits(Y mask, Bool enable)
-	{
-		Value maski = static_cast<Value>(mask);
-		m_bitmask = (enable) ? (m_bitmask | maski) : (m_bitmask & ~maski);
-	}
-
-	template<typename Y>
-	void disableBits(Y mask)
-	{
-		Value maski = static_cast<Value>(mask);
-		m_bitmask &= ~maski;
-	}
-
-	template<typename Y>
-	void switchBits(Y mask)
-	{
-		Value maski = static_cast<Value>(mask);
-		m_bitmask ^= maski;
-	}
-
-	template<typename Y>
-	Bool bitsEnabled(Y mask) const
-	{
-		Value maski = static_cast<Value>(mask);
-		return (m_bitmask & maski) == maski;
-	}
-
-	template<typename Y>
-	Bool anyBitsEnabled(Y mask) const
-	{
-		Value maski = static_cast<Value>(mask);
-		return (m_bitmask & maski) != static_cast<Value>(0);
-	}
-
-	Value getBitmask() const
-	{
-		return m_bitmask;
-	}
-	/// @}
-
-protected:
-	Value m_bitmask;
-};
-/// @}
-
-} // end namespace anki

+ 1 - 1
src/core/App.cpp

@@ -291,7 +291,7 @@ Error App::createInternal(const ConfigSet& config_,
 	//
 	m_script = m_heapAlloc.newInstance<ScriptManager>();
 
-	ANKI_CHECK(m_script->create(m_allocCb, m_allocCbData, m_scene));
+	ANKI_CHECK(m_script->init(m_allocCb, m_allocCbData, m_scene, m_renderer));
 
 	ANKI_LOGI("Application initialized");
 	return ErrorCode::NONE;

+ 44 - 18
src/renderer/Dbg.cpp

@@ -8,9 +8,11 @@
 #include <anki/renderer/Ms.h>
 #include <anki/renderer/Is.h>
 #include <anki/renderer/Pps.h>
+#include <anki/renderer/DebugDrawer.h>
 #include <anki/resource/ShaderResource.h>
 #include <anki/scene/SceneGraph.h>
 #include <anki/scene/FrustumComponent.h>
+#include <anki/scene/MoveComponent.h>
 #include <anki/scene/Sector.h>
 #include <anki/scene/Light.h>
 #include <anki/util/Logger.h>
@@ -36,18 +38,13 @@ Dbg::~Dbg()
 	{
 		getAllocator().deleteInstance(m_drawer);
 	}
-
-	if(m_sceneDrawer != nullptr)
-	{
-		getAllocator().deleteInstance(m_sceneDrawer);
-	}
 }
 
 //==============================================================================
 Error Dbg::init(const ConfigSet& initializer)
 {
 	m_enabled = initializer.getNumber("dbg.enabled");
-	enableBits(Flag::ALL);
+	m_flags.set(DbgFlag::ALL);
 
 	// Chose the correct color FAI
 	FramebufferInitInfo fbInit;
@@ -71,8 +68,6 @@ Error Dbg::init(const ConfigSet& initializer)
 	m_drawer = getAllocator().newInstance<DebugDrawer>();
 	ANKI_CHECK(m_drawer->create(m_r));
 
-	m_sceneDrawer = getAllocator().newInstance<SceneDebugDrawer>(m_drawer);
-
 	getGrManager().finish();
 	return ErrorCode::NONE;
 }
@@ -96,31 +91,62 @@ Error Dbg::run(RenderingContext& ctx)
 
 	SceneGraph& scene = cam.getSceneGraph();
 
+	SceneDebugDrawer sceneDrawer(m_drawer);
 	err = scene.iterateSceneNodes([&](SceneNode& node) -> Error {
-		SpatialComponent* sp = node.tryGetComponent<SpatialComponent>();
-
-		if(&cam.getComponent<SpatialComponent>() == sp)
+		if(&node == &cam)
 		{
 			return ErrorCode::NONE;
 		}
 
-		if(bitsEnabled(Flag::SPATIAL) && sp)
+		// Set position
+		MoveComponent* mv = node.tryGetComponent<MoveComponent>();
+		if(mv)
+		{
+			m_drawer->setModelMatrix(Mat4(mv->getWorldTransform()));
+		}
+		else
 		{
-			m_sceneDrawer->draw(node);
+			m_drawer->setModelMatrix(Mat4::getIdentity());
 		}
 
-		if(bitsEnabled(Flag::SECTOR)
-			&& node.tryGetComponent<PortalSectorComponent>())
+		// Spatial
+		if(m_flags.get(DbgFlag::SPATIAL_COMPONENT))
 		{
-			m_sceneDrawer->draw(node);
+			Error err = node.iterateComponentsOfType<SpatialComponent>(
+				[&](SpatialComponent& sp) -> Error {
+					sceneDrawer.draw(sp);
+					return ErrorCode::NONE;
+				});
+			(void)err;
+		}
+
+		// Frustum
+		if(m_flags.get(DbgFlag::FRUSTUM_COMPONENT))
+		{
+			Error err = node.iterateComponentsOfType<FrustumComponent>(
+				[&](FrustumComponent& frc) -> Error {
+					sceneDrawer.draw(frc);
+					return ErrorCode::NONE;
+				});
+			(void)err;
+		}
+
+		// Sector/portal
+		if(m_flags.get(DbgFlag::SECTOR_COMPONENT))
+		{
+			Error err = node.iterateComponentsOfType<PortalSectorComponent>(
+				[&](PortalSectorComponent& psc) -> Error {
+					sceneDrawer.draw(psc);
+					return ErrorCode::NONE;
+				});
+			(void)err;
 		}
 
 		return ErrorCode::NONE;
 	});
-
 	(void)err;
 
-	if(0)
+	if(m_flags.get(DbgFlag::PHYSICS))
 	{
 		PhysicsDebugDrawer phyd(m_drawer);
 

+ 0 - 40
src/renderer/DebugDrawer.cpp

@@ -525,46 +525,6 @@ void PhysicsDebugDrawer::drawLines(
 // SceneDebugDrawer                                                            =
 //==============================================================================
 
-//==============================================================================
-void SceneDebugDrawer::draw(SceneNode& node)
-{
-	MoveComponent* mv = node.tryGetComponent<MoveComponent>();
-	if(mv)
-	{
-		m_dbg->setModelMatrix(Mat4(mv->getWorldTransform()));
-	}
-	else
-	{
-		m_dbg->setModelMatrix(Mat4::getIdentity());
-	}
-
-	FrustumComponent* fr = node.tryGetComponent<FrustumComponent>();
-	if(fr)
-	{
-		draw(*fr);
-	}
-
-	Error err = node.iterateComponentsOfType<SpatialComponent>(
-		[&](SpatialComponent& sp) -> Error {
-			draw(sp);
-			return ErrorCode::NONE;
-		});
-	(void)err;
-
-	PortalSectorComponent* ps = node.tryGetComponent<PortalSectorComponent>();
-	if(ps)
-	{
-		draw(*ps);
-	}
-
-	ReflectionProxyComponent* proxy =
-		node.tryGetComponent<ReflectionProxyComponent>();
-	if(proxy)
-	{
-		draw(*proxy);
-	}
-}
-
 //==============================================================================
 void SceneDebugDrawer::draw(FrustumComponent& fr) const
 {

+ 5 - 5
src/scene/Camera.cpp

@@ -94,11 +94,11 @@ Error Camera::create(const CString& name, Frustum* frustum)
 	FrustumComponent* frc =
 		getSceneAllocator().newInstance<FrustumComponent>(this, frustum);
 	frc->setEnabledVisibilityTests(
-		FrustumComponent::VisibilityTestFlag::TEST_RENDER_COMPONENTS
-		| FrustumComponent::VisibilityTestFlag::TEST_LIGHT_COMPONENTS
-		| FrustumComponent::VisibilityTestFlag::TEST_LENS_FLARE_COMPONENTS
-		| FrustumComponent::VisibilityTestFlag::TEST_REFLECTION_PROBES
-		| FrustumComponent::VisibilityTestFlag::TEST_REFLECTION_PROXIES);
+		FrustumComponentVisibilityTestFlag::RENDER_COMPONENTS
+		| FrustumComponentVisibilityTestFlag::LIGHT_COMPONENTS
+		| FrustumComponentVisibilityTestFlag::LENS_FLARE_COMPONENTS
+		| FrustumComponentVisibilityTestFlag::REFLECTION_PROBES
+		| FrustumComponentVisibilityTestFlag::REFLECTION_PROXIES);
 	addComponent(frc, true);
 
 	// Feedback component #2

+ 4 - 5
src/scene/FrustumComponent.cpp

@@ -21,7 +21,7 @@ FrustumComponent::FrustumComponent(SceneNode* node, Frustum* frustum)
 	markShapeForUpdate();
 	markTransformForUpdate();
 
-	setEnabledVisibilityTests(VisibilityTestFlag::TEST_NONE);
+	setEnabledVisibilityTests(FrustumComponentVisibilityTestFlag::NONE);
 }
 
 //==============================================================================
@@ -43,14 +43,14 @@ Error FrustumComponent::update(SceneNode& node, F32, F32, Bool& updated)
 
 	updated = false;
 
-	if(m_flags.bitsEnabled(SHAPE_MARKED_FOR_UPDATE))
+	if(m_flags.get(SHAPE_MARKED_FOR_UPDATE))
 	{
 		updated = true;
 		m_pm = m_frustum->calculateProjectionMatrix();
 		computeProjectionParams();
 	}
 
-	if(m_flags.bitsEnabled(TRANSFORM_MARKED_FOR_UPDATE))
+	if(m_flags.get(TRANSFORM_MARKED_FOR_UPDATE))
 	{
 		updated = true;
 		m_vm = Mat4(m_frustum->getTransform().getInverse());
@@ -59,8 +59,7 @@ Error FrustumComponent::update(SceneNode& node, F32, F32, Bool& updated)
 	if(updated)
 	{
 		m_vpm = m_pm * m_vm;
-		m_flags.disableBits(
-			SHAPE_MARKED_FOR_UPDATE | TRANSFORM_MARKED_FOR_UPDATE);
+		m_flags.unset(SHAPE_MARKED_FOR_UPDATE | TRANSFORM_MARKED_FOR_UPDATE);
 	}
 
 	return ErrorCode::NONE;

+ 3 - 4
src/scene/Light.cpp

@@ -102,12 +102,12 @@ void Light::frameUpdateCommon()
 			if(castsShadow)
 			{
 				frc.setEnabledVisibilityTests(
-					FrustumComponent::VisibilityTestFlag::TEST_SHADOW_CASTERS);
+					FrustumComponentVisibilityTestFlag::SHADOW_CASTERS);
 			}
 			else
 			{
 				frc.setEnabledVisibilityTests(
-					FrustumComponent::VisibilityTestFlag::TEST_NONE);
+					FrustumComponentVisibilityTestFlag::NONE);
 			}
 
 			return ErrorCode::NONE;
@@ -296,8 +296,7 @@ Error SpotLight::create(const CString& name)
 
 	FrustumComponent* fr =
 		getSceneAllocator().newInstance<FrustumComponent>(this, &m_frustum);
-	fr->setEnabledVisibilityTests(
-		FrustumComponent::VisibilityTestFlag::TEST_NONE);
+	fr->setEnabledVisibilityTests(FrustumComponentVisibilityTestFlag::NONE);
 
 	addComponent(fr, true);
 

+ 6 - 6
src/scene/MoveComponent.cpp

@@ -10,9 +10,9 @@ namespace anki
 {
 
 //==============================================================================
-MoveComponent::MoveComponent(SceneNode* node, Flag flags)
+MoveComponent::MoveComponent(SceneNode* node, MoveComponentFlag flags)
 	: SceneComponent(Type::MOVE, node)
-	, Bitset<Flag>(flags)
+	, m_flags(flags)
 {
 	markForUpdate();
 }
@@ -33,7 +33,7 @@ Error MoveComponent::update(SceneNode& node, F32, F32, Bool& updated)
 Bool MoveComponent::updateWorldTransform(SceneNode& node)
 {
 	m_prevWTrf = m_wtrf;
-	const Bool dirty = bitsEnabled(Flag::MARKED_FOR_UPDATE);
+	const Bool dirty = m_flags.get(MoveComponentFlag::MARKED_FOR_UPDATE);
 
 	// If dirty then update world transform
 	if(dirty)
@@ -50,11 +50,11 @@ Bool MoveComponent::updateWorldTransform(SceneNode& node)
 				// Parent not movable
 				m_wtrf = m_ltrf;
 			}
-			else if(bitsEnabled(Flag::IGNORE_PARENT_TRANSFORM))
+			else if(m_flags.get(MoveComponentFlag::IGNORE_PARENT_TRANSFORM))
 			{
 				m_wtrf = m_ltrf;
 			}
-			else if(bitsEnabled(Flag::IGNORE_LOCAL_TRANSFORM))
+			else if(m_flags.get(MoveComponentFlag::IGNORE_LOCAL_TRANSFORM))
 			{
 				m_wtrf = parentMove->getWorldTransform();
 			}
@@ -72,7 +72,7 @@ Bool MoveComponent::updateWorldTransform(SceneNode& node)
 		}
 
 		// Now it's a good time to cleanse parent
-		disableBits(Flag::MARKED_FOR_UPDATE);
+		m_flags.unset(MoveComponentFlag::MARKED_FOR_UPDATE);
 	}
 
 	// If this is dirty then make children dirty as well. Don't walk the

+ 6 - 7
src/scene/ReflectionProbe.cpp

@@ -18,9 +18,9 @@ namespace anki
 // Misc                                                                        =
 //==============================================================================
 
-const FrustumComponent::VisibilityTestFlag FRUSTUM_TEST_FLAGS =
-	FrustumComponent::VisibilityTestFlag::TEST_RENDER_COMPONENTS
-	| FrustumComponent::VisibilityTestFlag::TEST_LIGHT_COMPONENTS;
+const FrustumComponentVisibilityTestFlag FRUSTUM_TEST_FLAGS =
+	FrustumComponentVisibilityTestFlag::RENDER_COMPONENTS
+	| FrustumComponentVisibilityTestFlag::LIGHT_COMPONENTS;
 
 /// Feedback component
 class ReflectionProbeMoveFeedbackComponent : public SceneComponent
@@ -106,7 +106,7 @@ Error ReflectionProbe::create(const CString& name, F32 radius)
 				this, &m_cubeSides[i].m_frustum);
 
 		frc->setEnabledVisibilityTests(
-			FrustumComponent::VisibilityTestFlag::TEST_NONE);
+			FrustumComponentVisibilityTestFlag::NONE);
 
 		addComponent(frc, true);
 	}
@@ -166,10 +166,9 @@ Error ReflectionProbe::frameUpdate(F32 prevUpdateTime, F32 crntTime)
 	const ReflectionProbeComponent& reflc =
 		getComponent<ReflectionProbeComponent>();
 
-	FrustumComponent::VisibilityTestFlag testFlags =
-		reflc.getMarkedForRendering()
+	FrustumComponentVisibilityTestFlag testFlags = reflc.getMarkedForRendering()
 		? FRUSTUM_TEST_FLAGS
-		: FrustumComponent::VisibilityTestFlag::TEST_NONE;
+		: FrustumComponentVisibilityTestFlag::NONE;
 
 	Error err = iterateComponentsOfType<FrustumComponent>(
 		[testFlags](FrustumComponent& frc) -> Error {

+ 1 - 1
src/scene/SceneNode.cpp

@@ -50,7 +50,7 @@ void SceneNode::setMarkedForDeletion()
 	// want to increase the counter again
 	if(!getMarkedForDeletion())
 	{
-		m_flags.enableBits(Flag::MARKED_FOR_DELETION);
+		m_flags.set(Flag::MARKED_FOR_DELETION);
 		m_scene->increaseObjectsMarkedForDeletion();
 	}
 

+ 3 - 3
src/scene/SpatialComponent.cpp

@@ -29,14 +29,14 @@ SpatialComponent::~SpatialComponent()
 //==============================================================================
 Error SpatialComponent::update(SceneNode&, F32, F32, Bool& updated)
 {
-	m_bits.disableBits(Flag::VISIBLE_ANY);
+	m_flags.unset(Flag::VISIBLE_ANY);
 
-	updated = m_bits.bitsEnabled(Flag::MARKED_FOR_UPDATE);
+	updated = m_flags.get(Flag::MARKED_FOR_UPDATE);
 	if(updated)
 	{
 		m_shape->computeAabb(m_aabb);
 		getSceneGraph().getSectorGroup().spatialUpdated(this);
-		m_bits.disableBits(Flag::MARKED_FOR_UPDATE);
+		m_flags.unset(Flag::MARKED_FOR_UPDATE);
 	}
 
 	return ErrorCode::NONE;

+ 6 - 6
src/scene/Visibility.cpp

@@ -216,22 +216,22 @@ void VisibilityTestTask::test(
 	List<SceneNode*> frustumsList;
 
 	Bool wantsRenderComponents = testedFrc.visibilityTestsEnabled(
-		FrustumComponent::VisibilityTestFlag::TEST_RENDER_COMPONENTS);
+		FrustumComponentVisibilityTestFlag::RENDER_COMPONENTS);
 
 	Bool wantsLightComponents = testedFrc.visibilityTestsEnabled(
-		FrustumComponent::VisibilityTestFlag::TEST_LIGHT_COMPONENTS);
+		FrustumComponentVisibilityTestFlag::LIGHT_COMPONENTS);
 
 	Bool wantsFlareComponents = testedFrc.visibilityTestsEnabled(
-		FrustumComponent::VisibilityTestFlag::TEST_LENS_FLARE_COMPONENTS);
+		FrustumComponentVisibilityTestFlag::LENS_FLARE_COMPONENTS);
 
 	Bool wantsShadowCasters = testedFrc.visibilityTestsEnabled(
-		FrustumComponent::VisibilityTestFlag::TEST_SHADOW_CASTERS);
+		FrustumComponentVisibilityTestFlag::SHADOW_CASTERS);
 
 	Bool wantsReflectionProbes = testedFrc.visibilityTestsEnabled(
-		FrustumComponent::VisibilityTestFlag::TEST_REFLECTION_PROBES);
+		FrustumComponentVisibilityTestFlag::REFLECTION_PROBES);
 
 	Bool wantsReflectionProxies = testedFrc.visibilityTestsEnabled(
-		FrustumComponent::VisibilityTestFlag::TEST_REFLECTION_PROXIES);
+		FrustumComponentVisibilityTestFlag::REFLECTION_PROXIES);
 
 #if 0
 	ANKI_LOGW("Running test code");

+ 1 - 1
src/script/Event.cpp

@@ -22,7 +22,7 @@ static EventManager* getEventManager(lua_State* l)
 	ScriptManager* scriptManager =
 		reinterpret_cast<ScriptManager*>(binder->getParent());
 
-	return &scriptManager->_getSceneGraph().getEventManager();
+	return &scriptManager->getSceneGraph().getEventManager();
 }
 
 //==============================================================================

+ 1 - 1
src/script/Event.xml

@@ -22,7 +22,7 @@ static EventManager* getEventManager(lua_State* l)
 	ScriptManager* scriptManager =
 		reinterpret_cast<ScriptManager*>(binder->getParent());
 
-	return &scriptManager->_getSceneGraph().getEventManager();
+	return &scriptManager->getSceneGraph().getEventManager();
 }]]></head>
 
 	<classes>

+ 44 - 0
src/script/Math.cpp

@@ -4497,6 +4497,49 @@ static inline void wrapTransform(lua_State* l)
 	lua_settop(l, 0);
 }
 
+//==============================================================================
+/// Pre-wrap function toRad.
+static inline int pwraptoRad(lua_State* l)
+{
+	UserData* ud;
+	(void)ud;
+	void* voidp;
+	(void)voidp;
+	PtrSize size;
+	(void)size;
+
+	LuaBinder::checkArgsCount(l, 1);
+
+	// Pop arguments
+	F32 arg0;
+	if(LuaBinder::checkNumber(l, 1, arg0))
+	{
+		return -1;
+	}
+
+	// Call the function
+	F32 ret = toRad(arg0);
+
+	// Push return value
+	lua_pushnumber(l, ret);
+
+	return 1;
+}
+
+//==============================================================================
+/// Wrap function toRad.
+static int wraptoRad(lua_State* l)
+{
+	int res = pwraptoRad(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
 //==============================================================================
 /// Wrap the module.
 void wrapModuleMath(lua_State* l)
@@ -4507,6 +4550,7 @@ void wrapModuleMath(lua_State* l)
 	wrapMat3(l);
 	wrapMat3x4(l);
 	wrapTransform(l);
+	LuaBinder::pushLuaCFunc(l, "toRad", wraptoRad);
 }
 
 } // end namespace anki

+ 9 - 1
src/script/Math.xml

@@ -465,7 +465,15 @@ namespace anki {]]></head>
 			</methods>
 		</class>
 	</classes>
-
+	<functions>
+		<function name="toRad">
+			<overrideCall>F32 ret = toRad(arg0);</overrideCall>
+			<args>
+				<arg>F32</arg>
+			</args>
+			<return>F32</return>
+		</function>
+	</functions>
 	<tail><![CDATA[} // end namespace anki]]></tail>
 </glue>
 

+ 134 - 0
src/script/Renderer.cpp

@@ -6,11 +6,24 @@
 // WARNING: The file is auto generated.
 
 #include <anki/script/LuaBinder.h>
+#include <anki/script/ScriptManager.h>
 #include <anki/Renderer.h>
 
 namespace anki
 {
 
+//==============================================================================
+static MainRenderer* getMainRenderer(lua_State* l)
+{
+	LuaBinder* binder = nullptr;
+	lua_getallocf(l, reinterpret_cast<void**>(&binder));
+
+	ScriptManager* scriptManager =
+		reinterpret_cast<ScriptManager*>(binder->getParent());
+
+	return &scriptManager->getMainRenderer();
+}
+
 //==============================================================================
 // Dbg                                                                         =
 //==============================================================================
@@ -132,11 +145,132 @@ static inline void wrapDbg(lua_State* l)
 	lua_settop(l, 0);
 }
 
+//==============================================================================
+// MainRenderer                                                                =
+//==============================================================================
+
+//==============================================================================
+static const char* classnameMainRenderer = "MainRenderer";
+
+template<>
+I64 LuaBinder::getWrappedTypeSignature<MainRenderer>()
+{
+	return 919289102518575326;
+}
+
+template<>
+const char* LuaBinder::getWrappedTypeName<MainRenderer>()
+{
+	return classnameMainRenderer;
+}
+
+//==============================================================================
+/// Pre-wrap method MainRenderer::getAspectRatio.
+static inline int pwrapMainRenderergetAspectRatio(lua_State* l)
+{
+	UserData* ud;
+	(void)ud;
+	void* voidp;
+	(void)voidp;
+	PtrSize size;
+	(void)size;
+
+	LuaBinder::checkArgsCount(l, 1);
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(
+		   l, 1, classnameMainRenderer, 919289102518575326, ud))
+	{
+		return -1;
+	}
+
+	MainRenderer* self = ud->getData<MainRenderer>();
+
+	// Call the method
+	F32 ret = self->getAspectRatio();
+
+	// Push return value
+	lua_pushnumber(l, ret);
+
+	return 1;
+}
+
+//==============================================================================
+/// Wrap method MainRenderer::getAspectRatio.
+static int wrapMainRenderergetAspectRatio(lua_State* l)
+{
+	int res = pwrapMainRenderergetAspectRatio(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
+//==============================================================================
+/// Wrap class MainRenderer.
+static inline void wrapMainRenderer(lua_State* l)
+{
+	LuaBinder::createClass(l, classnameMainRenderer);
+	LuaBinder::pushLuaCFuncMethod(
+		l, "getAspectRatio", wrapMainRenderergetAspectRatio);
+	lua_settop(l, 0);
+}
+
+//==============================================================================
+/// Pre-wrap function getMainRenderer.
+static inline int pwrapgetMainRenderer(lua_State* l)
+{
+	UserData* ud;
+	(void)ud;
+	void* voidp;
+	(void)voidp;
+	PtrSize size;
+	(void)size;
+
+	LuaBinder::checkArgsCount(l, 0);
+
+	// Call the function
+	MainRenderer* ret = getMainRenderer(l);
+
+	// Push return value
+	if(ANKI_UNLIKELY(ret == nullptr))
+	{
+		lua_pushstring(l, "Glue code returned nullptr");
+		return -1;
+	}
+
+	voidp = lua_newuserdata(l, sizeof(UserData));
+	ud = static_cast<UserData*>(voidp);
+	luaL_setmetatable(l, "MainRenderer");
+	ud->initPointed(919289102518575326, const_cast<MainRenderer*>(ret));
+
+	return 1;
+}
+
+//==============================================================================
+/// Wrap function getMainRenderer.
+static int wrapgetMainRenderer(lua_State* l)
+{
+	int res = pwrapgetMainRenderer(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
 //==============================================================================
 /// Wrap the module.
 void wrapModuleRenderer(lua_State* l)
 {
 	wrapDbg(l);
+	wrapMainRenderer(l);
+	LuaBinder::pushLuaCFunc(l, "getMainRenderer", wrapgetMainRenderer);
 }
 
 } // end namespace anki

+ 28 - 2
src/script/Renderer.xml

@@ -7,9 +7,23 @@
 // WARNING: The file is auto generated.
 
 #include <anki/script/LuaBinder.h>
+#include <anki/script/ScriptManager.h>
 #include <anki/Renderer.h>
 
-namespace anki {]]></head>
+namespace anki {
+	
+//==============================================================================
+static MainRenderer* getMainRenderer(lua_State* l)
+{
+	LuaBinder* binder = nullptr;
+	lua_getallocf(l, reinterpret_cast<void**>(&binder));
+
+	ScriptManager* scriptManager =
+		reinterpret_cast<ScriptManager*>(binder->getParent());
+
+	return &scriptManager->getMainRenderer();
+}	
+]]></head>
 
 	<classes>
 		<class name="Dbg">
@@ -24,8 +38,20 @@ namespace anki {]]></head>
 				</method>
 			</methods>
 		</class>
+		<class name="MainRenderer">
+			<methods>
+				<method name="getAspectRatio">
+					<return>F32</return>
+				</method>
+			</methods>
+		</class>
 	</classes>
-
+	<functions>
+		<function name="getMainRenderer">
+			<overrideCall>MainRenderer* ret = getMainRenderer(l);</overrideCall>
+			<return>MainRenderer*</return>
+		</function>
+	</functions>
 	<tail><![CDATA[} // end namespace anki]]></tail>
 </glue>
 

+ 1 - 1
src/script/Scene.cpp

@@ -38,7 +38,7 @@ static SceneGraph* getSceneGraph(lua_State* l)
 	ScriptManager* scriptManager =
 		reinterpret_cast<ScriptManager*>(binder->getParent());
 
-	return &scriptManager->_getSceneGraph();
+	return &scriptManager->getSceneGraph();
 }
 
 //==============================================================================

+ 1 - 3
src/script/Scene.xml

@@ -39,7 +39,7 @@ static SceneGraph* getSceneGraph(lua_State* l)
 	ScriptManager* scriptManager =
 		reinterpret_cast<ScriptManager*>(binder->getParent());
 
-	return &scriptManager->_getSceneGraph();
+	return &scriptManager->getSceneGraph();
 }]]></head>
 
 	<classes>
@@ -356,14 +356,12 @@ static SceneGraph* getSceneGraph(lua_State* l)
 			</methods>
 		</class>
 	</classes>
-
 	<functions>
 		<function name="getSceneGraph">
 			<overrideCall>SceneGraph* ret = getSceneGraph(l);</overrideCall>
 			<return>SceneGraph*</return>
 		</function>
 	</functions>
-
 	<tail><![CDATA[} // end namespace anki]]></tail>
 </glue>
 

+ 13 - 11
src/script/ScriptManager.cpp

@@ -6,10 +6,6 @@
 #include <anki/script/ScriptManager.h>
 #include <anki/util/Logger.h>
 
-#define ANKI_SCRIPT_CALL_WRAP(x_)                                              \
-	extern void wrapModule##x_(lua_State*);                                    \
-	wrapModule##x_(l);
-
 namespace anki
 {
 
@@ -25,28 +21,34 @@ ScriptManager::~ScriptManager()
 }
 
 //==============================================================================
-Error ScriptManager::create(
-	AllocAlignedCallback allocCb, void* allocCbData, SceneGraph* scene)
+Error ScriptManager::init(AllocAlignedCallback allocCb,
+	void* allocCbData,
+	SceneGraph* scene,
+	MainRenderer* renderer)
 {
 	ANKI_LOGI("Initializing scripting engine...");
 
 	m_scene = scene;
+	m_r = renderer;
 	m_alloc = ChainAllocator<U8>(allocCb, allocCbData, 1024, 1.0, 0);
 
-	Error err = m_lua.create(m_alloc, this);
-	if(err)
-		return err;
+	ANKI_CHECK(m_lua.create(m_alloc, this));
 
 	// Wrap stuff
 	lua_State* l = m_lua.getLuaState();
 
+#define ANKI_SCRIPT_CALL_WRAP(x_)                                              \
+	extern void wrapModule##x_(lua_State*);                                    \
+	wrapModule##x_(l);
+
 	ANKI_SCRIPT_CALL_WRAP(Math);
 	ANKI_SCRIPT_CALL_WRAP(Renderer);
 	ANKI_SCRIPT_CALL_WRAP(Scene);
 	ANKI_SCRIPT_CALL_WRAP(Event);
 
-	ANKI_LOGI("Scripting engine initialized");
-	return err;
+#undef ANKI_SCRIPT_CALL_WRAP
+
+	return ErrorCode::NONE;
 }
 
 } // end namespace anki

+ 1 - 1
src/ui/Widget.cpp

@@ -28,7 +28,7 @@ void Widget::markForDeletion()
 {
 	if(!isMarkedForDeletion())
 	{
-		m_flags.enableBits(MARKED_FOR_DELETION);
+		m_flags.set(MARKED_FOR_DELETION);
 		getCanvas().getMarkedForDeletionCount().fetchAdd(1);
 	}
 

+ 3 - 7
testapp/Main.cpp

@@ -128,19 +128,15 @@ Error MyApp::userMainLoop(Bool& quit)
 	}
 	if(in.getKey(KeyCode::F2) == 1)
 	{
-		renderer.getDbg().switchBits(Dbg::Flag::SPATIAL);
+		renderer.getDbg().flipFlags(DbgFlag::SPATIAL_COMPONENT);
 	}
 	if(in.getKey(KeyCode::F3) == 1)
 	{
-		renderer.getDbg().switchBits(Dbg::Flag::PHYSICS);
+		renderer.getDbg().flipFlags(DbgFlag::PHYSICS);
 	}
 	if(in.getKey(KeyCode::F4) == 1)
 	{
-		renderer.getDbg().switchBits(Dbg::Flag::SECTOR);
-	}
-	if(in.getKey(KeyCode::F5) == 1)
-	{
-		renderer.getDbg().switchBits(Dbg::Flag::OCTREE);
+		renderer.getDbg().flipFlags(DbgFlag::SECTOR_COMPONENT);
 	}
 	if(in.getKey(KeyCode::F6) == 1)
 	{

+ 3 - 3
tools/scene/Exporter.cpp

@@ -699,9 +699,9 @@ void Exporter::exportCamera(const aiCamera& cam)
 
 	file << "scene:setActiveCamera(node:getSceneNodeBase())\n";
 
-	file << "node:setAll(" << cam.mHorizontalFOV * cam.mAspect << ", "
-		 << cam.mHorizontalFOV << ", " << cam.mClipPlaneNear << ", "
-		 << cam.mClipPlaneFar << ")\n";
+	file << "node:setAll(" << cam.mHorizontalFOV << ", "
+		 << "1.0 / getMainRenderer():getAspectRatio() * " << cam.mHorizontalFOV
+		 << ", " << cam.mClipPlaneNear << ", " << cam.mClipPlaneFar << ")\n";
 
 	// Find the node
 	const aiNode* node =