Browse Source

Refactoring again. WONT COMPILE

Panagiotis Christopoulos Charitos 10 years ago
parent
commit
9d612b33db
38 changed files with 678 additions and 512 deletions
  1. 1 1
      include/anki/gr/GrManager.h
  2. 5 5
      include/anki/math/Axisang.h
  3. 4 6
      include/anki/math/Euler.h
  4. 4 14
      include/anki/math/Mat.h
  5. 3 6
      include/anki/math/Transform.h
  6. 3 14
      include/anki/math/Vec.h
  7. 1 2
      include/anki/misc/Xml.h
  8. 0 22
      include/anki/resource/Common.h
  9. 7 7
      include/anki/resource/Material.h
  10. 9 14
      include/anki/resource/MaterialProgramCreator.h
  11. 2 2
      include/anki/resource/MeshLoader.h
  12. 4 8
      include/anki/resource/ProgramPrePreprocessor.h
  13. 7 7
      include/anki/resource/ResourceManager.h
  14. 2 5
      include/anki/resource/ResourcePointer.inl.h
  15. 1 1
      include/anki/resource/ShaderResource.h
  16. 53 49
      include/anki/scene/Sector.h
  17. 7 0
      include/anki/util/Allocator.h
  18. 5 5
      include/anki/util/DArray.h
  19. 2 2
      include/anki/util/File.h
  20. 9 0
      include/anki/util/StdTypes.h
  21. 137 46
      include/anki/util/String.h
  22. 12 15
      include/anki/util/String.inl.h
  23. 64 27
      include/anki/util/StringList.h
  24. 14 17
      include/anki/util/StringList.inl.h
  25. 2 2
      shaders/Pps.frag.glsl
  26. 2 0
      src/gr/gl/GrManager.cpp
  27. 3 4
      src/gr/gl/ShaderImpl.cpp
  28. 1 1
      src/gr/gl/TextureImpl.cpp
  29. 5 5
      src/misc/Xml.cpp
  30. 5 12
      src/resource/Material.cpp
  31. 19 27
      src/resource/MaterialProgramCreator.cpp
  32. 1 1
      src/resource/Mesh.cpp
  33. 2 2
      src/resource/MeshLoader.cpp
  34. 2 1
      src/resource/Model.cpp
  35. 7 13
      src/resource/ProgramPrePreprocessor.cpp
  36. 3 3
      src/resource/ResourceManager.cpp
  37. 15 24
      src/resource/ShaderResource.cpp
  38. 255 142
      src/scene/Sector.cpp

+ 1 - 1
include/anki/gr/GrManager.h

@@ -84,7 +84,7 @@ public:
 
 
 private:
 private:
 	GrManagerImpl* m_impl = nullptr;
 	GrManagerImpl* m_impl = nullptr;
-	StringBase<GrAllocator<char>> m_cacheDir;
+	String m_cacheDir;
 	GrAllocator<U8> m_alloc; ///< Keep it last to deleted last
 	GrAllocator<U8> m_alloc; ///< Keep it last to deleted last
 
 
 	void destroy();
 	void destroy();

+ 5 - 5
include/anki/math/Axisang.h

@@ -190,12 +190,12 @@ public:
 	/// @name Other
 	/// @name Other
 	/// @{
 	/// @{
 	template<typename TAlloc>
 	template<typename TAlloc>
-	StringBase<TAlloc> toString(
-		typename StringBase<TAlloc>::Allocator& alloc) const
+	String toString(TAlloc alloc) const
 	{
 	{
-		StringBase<TAlloc> s(alloc);
-		s += "axis: " + m_axis.toString(alloc) 
-			+ ", angle: " + StringBase<TAlloc>::toString(m_ang, alloc);
+		String s;
+		Error err = s.sprintf("axis: %f %f %f, angle: %f", 
+			m_axis[0], m_axis[1], m_axis[2], m_ang);
+		(void)err;
 		return s;
 		return s;
 	}
 	}
 	/// @}
 	/// @}

+ 4 - 6
include/anki/math/Euler.h

@@ -157,13 +157,11 @@ public:
 	/// @name Other
 	/// @name Other
 	/// @{
 	/// @{
 	template<typename TAlloc>
 	template<typename TAlloc>
-	StringBase<TAlloc> toString(
-		typename StringBase<TAlloc>::Allocator& alloc) const
+	String toString(TAlloc alloc) const
 	{
 	{
-		StringBase<TAlloc> s(alloc);
-		s = StringBase<TAlloc>::toString(x(), alloc) + CString(" ") 
-			+ StringBase<TAlloc>::toString(y(), alloc) + CString(" ") 
-			+ StringBase<TAlloc>::toString(z(), alloc);
+		String s;
+		Error err = s.sprintf("%f %f %f", x(), y(), z());
+		(void)err;
 		return s;
 		return s;
 	}
 	}
 	/// @}
 	/// @}

+ 4 - 14
include/anki/math/Mat.h

@@ -750,21 +750,11 @@ public:
 	}
 	}
 
 
 	template<typename TAlloc>
 	template<typename TAlloc>
-	StringBase<TAlloc> toString(
-		typename StringBase<TAlloc>::Allocator& alloc) const
+	String toString(TAlloc alloc) const
 	{
 	{
-		const TMat& m = *this;
-		StringBase<TAlloc> s(alloc);
-		for(U j = 0; j < J; j++)
-		{
-			for(U i = 0; i < I; i++)
-			{
-				s += StringBase<TAlloc>::toString(m(j, i), alloc) 
-					+ CString(" ");
-			}
-			s += CString("\n");
-		}
-		return s;
+		// TODO
+		ANKI_ASSERT(0 && "TODO");
+		return String();
 	}
 	}
 	/// @}
 	/// @}
 
 

+ 3 - 6
include/anki/math/Transform.h

@@ -188,13 +188,10 @@ public:
 	}
 	}
 
 
 	template<typename TAlloc>
 	template<typename TAlloc>
-	StringBase<TAlloc> toString(
-		typename StringBase<TAlloc>::Allocator& alloc) const
+	String toString(TAlloc alloc) const
 	{
 	{
-		StringBase<TAlloc> out(alloc);
-		out = StringBase<TAlloc>("t: ", alloc) + m_origin.toString(alloc) 
-			+ CString("\n\nr: ") + m_rotation.toString(alloc) 
-			+ CString("\ns: ") + StringBase<TAlloc>::toString(m_scale, alloc);
+		ANKI_ASSERT(0 && "TODO");
+		return String();
 	}
 	}
 	/// @}
 	/// @}
 
 

+ 3 - 14
include/anki/math/Vec.h

@@ -2166,21 +2166,10 @@ public:
 	}
 	}
 
 
 	template<typename TAlloc>
 	template<typename TAlloc>
-	StringBase<typename TAlloc::template rebind<char>::other> toString(
-		TAlloc alloc_) const
+	String toString(TAlloc alloc) const
 	{
 	{
-		using Alloc = typename TAlloc::template rebind<char>::other;
-		Alloc alloc = alloc_;
-		StringBase<Alloc> out;
-		for(U i = 0; i < N; i++)
-		{
-			StringBase<Alloc> tmp;
-			tmp.toString(alloc, m_arr[i]);
-			out.append(alloc, tmp);
-			out.append(alloc, " ");
-			tmp.destroy(alloc);
-		}
-		return out;
+		ANKI_ASSERT(0 && "TODO");
+		return String();
 	}
 	}
 	/// @}
 	/// @}
 
 

+ 1 - 2
include/anki/misc/Xml.h

@@ -60,8 +60,7 @@ public:
 	ANKI_USE_RESULT Error getF64(F64& out) const;
 	ANKI_USE_RESULT Error getF64(F64& out) const;
 
 
 	/// Get a number of floats
 	/// Get a number of floats
-	ANKI_USE_RESULT Error getFloats(
-		DArrayAuto<F64, StackAllocator<F64>>& out) const;
+	ANKI_USE_RESULT Error getFloats(DArrayAuto<F64>& out) const;
 
 
 	/// Return the text inside as a Mat4
 	/// Return the text inside as a Mat4
 	ANKI_USE_RESULT Error getMat4(Mat4& out) const;
 	ANKI_USE_RESULT Error getMat4(Mat4& out) const;

+ 0 - 22
include/anki/resource/Common.h

@@ -21,19 +21,9 @@ class ResourceManager;
 template<typename T>
 template<typename T>
 using ResourceAllocator = HeapAllocator<T>;
 using ResourceAllocator = HeapAllocator<T>;
 
 
-template<typename T>
-using ResourceDArray = DArray<T>;
-
-using ResourceString = StringBase<ResourceAllocator<char>>;
-
 template<typename T>
 template<typename T>
 using TempResourceAllocator = StackAllocator<T>;
 using TempResourceAllocator = StackAllocator<T>;
 
 
-template<typename T>
-using TempResourceDArrayAuto = DArrayAuto<T, TempResourceAllocator<T>>;
-
-using TempResourceString = StringBase<TempResourceAllocator<char>>;
-
 /// Contains initialization information for the resource classes.
 /// Contains initialization information for the resource classes.
 class ResourceInitializer
 class ResourceInitializer
 {
 {
@@ -53,18 +43,6 @@ public:
 };
 };
 /// @}
 /// @}
 
 
-/// @privatesection
-/// @{
-
-// Sortcut
-#define ANKI_CHECK_C(x_) \
-	err = x_; \
-	if(ANKI_UNLIKELY(err)) \
-	{ \
-		goto cleanup; \
-	}
-/// @}
-
 } // end namespace anki
 } // end namespace anki
 
 
 #endif
 #endif

+ 7 - 7
include/anki/resource/Material.h

@@ -123,7 +123,7 @@ protected:
 	ShaderVariableDataType m_varType = ShaderVariableDataType::NONE;
 	ShaderVariableDataType m_varType = ShaderVariableDataType::NONE;
 	ShaderVariableBlockInfo m_varBlkInfo;
 	ShaderVariableBlockInfo m_varBlkInfo;
 	I16 m_textureUnit = -1;
 	I16 m_textureUnit = -1;
-	ResourceString m_name;
+	String m_name;
 
 
 	Bool8 m_instanced = false;
 	Bool8 m_instanced = false;
 };
 };
@@ -181,7 +181,7 @@ public:
 		TempResourceAllocator<U8> talloc);
 		TempResourceAllocator<U8> talloc);
 
 
 private:
 private:
-	ResourceDArray<TData> m_data;
+	DArray<TData> m_data;
 };
 };
 
 
 /// Contains a few properties that other classes may use. For an explanation of
 /// Contains a few properties that other classes may use. For an explanation of
@@ -340,7 +340,7 @@ public:
 	}
 	}
 
 
 	// Variable accessors
 	// Variable accessors
-	const ResourceDArray<MaterialVariable*>& getVariables() const
+	const DArray<MaterialVariable*>& getVariables() const
 	{
 	{
 		return m_vars;
 		return m_vars;
 	}
 	}
@@ -367,11 +367,11 @@ private:
 	/// Keep it to have access to some stuff at runtime
 	/// Keep it to have access to some stuff at runtime
 	ResourceManager* m_resources = nullptr; 
 	ResourceManager* m_resources = nullptr; 
 		
 		
-	ResourceDArray<MaterialVariable*> m_vars;
+	DArray<MaterialVariable*> m_vars;
 	Dictionary<MaterialVariable*> m_varDict;
 	Dictionary<MaterialVariable*> m_varDict;
 
 
-	ResourceDArray<ShaderResourcePointer> m_progs;
-	ResourceDArray<PipelineHandle> m_pplines;
+	DArray<ShaderResourcePointer> m_progs;
+	DArray<PipelineHandle> m_pplines;
 
 
 	U32 m_shaderBlockSize;
 	U32 m_shaderBlockSize;
 
 
@@ -388,7 +388,7 @@ private:
 
 
 	/// Create a unique shader source in chache. If already exists do nothing
 	/// Create a unique shader source in chache. If already exists do nothing
 	ANKI_USE_RESULT Error createProgramSourceToCache(
 	ANKI_USE_RESULT Error createProgramSourceToCache(
-		const TempResourceString& source, TempResourceString& out);
+		const StringAuto& source, StringAuto& out);
 
 
 	/// Read all shader programs and pupulate the @a vars and @a nameToVar
 	/// Read all shader programs and pupulate the @a vars and @a nameToVar
 	/// containers
 	/// containers

+ 9 - 14
include/anki/resource/MaterialProgramCreator.h

@@ -20,19 +20,16 @@ class XmlElement;
 class MaterialProgramCreatorInputVariable: public NonCopyable
 class MaterialProgramCreatorInputVariable: public NonCopyable
 {
 {
 public:
 public:
-	using MPString = TempResourceString; 
-	using MPStringList = StringListBase<TempResourceAllocator<char>>;
-
 	TempResourceAllocator<U8> m_alloc;
 	TempResourceAllocator<U8> m_alloc;
-	MPString m_name;
-	MPString m_typeStr;
+	String m_name;
+	String m_typeStr;
 	ShaderVariableDataType m_type = ShaderVariableDataType::NONE;
 	ShaderVariableDataType m_type = ShaderVariableDataType::NONE;
-	MPStringList m_value;
+	StringList m_value;
 	Bool8 m_constant = false;
 	Bool8 m_constant = false;
 	U16 m_arraySize = 0;
 	U16 m_arraySize = 0;
 	Bool8 m_instanced = false;
 	Bool8 m_instanced = false;
 
 
-	MPString m_line;
+	String m_line;
 	GLbitfield m_shaderDefinedMask = 0; ///< Defined in
 	GLbitfield m_shaderDefinedMask = 0; ///< Defined in
 	GLbitfield m_shaderReferencedMask = 0; ///< Referenced by
 	GLbitfield m_shaderReferencedMask = 0; ///< Referenced by
 	Bool8 m_inBlock = true;
 	Bool8 m_inBlock = true;
@@ -108,8 +105,6 @@ public:
 class MaterialProgramCreator
 class MaterialProgramCreator
 {
 {
 public:
 public:
-	using MPString = TempResourceString; 
-	using MPStringList = StringListBase<TempResourceAllocator<char>>;
 	using Input = MaterialProgramCreatorInputVariable;
 	using Input = MaterialProgramCreatorInputVariable;
 
 
 	explicit MaterialProgramCreator(TempResourceAllocator<U8>& alloc);
 	explicit MaterialProgramCreator(TempResourceAllocator<U8>& alloc);
@@ -121,7 +116,7 @@ public:
 	ANKI_USE_RESULT Error parseProgramsTag(const XmlElement& el);
 	ANKI_USE_RESULT Error parseProgramsTag(const XmlElement& el);
 
 
 	/// Get the shader program source code
 	/// Get the shader program source code
-	const MPString& getProgramSource(ShaderType shaderType_) const
+	const String& getProgramSource(ShaderType shaderType_) const
 	{
 	{
 		U shaderType = enumToType(shaderType_);
 		U shaderType = enumToType(shaderType_);
 		ANKI_ASSERT(!m_sourceBaked[shaderType].isEmpty());
 		ANKI_ASSERT(!m_sourceBaked[shaderType].isEmpty());
@@ -145,10 +140,10 @@ public:
 
 
 private:
 private:
 	TempResourceAllocator<char> m_alloc; 
 	TempResourceAllocator<char> m_alloc; 
-	Array<MPStringList, 5> m_source; ///< Shader program final source
-	Array<MPString, 5> m_sourceBaked; ///< Final source baked
+	Array<StringList, 5> m_source; ///< Shader program final source
+	Array<String, 5> m_sourceBaked; ///< Final source baked
 	List<Input> m_inputs;
 	List<Input> m_inputs;
-	MPStringList m_uniformBlock;
+	StringList m_uniformBlock;
 	GLbitfield m_uniformBlockReferencedMask = 0;
 	GLbitfield m_uniformBlockReferencedMask = 0;
 	U32 m_blockSize = 0;
 	U32 m_blockSize = 0;
 	Bool8 m_instanced = false;
 	Bool8 m_instanced = false;
@@ -166,7 +161,7 @@ private:
 	/// Parse what is within the @code <operation></operation> @endcode
 	/// Parse what is within the @code <operation></operation> @endcode
 	ANKI_USE_RESULT Error parseOperationTag(
 	ANKI_USE_RESULT Error parseOperationTag(
 		const XmlElement& el, GLenum glshader, 
 		const XmlElement& el, GLenum glshader, 
-		GLbitfield glshaderbit, MPString& out);
+		GLbitfield glshaderbit, String& out);
 };
 };
 
 
 } // end namespace anki
 } // end namespace anki

+ 2 - 2
include/anki/resource/MeshLoader.h

@@ -95,7 +95,7 @@ public:
 	~MeshLoader();
 	~MeshLoader();
 
 
 	ANKI_USE_RESULT Error load(
 	ANKI_USE_RESULT Error load(
-		TempResourceAllocator<U8> alloc,
+		BaseMemoryPool* pool,
 		const CString& filename);
 		const CString& filename);
 
 
 	const Header& getHeader() const
 	const Header& getHeader() const
@@ -145,7 +145,7 @@ private:
 	template<typename T>
 	template<typename T>
 	using MDArray = DArray<T>;
 	using MDArray = DArray<T>;
 
 
-	TempResourceAllocator<U8> m_alloc;
+	GenericPoolAllocator<U8, BaseMemoryPool> m_alloc;
 	Header m_header;
 	Header m_header;
 
 
 	MDArray<U8> m_verts;
 	MDArray<U8> m_verts;

+ 4 - 8
include/anki/resource/ProgramPrePreprocessor.h

@@ -26,10 +26,6 @@ namespace anki {
 /// - #pragma anki include "<filename>"
 /// - #pragma anki include "<filename>"
 class ProgramPrePreprocessor
 class ProgramPrePreprocessor
 {
 {
-private:
-	using PPPStringList = StringListBase<TempResourceAllocator<char>>;
-	using PPPString = TempResourceString;
-
 public:
 public:
 	/// It loads a file and parses it
 	/// It loads a file and parses it
 	/// @param[in] filename The file to load
 	/// @param[in] filename The file to load
@@ -50,7 +46,7 @@ public:
 	/// @param filename The file to parse
 	/// @param filename The file to parse
 	ANKI_USE_RESULT Error parseFile(const CString& filename);
 	ANKI_USE_RESULT Error parseFile(const CString& filename);
 
 
-	const PPPString& getShaderSource() const
+	const String& getShaderSource() const
 	{
 	{
 		ANKI_ASSERT(!m_shaderSource.isEmpty());
 		ANKI_ASSERT(!m_shaderSource.isEmpty());
 		return m_shaderSource;
 		return m_shaderSource;
@@ -66,10 +62,10 @@ protected:
 	TempResourceAllocator<U8> m_alloc;
 	TempResourceAllocator<U8> m_alloc;
 
 
 	/// The final program source
 	/// The final program source
-	PPPString m_shaderSource;
+	String m_shaderSource;
 
 
 	/// The parseFileForPragmas fills this
 	/// The parseFileForPragmas fills this
-	PPPStringList m_sourceLines;
+	StringList m_sourceLines;
 
 
 	/// Shader type
 	/// Shader type
 	ShaderType m_type = ShaderType::COUNT;
 	ShaderType m_type = ShaderType::COUNT;
@@ -87,7 +83,7 @@ protected:
 		CString filename, U32 depth);
 		CString filename, U32 depth);
 
 
 	/// Parse the type
 	/// Parse the type
-	ANKI_USE_RESULT Error parseType(const PPPString& line, Bool& found);
+	ANKI_USE_RESULT Error parseType(const String& line, Bool& found);
 
 
 	void printSourceLines() const;  ///< For debugging
 	void printSourceLines() const;  ///< For debugging
 };
 };

+ 7 - 7
include/anki/resource/ResourceManager.h

@@ -158,7 +158,7 @@ public:
 
 
 	ANKI_USE_RESULT Error create(Initializer& init);
 	ANKI_USE_RESULT Error create(Initializer& init);
 
 
-	const ResourceString& getDataDirectory() const
+	const String& getDataDirectory() const
 	{
 	{
 		return m_dataDir;
 		return m_dataDir;
 	}
 	}
@@ -175,7 +175,7 @@ public:
 
 
 	ANKI_USE_RESULT Error fixResourceFilename(
 	ANKI_USE_RESULT Error fixResourceFilename(
 		const CString& filename,
 		const CString& filename,
-		TempResourceString& out) const;
+		StringAuto& out) const;
 
 
 	/// @privatesection
 	/// @privatesection
 	/// @{
 	/// @{
@@ -201,7 +201,7 @@ public:
 		return *m_physics;
 		return *m_physics;
 	}
 	}
 
 
-	const ResourceString& _getCacheDirectory() const
+	const String& _getCacheDirectory() const
 	{
 	{
 		return m_cacheDir;
 		return m_cacheDir;
 	}
 	}
@@ -212,7 +212,7 @@ public:
 		return m_shadersPrependedSource.create(m_alloc, cstr);
 		return m_shadersPrependedSource.create(m_alloc, cstr);
 	}
 	}
 
 
-	const ResourceString& _getShadersPrependedSource() const
+	const String& _getShadersPrependedSource() const
 	{
 	{
 		return m_shadersPrependedSource;
 		return m_shadersPrependedSource;
 	}
 	}
@@ -249,11 +249,11 @@ private:
 	PhysicsWorld* m_physics = nullptr;
 	PhysicsWorld* m_physics = nullptr;
 	ResourceAllocator<U8> m_alloc;
 	ResourceAllocator<U8> m_alloc;
 	TempResourceAllocator<U8> m_tmpAlloc;
 	TempResourceAllocator<U8> m_tmpAlloc;
-	ResourceString m_cacheDir;
-	ResourceString m_dataDir;
+	String m_cacheDir;
+	String m_dataDir;
 	U32 m_maxTextureSize;
 	U32 m_maxTextureSize;
 	U32 m_textureAnisotropy;
 	U32 m_textureAnisotropy;
-	ResourceString m_shadersPrependedSource;
+	String m_shadersPrependedSource;
 	AsyncLoader* m_asyncLoader = nullptr; ///< Async loading thread
 	AsyncLoader* m_asyncLoader = nullptr; ///< Async loading thread
 };
 };
 
 

+ 2 - 5
include/anki/resource/ResourcePointer.inl.h

@@ -46,9 +46,7 @@ Error ResourcePointer<T, TResourceManager>::load(
 		// WARNING: Keep the brackets to force deallocation of newFname before
 		// WARNING: Keep the brackets to force deallocation of newFname before
 		// reseting the mempool
 		// reseting the mempool
 		{
 		{
-			TempResourceString newFname;
-			TempResourceString::ScopeDestroyer newFnamed(
-				&newFname, resources->_getTempAllocator());
+			StringAuto newFname(resources->_getTempAllocator());
 
 
 			err = resources->fixResourceFilename(filename, newFname);
 			err = resources->fixResourceFilename(filename, newFname);
 			if(err)
 			if(err)
@@ -150,7 +148,7 @@ template<typename... TArgs>
 Error ResourcePointer<T, TResourceManager>::loadToCache(
 Error ResourcePointer<T, TResourceManager>::loadToCache(
 	TResourceManager* resources, TArgs&&... args)
 	TResourceManager* resources, TArgs&&... args)
 {
 {
-	TempResourceString fname;
+	StringAuto fname(resources->_getTempAllocator());
 
 
 	Error err = T::createToCache(args..., *resources, fname);
 	Error err = T::createToCache(args..., *resources, fname);
 
 
@@ -159,7 +157,6 @@ Error ResourcePointer<T, TResourceManager>::loadToCache(
 		err = load(fname.toCString(), resources);
 		err = load(fname.toCString(), resources);
 	}
 	}
 
 
-	fname.destroy(resources->_getTempAllocator());
 	return err;
 	return err;
 }
 }
 
 

+ 1 - 1
include/anki/resource/ShaderResource.h

@@ -52,7 +52,7 @@ public:
 		const CString& preAppendedSrcCode,
 		const CString& preAppendedSrcCode,
 		const CString& filenamePrefix,
 		const CString& filenamePrefix,
 		ResourceManager& manager,
 		ResourceManager& manager,
-		TempResourceString& out);
+		StringAuto& out);
 
 
 	ShaderType getType() const
 	ShaderType getType() const
 	{
 	{

+ 53 - 49
include/anki/scene/Sector.h

@@ -6,88 +6,106 @@
 #ifndef ANKI_SCENE_SECTOR_H
 #ifndef ANKI_SCENE_SECTOR_H
 #define ANKI_SCENE_SECTOR_H
 #define ANKI_SCENE_SECTOR_H
 
 
-#include "anki/scene/Common.h"
-#include "anki/scene/Visibility.h"
+#include "anki/scene/SceneNode.h"
 #include "anki/Collision.h"
 #include "anki/Collision.h"
 
 
 namespace anki {
 namespace anki {
 
 
 // Forward
 // Forward
-class SceneNode;
 class Sector;
 class Sector;
 class SectorGroup;
 class SectorGroup;
 class FrustumComponent;
 class FrustumComponent;
+class SpatialComponent;
 
 
 /// @addtogroup scene
 /// @addtogroup scene
 /// @{
 /// @{
 
 
-/// 2 way Portal
-class Portal
+/// The base for portals and sectors.
+class PortalSectorBase: public SceneNode
 {
 {
-	friend class SectorGroup;
-
 public:
 public:
-	Portal(SectorGroup* sectorGroup)
-	:	m_group(sectorGroup)
+	PortalSectorBase(SceneGraph* scene)
+	:	SceneNode(scene)
 	{}
 	{}
 
 
-	~Portal();
+	~PortalSectorBase();
 
 
-	ANKI_USE_RESULT Error create(const SArray<Vec4>& vertPositions);
+	ANKI_USE_RESULT Error create(
+		const CString& name, const CString& modelFname);
 
 
 	const CollisionShape& getBoundingShape() const
 	const CollisionShape& getBoundingShape() const
 	{
 	{
 		return *m_shape;
 		return *m_shape;
 	}
 	}
 
 
-	ANKI_USE_RESULT Error addSector(Sector* sector);
+	SectorGroup& getSectorGroup();
 
 
-private:
-	SectorGroup* m_group;
-	List<Sector*> m_sectors;
+protected:
 	CollisionShape* m_shape = nullptr;
 	CollisionShape* m_shape = nullptr;
 	DArray<Vec4> m_shapeStorage;
 	DArray<Vec4> m_shapeStorage;
+};
+
+/// 2 way portal.
+class Portal: public PortalSectorBase
+{
+	friend class SectorGroup;
+
+public:
+	Portal(SceneGraph* scene)
+	:	PortalSectorBase(scene)
+	{}
+
+	~Portal();
+
+	ANKI_USE_RESULT Error create(
+		const CString& name, const CString& modelFname);
+
+	ANKI_USE_RESULT Error frameUpdate(
+		F32 prevUpdateTime, F32 crntTime) override;
+
+	/// Add reference to sector.
+	ANKI_USE_RESULT Error tryAddSector(Sector* sector);
+
+	/// Remove reference from sector.
+	void tryRemoveSector(Sector* sector);
+
+private:
+	List<Sector*> m_sectors;
 	Bool m_open = true;
 	Bool m_open = true;
 };
 };
 
 
 /// A sector. It consists of an octree and some portals
 /// A sector. It consists of an octree and some portals
-class Sector
+class Sector: public PortalSectorBase
 {
 {
 	friend class SectorGroup;
 	friend class SectorGroup;
 
 
 public:
 public:
 	/// Default constructor
 	/// Default constructor
-	Sector(SectorGroup* group)
-	:	m_group(group)
+	Sector(SceneGraph* scene)
+	:	PortalSectorBase(scene)
 	{}
 	{}
 
 
 	~Sector();
 	~Sector();
 
 
-	ANKI_USE_RESULT Error create(const SArray<Vec4>& vertPositions);
+	ANKI_USE_RESULT Error create(
+		const CString& name, const CString& modelFname);
 
 
-	const CollisionShape& getBoundingShape() const
-	{
-		return *m_shape;
-	}
-
-	ANKI_USE_RESULT Error addPortal(Portal* portal);
+	ANKI_USE_RESULT Error tryAddPortal(Portal* portal);
+	void tryRemovePortal(Portal* portal);
 
 
 	ANKI_USE_RESULT Error tryAddSpatialComponent(SpatialComponent* sp);
 	ANKI_USE_RESULT Error tryAddSpatialComponent(SpatialComponent* sp);
-
 	void tryRemoveSpatialComponent(SpatialComponent* sp);
 	void tryRemoveSpatialComponent(SpatialComponent* sp);
 
 
-private:
-	SectorGroup* m_group; ///< Know your father
-	CollisionShape* m_shape;
-	DArray<Vec4> m_shapeStorage;
+	ANKI_USE_RESULT Error frameUpdate(
+		F32 prevUpdateTime, F32 crntTime) override;
 
 
+private:
 	List<Portal*> m_portals;
 	List<Portal*> m_portals;
 	List<SpatialComponent*> m_spatials;
 	List<SpatialComponent*> m_spatials;
 
 
+	/// Lock the m_spatials cause many threads will update that
 	SpinLock m_lock;
 	SpinLock m_lock;
 
 
-	Bool m_dirty = true;
-
 	List<SpatialComponent*>::Iterator findSpatialComponent(
 	List<SpatialComponent*>::Iterator findSpatialComponent(
 		SpatialComponent* sp);
 		SpatialComponent* sp);
 };
 };
@@ -95,6 +113,9 @@ private:
 /// Sector group. This is supposed to represent the whole scene
 /// Sector group. This is supposed to represent the whole scene
 class SectorGroup
 class SectorGroup
 {
 {
+	friend class Sector;
+	friend class Portal;
+
 public:
 public:
 	/// Default constructor
 	/// Default constructor
 	SectorGroup(SceneGraph* scene)
 	SectorGroup(SceneGraph* scene)
@@ -104,16 +125,6 @@ public:
 	/// Destructor
 	/// Destructor
 	~SectorGroup();
 	~SectorGroup();
 
 
-	SceneAllocator<U8> getAllocator() const;
-
-	/// The owner of the pointer is the sector group
-	Sector* createNewSector(const SArray<Vec4>& vertexPositions);
-
-	/// The owner of the pointer is the sector group
-	Portal* createNewPortal(const SArray<Vec4>& vertexPositions);
-
-	ANKI_USE_RESULT Error bake();
-
 	ANKI_USE_RESULT Error spatialUpdated(SpatialComponent* sp);
 	ANKI_USE_RESULT Error spatialUpdated(SpatialComponent* sp);
 	void spatialDeleted(SpatialComponent* sp);
 	void spatialDeleted(SpatialComponent* sp);
 
 
@@ -124,13 +135,6 @@ public:
 	ANKI_USE_RESULT Error iterateVisibleSceneNodes(
 	ANKI_USE_RESULT Error iterateVisibleSceneNodes(
 		PtrSize begin, PtrSize end, Func func);
 		PtrSize begin, PtrSize end, Func func);
 
 
-	/// @privatesection
-	/// @{
-	ConvexHullShape* createConvexHull(
-		const SArray<Vec4>& vertPositions,
-		DArray<Vec4>& shapeStorage);
-	/// @}
-
 private:
 private:
 	SceneGraph* m_scene; ///< Keep it here to access various allocators
 	SceneGraph* m_scene; ///< Keep it here to access various allocators
 	List<Sector*> m_sectors;
 	List<Sector*> m_sectors;

+ 7 - 0
include/anki/util/Allocator.h

@@ -103,6 +103,13 @@ public:
 		m_pool->getRefcount().store(1);
 		m_pool->getRefcount().store(1);
 	}
 	}
 
 
+	/// Assing a pool directly.
+	GenericPoolAllocator(TPool* pool)
+	{
+		m_pool = pool;
+		m_pool->getRefcount().fetchAdd(1);
+	}
+
 	/// Destructor
 	/// Destructor
 	~GenericPoolAllocator()
 	~GenericPoolAllocator()
 	{
 	{

+ 5 - 5
include/anki/util/DArray.h

@@ -268,17 +268,17 @@ protected:
 /// Dynamic array with automatic destruction. It's the same as DArray but it 
 /// Dynamic array with automatic destruction. It's the same as DArray but it 
 /// holds the allocator in order to perform automatic destruction. Use it for
 /// holds the allocator in order to perform automatic destruction. Use it for
 /// temp operations and on transient classes.
 /// temp operations and on transient classes.
-template<typename T, typename TAlloc = HeapAllocator<T>>
+template<typename T>
 class DArrayAuto: public DArray<T>
 class DArrayAuto: public DArray<T>
 {
 {
 public:
 public:
 	using Base = DArray<T>;
 	using Base = DArray<T>;
 	using Value = T;
 	using Value = T;
-	using Allocator = TAlloc;
 
 
-	DArrayAuto(Allocator alloc)
+	template<typename TAllocator>
+	DArrayAuto(TAllocator alloc)
 	:	Base(),
 	:	Base(),
-		m_alloc(alloc)
+		m_alloc(&alloc.getMemoryPool())
 	{}
 	{}
 
 
 	/// Move.
 	/// Move.
@@ -319,7 +319,7 @@ public:
 	}
 	}
 
 
 private:
 private:
-	Allocator m_alloc;
+	GenericMemoryPoolAllocator<T> m_alloc;
 
 
 	void move(DArrayAuto& b)
 	void move(DArrayAuto& b)
 	{
 	{

+ 2 - 2
include/anki/util/File.h

@@ -97,7 +97,7 @@ public:
 	/// Read all the contents of a text file
 	/// Read all the contents of a text file
 	/// If the file is not rewined it will probably fail
 	/// If the file is not rewined it will probably fail
 	template<typename TAlloc>
 	template<typename TAlloc>
-	ANKI_USE_RESULT Error readAllText(TAlloc alloc, StringBase<TAlloc>& out);
+	ANKI_USE_RESULT Error readAllText(TAlloc alloc, String& out);
 
 
 	/// Read 32bit unsigned integer. Set the endianness if the file's 
 	/// Read 32bit unsigned integer. Set the endianness if the file's 
 	/// endianness is different from the machine's
 	/// endianness is different from the machine's
@@ -170,7 +170,7 @@ private:
 
 
 //==============================================================================
 //==============================================================================
 template<typename TAlloc>
 template<typename TAlloc>
-inline Error File::readAllText(TAlloc alloc, StringBase<TAlloc>& out)
+inline Error File::readAllText(TAlloc alloc, String& out)
 {
 {
 	Error err = ErrorCode::NONE;
 	Error err = ErrorCode::NONE;
 	PtrSize size = getSize();
 	PtrSize size = getSize();

+ 9 - 0
include/anki/util/StdTypes.h

@@ -154,6 +154,7 @@ private:
 	ErrorCode m_code = ErrorCode::NONE;
 	ErrorCode m_code = ErrorCode::NONE;
 };
 };
 
 
+/// Macro to check if a method/function returned an error.
 #define ANKI_CHECK(x_) \
 #define ANKI_CHECK(x_) \
 	do { \
 	do { \
 		Error error = x_; \
 		Error error = x_; \
@@ -161,6 +162,14 @@ private:
 			return error; \
 			return error; \
 		} \
 		} \
 	} while(0)
 	} while(0)
+
+/// Macro the check if a memory allocation is OOM.
+#define ANKI_CHECK_OOM(x_) \
+	do { \
+		if(ANKI_UNLIKELY(x_ == nullptr)) { \
+			return ErrorCode::OUT_OF_MEMORY; \
+		} \
+	} while(0)
 /// @}
 /// @}
 
 
 } // end namespace anki
 } // end namespace anki

+ 137 - 46
include/anki/util/String.h

@@ -18,8 +18,7 @@
 namespace anki {
 namespace anki {
 
 
 // Forward
 // Forward
-template<typename TAlloc>
-class StringBase;
+class String;
 
 
 /// @addtogroup util_private
 /// @addtogroup util_private
 /// @{
 /// @{
@@ -62,8 +61,7 @@ ANKI_DEPLOY_TO_STRING(F64, "%f")
 /// A wrapper on top of C strings. Used mainly for safety.
 /// A wrapper on top of C strings. Used mainly for safety.
 class CString
 class CString
 {
 {
-	template<typename TAlloc>
-	friend class StringBase; // For the secret constructor
+	friend class String; // For the secret constructor
 
 
 public:
 public:
 	using Char = char;
 	using Char = char;
@@ -281,65 +279,62 @@ private:
 	}
 	}
 };
 };
 
 
-template<typename TAlloc>
-using StringScopeDestroyer = ScopeDestroyer<StringBase<TAlloc>, TAlloc>;
-
 /// The base class for strings.
 /// The base class for strings.
-template<typename TAlloc>
-class StringBase: public NonCopyable
+class String: public NonCopyable
 {
 {
 public:
 public:
 	using Char = char; ///< Character type
 	using Char = char; ///< Character type
-	using Allocator = TAlloc; ///< Allocator type
-	using Self = StringBase;
 	using CStringType = CString;
 	using CStringType = CString;
 	using Iterator = Char*;
 	using Iterator = Char*;
 	using ConstIterator = const Char*;
 	using ConstIterator = const Char*;
 
 
-	using ScopeDestroyer = StringScopeDestroyer<Allocator>;
-
 	static const PtrSize NPOS = MAX_PTR_SIZE;
 	static const PtrSize NPOS = MAX_PTR_SIZE;
 
 
 	/// Default constructor.
 	/// Default constructor.
-	StringBase() 
+	String() 
 	{}
 	{}
 
 
 	/// Move constructor.
 	/// Move constructor.
-	StringBase(StringBase&& b) 
-	:	m_data(std::move(b.m_data))
-	{}
+	String(String&& b) 
+	{
+		move(b);
+	}
 
 
 	/// Requires manual destruction.
 	/// Requires manual destruction.
-	~StringBase() 
+	~String() 
 	{}
 	{}
 
 
 	/// Initialize using a const string.
 	/// Initialize using a const string.
-	ANKI_USE_RESULT Error create(Allocator alloc, const CStringType& cstr);
+	template<typename TAllocator>
+	ANKI_USE_RESULT Error create(TAllocator alloc, const CStringType& cstr);
 
 
 	/// Initialize using a range. Copies the range of [first, last)
 	/// Initialize using a range. Copies the range of [first, last)
-	ANKI_USE_RESULT Error create(Allocator alloc,
+	template<typename TAllocator>
+	ANKI_USE_RESULT Error create(TAllocator alloc,
 		ConstIterator first, ConstIterator last);
 		ConstIterator first, ConstIterator last);
 
 
 	/// Initialize using a character.
 	/// Initialize using a character.
-	ANKI_USE_RESULT Error create(Allocator alloc, Char c, PtrSize length);
+	template<typename TAllocator>
+	ANKI_USE_RESULT Error create(TAllocator alloc, Char c, PtrSize length);
 
 
 	/// Copy one string to this one.
 	/// Copy one string to this one.
-	ANKI_USE_RESULT Error create(Allocator alloc, const Self& b)
+	template<typename TAllocator>
+	ANKI_USE_RESULT Error create(TAllocator alloc, const String& b)
 	{
 	{
 		return create(alloc, b.toCString());
 		return create(alloc, b.toCString());
 	}
 	}
 
 
 	/// Destroy the string.
 	/// Destroy the string.
-	void destroy(Allocator alloc)
+	template<typename TAllocator>
+	void destroy(TAllocator alloc)
 	{
 	{
 		m_data.destroy(alloc);
 		m_data.destroy(alloc);
 	}
 	}
 
 
 	/// Move one string to this one.
 	/// Move one string to this one.
-	Self& operator=(Self&& b) 
+	String& operator=(String&& b) 
 	{
 	{
-		ANKI_ASSERT(this != &b);
-		m_data = std::move(b.m_data);
+		move(b);
 		return *this;
 		return *this;
 	}
 	}
 
 
@@ -382,7 +377,7 @@ public:
 	}
 	}
 
 
 	/// Return true if strings are equal
 	/// Return true if strings are equal
-	Bool operator==(const Self& b) const 
+	Bool operator==(const String& b) const 
 	{
 	{
 		checkInit();
 		checkInit();
 		b.checkInit();
 		b.checkInit();
@@ -390,13 +385,13 @@ public:
 	}
 	}
 
 
 	/// Return true if strings are not equal
 	/// Return true if strings are not equal
-	Bool operator!=(const Self& b) const 
+	Bool operator!=(const String& b) const 
 	{
 	{
 		return !(*this == b);
 		return !(*this == b);
 	}
 	}
 
 
 	/// Return true if this is less than b
 	/// Return true if this is less than b
-	Bool operator<(const Self& b) const 
+	Bool operator<(const String& b) const 
 	{
 	{
 		checkInit();
 		checkInit();
 		b.checkInit();
 		b.checkInit();
@@ -404,7 +399,7 @@ public:
 	}
 	}
 
 
 	/// Return true if this is less or equal to b
 	/// Return true if this is less or equal to b
-	Bool operator<=(const Self& b) const 
+	Bool operator<=(const String& b) const 
 	{
 	{
 		checkInit();
 		checkInit();
 		b.checkInit();
 		b.checkInit();
@@ -412,7 +407,7 @@ public:
 	}
 	}
 
 
 	/// Return true if this is greater than b
 	/// Return true if this is greater than b
-	Bool operator>(const Self& b) const 
+	Bool operator>(const String& b) const 
 	{
 	{
 		checkInit();
 		checkInit();
 		b.checkInit();
 		b.checkInit();
@@ -420,7 +415,7 @@ public:
 	}
 	}
 
 
 	/// Return true if this is greater or equal to b
 	/// Return true if this is greater or equal to b
-	Bool operator>=(const Self& b) const 
+	Bool operator>=(const String& b) const 
 	{
 	{
 		checkInit();
 		checkInit();
 		b.checkInit();
 		b.checkInit();
@@ -485,8 +480,8 @@ public:
 	}
 	}
 
 
 	/// Append another string to this one.
 	/// Append another string to this one.
-	template<typename TTAlloc>
-	ANKI_USE_RESULT Error append(Allocator alloc, const StringBase<TTAlloc>& b)
+	template<typename TAllocator>
+	ANKI_USE_RESULT Error append(TAllocator alloc, const String& b)
 	{
 	{
 		Error err = ErrorCode::NONE;
 		Error err = ErrorCode::NONE;
 		if(!b.isEmpty())
 		if(!b.isEmpty())
@@ -498,7 +493,8 @@ public:
 	}
 	}
 
 
 	/// Append a const string to this one.
 	/// Append a const string to this one.
-	ANKI_USE_RESULT Error append(Allocator alloc, const CStringType& cstr)
+	template<typename TAllocator>
+	ANKI_USE_RESULT Error append(TAllocator alloc, const CStringType& cstr)
 	{
 	{
 		Error err = ErrorCode::NONE;
 		Error err = ErrorCode::NONE;
 		if(!cstr.isEmpty())
 		if(!cstr.isEmpty())
@@ -510,7 +506,8 @@ public:
 	}
 	}
 
 
 	/// Create formated string.
 	/// Create formated string.
-	ANKI_USE_RESULT Error sprintf(Allocator alloc, CString fmt, ...);
+	template<typename TAllocator>
+	ANKI_USE_RESULT Error sprintf(TAllocator alloc, CString fmt, ...);
 
 
 	/// Return true if it's empty.
 	/// Return true if it's empty.
 	Bool isEmpty() const 
 	Bool isEmpty() const 
@@ -534,17 +531,15 @@ public:
 	/// @param position Position of the first character in the string to be 
 	/// @param position Position of the first character in the string to be 
 	///                 considered in the search.
 	///                 considered in the search.
 	/// @return A valid position if the string is found or NPOS if not found.
 	/// @return A valid position if the string is found or NPOS if not found.
-	template<typename TTAlloc>
-	PtrSize find(
-		const StringBase<TTAlloc>& str, PtrSize position) const 
+	PtrSize find(const String& str, PtrSize position) const 
 	{
 	{
-		str.chechInit();
+		str.checkInit();
 		return find(str.toCString(), position);
 		return find(str.toCString(), position);
 	}
 	}
 
 
 	/// Convert a number to a string.
 	/// Convert a number to a string.
-	template<typename TNumber>
-	ANKI_USE_RESULT Error toString(Allocator alloc, TNumber number);
+	template<typename TAllocator, typename TNumber>
+	ANKI_USE_RESULT Error toString(TAllocator alloc, TNumber number);
 
 
 	/// Convert to F64.
 	/// Convert to F64.
 	ANKI_USE_RESULT Error toF64(F64& out) const
 	ANKI_USE_RESULT Error toF64(F64& out) const
@@ -558,7 +553,7 @@ public:
 		return toCString().toI64(out);
 		return toCString().toI64(out);
 	}
 	}
 
 
-private:
+protected:
 	DArray<Char> m_data;
 	DArray<Char> m_data;
 
 
 	void checkInit() const
 	void checkInit() const
@@ -567,13 +562,109 @@ private:
 	}
 	}
 
 
 	/// Append to this string.
 	/// Append to this string.
+	template<typename TAllocator>
 	ANKI_USE_RESULT Error appendInternal(
 	ANKI_USE_RESULT Error appendInternal(
-		Allocator alloc, const Char* str, PtrSize strSize);
+		TAllocator alloc, const Char* str, PtrSize strSize);
+
+	void move(String& b)
+	{
+		ANKI_ASSERT(this != &b);
+		m_data = std::move(b.m_data);
+	}
 };
 };
 
 
-/// A common string type that uses heap allocator.
-using String = StringBase<HeapAllocator<char>>;
+/// String with automatic cleanup.
+class StringAuto: public String
+{
+public:
+	using Base = String;
+
+	/// Create with allocator.
+	template<typename TAllocator>
+	StringAuto(TAllocator alloc)
+	:	Base(),
+		m_alloc(&alloc.getMemoryPool())
+	{}
+
+	/// Move constructor.
+	StringAuto(StringAuto&& b)
+	:	Base()
+	{
+		move(b);
+	}
+
+	/// Automatic destruction.
+	~StringAuto() 
+	{
+		Base::destroy(m_alloc);
+	}
+
+	/// Initialize using a const string.
+	ANKI_USE_RESULT Error create(const CStringType& cstr)
+	{
+		return Base::create(m_alloc, cstr);
+	}
+
+	/// Initialize using a range. Copies the range of [first, last)
+	ANKI_USE_RESULT Error create(ConstIterator first, ConstIterator last)
+	{
+		return Base::create(m_alloc, first, last);
+	}
+
+	/// Initialize using a character.
+	ANKI_USE_RESULT Error create(Char c, PtrSize length)
+	{
+		return Base::create(m_alloc, c, length);
+	}
+
+	/// Copy one string to this one.
+	ANKI_USE_RESULT Error create(const String& b)
+	{
+		return Base::create(m_alloc, b.toCString());
+	}
+
+	/// Move one string to this one.
+	StringAuto& operator=(StringAuto&& b) 
+	{
+		move(b);
+		return *this;
+	}
+
+	/// Append another string to this one.
+	ANKI_USE_RESULT Error append(const String& b)
+	{
+		return Base::append(m_alloc, b);
+	}
+
+	/// Append a const string to this one.
+	ANKI_USE_RESULT Error append(const CStringType& cstr)
+	{
+		return Base::append(m_alloc, cstr);
+	}
 
 
+	/// Create formated string.
+	template<typename... TArgs>
+	ANKI_USE_RESULT Error sprintf(CString fmt, TArgs... args)
+	{
+		return Base::sprintf(m_alloc, fmt, args...);
+	}
+
+	/// Convert a number to a string.
+	template<typename TNumber>
+	ANKI_USE_RESULT Error toString(TNumber number)
+	{
+		return Base::toString(m_alloc, number);
+	}
+
+private:
+	GenericMemoryPoolAllocator<Char> m_alloc;
+
+	void move(StringAuto& b)
+	{
+		Base::move(b);
+		m_alloc = std::move(b.m_alloc);
+	}
+};
 /// @}
 /// @}
 
 
 } // end namespace anki
 } // end namespace anki

+ 12 - 15
include/anki/util/String.inl.h

@@ -6,8 +6,8 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-template<typename TAlloc>
-Error StringBase<TAlloc>::create(Allocator alloc, const CStringType& cstr)
+template<typename TAllocator>
+Error String::create(TAllocator alloc, const CStringType& cstr)
 {
 {
 	Error err = ErrorCode::NONE;
 	Error err = ErrorCode::NONE;
 	
 	
@@ -27,9 +27,8 @@ Error StringBase<TAlloc>::create(Allocator alloc, const CStringType& cstr)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-template<typename TAlloc>
-Error StringBase<TAlloc>::create(
-	Allocator alloc, ConstIterator first, ConstIterator last)
+template<typename TAllocator>
+Error String::create(TAllocator alloc, ConstIterator first, ConstIterator last)
 {
 {
 	ANKI_ASSERT(first != 0 && last != 0);
 	ANKI_ASSERT(first != 0 && last != 0);
 	auto length = last - first;
 	auto length = last - first;
@@ -45,8 +44,8 @@ Error StringBase<TAlloc>::create(
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-template<typename TAlloc>
-Error StringBase<TAlloc>::create(Allocator alloc, Char c, PtrSize length)
+template<typename TAllocator>
+Error String::create(TAllocator alloc, Char c, PtrSize length)
 {
 {
 	ANKI_ASSERT(c != '\0');
 	ANKI_ASSERT(c != '\0');
 	Error err = m_data.create(alloc, length + 1);
 	Error err = m_data.create(alloc, length + 1);
@@ -61,9 +60,8 @@ Error StringBase<TAlloc>::create(Allocator alloc, Char c, PtrSize length)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-template<typename TAlloc>
-Error StringBase<TAlloc>::appendInternal(
-	Allocator alloc, const Char* str, PtrSize strSize)
+template<typename TAllocator>
+Error String::appendInternal(TAllocator alloc, const Char* str, PtrSize strSize)
 {
 {
 	ANKI_ASSERT(str != nullptr);
 	ANKI_ASSERT(str != nullptr);
 	ANKI_ASSERT(strSize > 1);
 	ANKI_ASSERT(strSize > 1);
@@ -96,8 +94,8 @@ Error StringBase<TAlloc>::appendInternal(
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-template<typename TAlloc>
-Error StringBase<TAlloc>::sprintf(Allocator alloc, CString fmt, ...)
+template<typename TAllocator>
+Error String::sprintf(TAllocator alloc, CString fmt, ...)
 {
 {
 	Error err = ErrorCode::NONE;
 	Error err = ErrorCode::NONE;
 	Array<Char, 512> buffer;
 	Array<Char, 512> buffer;
@@ -137,9 +135,8 @@ Error StringBase<TAlloc>::sprintf(Allocator alloc, CString fmt, ...)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-template<typename TAlloc>
-template<typename TNumber>
-Error StringBase<TAlloc>::toString(Allocator alloc, TNumber number)
+template<typename TAllocator, typename TNumber>
+Error String::toString(TAllocator alloc, TNumber number)
 {
 {
 	Error err = ErrorCode::NONE;
 	Error err = ErrorCode::NONE;
 
 

+ 64 - 27
include/anki/util/StringList.h

@@ -12,35 +12,16 @@
 
 
 namespace anki {
 namespace anki {
 
 
-// Forward
-template<typename TAlloc>
-class StringListBase;
-
-/// @addtogroup util_private
-/// @{
-
-template<typename TAlloc>
-using StringListBaseScopeDestroyer = 
-	ScopeDestroyer<StringListBase<TAlloc>, TAlloc>;
-
-/// @}
-
 /// @addtogroup util_containers
 /// @addtogroup util_containers
 /// @{
 /// @{
 
 
 /// A simple convenience class for string lists
 /// A simple convenience class for string lists
-template<typename TAlloc>
-class StringListBase: public List<StringBase<TAlloc>>
+class StringList: public List<String>
 {
 {
 public:
 public:
-	using Self = StringListBase; ///< Self type
 	using Char = char; ///< Char type
 	using Char = char; ///< Char type
-	using Allocator = TAlloc;
-	using String = StringBase<Allocator>; ///< String type
 	using Base = List<String>; ///< Base
 	using Base = List<String>; ///< Base
 
 
-	using ScopeDestroyer = StringListBaseScopeDestroyer<Allocator>;
-
 	/// Sort method for sortAll().
 	/// Sort method for sortAll().
 	enum class Sort
 	enum class Sort
 	{
 	{
@@ -51,12 +32,14 @@ public:
 	// Use the base constructors
 	// Use the base constructors
 	using Base::Base;
 	using Base::Base;
 
 
-	void destroy(Allocator alloc);
+	template<typename TAllocator>
+	void destroy(TAllocator alloc);
 
 
 	/// Join all the elements into a single big string using a the
 	/// Join all the elements into a single big string using a the
 	/// seperator @a separator
 	/// seperator @a separator
+	template<typename TAllocator>
 	ANKI_USE_RESULT Error join(
 	ANKI_USE_RESULT Error join(
-		Allocator alloc, const CString& separator, String& out) const;
+		TAllocator alloc, const CString& separator, String& out) const;
 
 
 	/// Returns the index position of the last occurrence of @a value in
 	/// Returns the index position of the last occurrence of @a value in
 	/// the list
 	/// the list
@@ -67,19 +50,73 @@ public:
 	void sortAll(const Sort method = Sort::ASCENDING);
 	void sortAll(const Sort method = Sort::ASCENDING);
 
 
 	/// Push at the end of the list a formated string
 	/// Push at the end of the list a formated string
-	template<typename... TArgs>
+	template<typename TAllocator, typename... TArgs>
 	ANKI_USE_RESULT Error pushBackSprintf(
 	ANKI_USE_RESULT Error pushBackSprintf(
-		Allocator alloc, const TArgs&... args);
+		TAllocator alloc, const TArgs&... args);
 
 
 	/// Split a string using a separator (@a separator) and return these
 	/// Split a string using a separator (@a separator) and return these
 	/// strings in a string list
 	/// strings in a string list
+	template<typename TAllocator>
 	ANKI_USE_RESULT Error splitString(
 	ANKI_USE_RESULT Error splitString(
-		Allocator alloc, const CString& s, const Char separator);
+		TAllocator alloc, const CString& s, const Char separator);
 };
 };
 
 
-/// A common string list allocated in heap.
-using StringList = StringListBase<HeapAllocator<char>>;
+/// String list with automatic destruction.
+class StringListAuto: public StringList
+{
+public:
+	using Base = StringList;
+
+	/// Create using an allocator.
+	template<typename TAllocator>
+	StringListAuto(TAllocator alloc)
+	:	Base(),
+		m_alloc(&alloc.getMemoryPool())
+	{}
+
+	/// Move.
+	StringListAuto(StringListAuto&& b)
+	:	Base()
+	{
+		move(b);
+	}
 
 
+	~StringListAuto()
+	{
+		Base::destroy(m_alloc);
+	}
+
+	/// Move.
+	StringListAuto& operator=(StringListAuto&& b)
+	{
+		move(b);
+		return *this;
+	}
+
+	/// Push at the end of the list a formated string
+	template<typename... TArgs>
+	ANKI_USE_RESULT Error pushBackSprintf(const TArgs&... args)
+	{
+		return Base::pushBackSprintf(m_alloc, args...);
+	}
+
+	/// Split a string using a separator (@a separator) and return these
+	/// strings in a string list
+	ANKI_USE_RESULT Error splitString(
+		const CString& s, const Base::Char separator)
+	{
+		return Base::splitString(m_alloc, s, separator);
+	}
+
+private:
+	GenericMemoryPoolAllocator<Char> m_alloc;
+
+	void move(StringListAuto& b)
+	{
+		Base::operator=(std::move(b));
+		m_alloc = std::move(b.m_alloc);
+	}
+};
 /// @}
 /// @}
 
 
 } // end namespace anki
 } // end namespace anki

+ 14 - 17
include/anki/util/StringList.inl.h

@@ -9,8 +9,8 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-template<typename TAlloc>
-void StringListBase<TAlloc>::destroy(Allocator alloc)
+template<typename TAllocator>
+void StringList::destroy(TAllocator alloc)
 {
 {
 	auto it = Base::getBegin();
 	auto it = Base::getBegin();
 	auto endit = Base::getEnd();
 	auto endit = Base::getEnd();
@@ -23,9 +23,9 @@ void StringListBase<TAlloc>::destroy(Allocator alloc)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-template<typename TAlloc>
-Error StringListBase<TAlloc>::join(
-	Allocator alloc,
+template<typename TAllocator>
+Error StringList::join(
+	TAllocator alloc,
 	const CString& separator,
 	const CString& separator,
 	String& out) const
 	String& out) const
 {
 {
@@ -72,8 +72,7 @@ Error StringListBase<TAlloc>::join(
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-template<typename TAlloc>
-I StringListBase<TAlloc>::getIndexOf(const CString& value) const
+I StringList::getIndexOf(const CString& value) const
 {
 {
 	U pos = 0;
 	U pos = 0;
 
 
@@ -86,13 +85,13 @@ I StringListBase<TAlloc>::getIndexOf(const CString& value) const
 		++ pos;
 		++ pos;
 	}
 	}
 
 
-	return (pos == Base::size()) ? -1 : pos;
+	return (pos == Base::getSize()) ? -1 : pos;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-template<typename TAlloc>
-Error StringListBase<TAlloc>::splitString(
-	Allocator alloc,
+template<typename TAllocator>
+Error StringList::splitString(
+	TAllocator alloc,
 	const CString& s, 
 	const CString& s, 
 	const Char separator)
 	const Char separator)
 {
 {
@@ -155,8 +154,7 @@ Error StringListBase<TAlloc>::splitString(
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-template<typename TAlloc>
-void StringListBase<TAlloc>::sortAll(const Sort method)
+void StringList::sortAll(const Sort method)
 {
 {
 	if(method == Sort::ASCENDING)
 	if(method == Sort::ASCENDING)
 	{
 	{
@@ -176,10 +174,9 @@ void StringListBase<TAlloc>::sortAll(const Sort method)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-template<typename TAlloc>
-template<typename... TArgs>
-Error StringListBase<TAlloc>::pushBackSprintf(
-	Allocator alloc, const TArgs&... args)
+template<typename TAllocator, typename... TArgs>
+Error StringList::pushBackSprintf(
+	TAllocator alloc, const TArgs&... args)
 {
 {
 	String str;
 	String str;
 	Error err = str.sprintf(alloc, args...);
 	Error err = str.sprintf(alloc, args...);

+ 2 - 2
shaders/Pps.frag.glsl

@@ -107,8 +107,8 @@ void main()
 #endif
 #endif
 
 
 #if GAMMA_CORRECTION_ENABLED
 #if GAMMA_CORRECTION_ENABLED
-	//outColor = BlendHardLight(vec3(0.7, 0.72, 0.4), outColor);
-	outColor = gammaCorrectionRgb(vec3(0.9, 0.92, 0.75), outColor);
+	outColor = BlendHardLight(vec3(0.7, 0.72, 0.4), outColor);
+	//outColor = gammaCorrectionRgb(vec3(0.9, 0.92, 0.75), outColor);
 #endif
 #endif
 
 
 #if 0
 #if 0

+ 2 - 0
src/gr/gl/GrManager.cpp

@@ -39,6 +39,8 @@ Error GrManager::create(Initializer& init)
 //==============================================================================
 //==============================================================================
 void GrManager::destroy()
 void GrManager::destroy()
 {
 {
+	m_cacheDir.destroy(m_alloc);
+
 	if(m_impl)
 	if(m_impl)
 	{
 	{
 		m_alloc.deleteInstance(m_impl);
 		m_alloc.deleteInstance(m_impl);

+ 3 - 4
src/gr/gl/ShaderImpl.cpp

@@ -42,12 +42,11 @@ Error ShaderImpl::create(ShaderType type, const CString& source)
 	}
 	}
 
 
 	auto alloc = getAllocator();
 	auto alloc = getAllocator();
-	String fullSrc;
-	String::ScopeDestroyer fullSrcd(&fullSrc, alloc); 
+	StringAuto fullSrc(alloc);
 #if ANKI_GL == ANKI_GL_DESKTOP
 #if ANKI_GL == ANKI_GL_DESKTOP
-	err = fullSrc.sprintf(alloc, "#version %d core\n%s\n", version, &source[0]); 
+	err = fullSrc.sprintf("#version %d core\n%s\n", version, &source[0]); 
 #else
 #else
-	err = fullSrc.sprintf(alloc, "#version %d es\n%s\n", version, &source[0]);
+	err = fullSrc.sprintf("#version %d es\n%s\n", version, &source[0]);
 #endif
 #endif
 
 
 	// 2) Gen name, create, compile and link
 	// 2) Gen name, create, compile and link

+ 1 - 1
src/gr/gl/TextureImpl.cpp

@@ -248,7 +248,7 @@ Error TextureImpl::create(const Initializer& init)
 					ANKI_ASSERT(m_depth > 0);
 					ANKI_ASSERT(m_depth > 0);
 
 
 					// Gather the data
 					// Gather the data
-					DArrayAuto<U8, GrAllocator<U8>> data(alloc);
+					DArrayAuto<U8> data(alloc);
 
 
 					// Check if there are data
 					// Check if there are data
 					if(init.m_data[level][0].m_ptr != nullptr)
 					if(init.m_data[level][0].m_ptr != nullptr)

+ 5 - 5
src/misc/Xml.cpp

@@ -87,7 +87,7 @@ Error XmlElement::getF64(F64& out) const
 }
 }
 
 
 //==============================================================================V
 //==============================================================================V
-Error XmlElement::getFloats(DArrayAuto<F64, StackAllocator<F64>>& out) const
+Error XmlElement::getFloats(DArrayAuto<F64>& out) const
 {
 {
 	Error err = check();
 	Error err = check();
 	
 	
@@ -107,7 +107,7 @@ Error XmlElement::getFloats(DArrayAuto<F64, StackAllocator<F64>>& out) const
 		err = list.splitString(m_alloc, txt, ' ');
 		err = list.splitString(m_alloc, txt, ' ');
 	}
 	}
 
 
-	out = std::move(DArrayAuto<F64, StackAllocator<F64>>(m_alloc));
+	out = std::move(DArrayAuto<F64>(m_alloc));
 
 
 	if(!err)
 	if(!err)
 	{
 	{
@@ -134,7 +134,7 @@ Error XmlElement::getFloats(DArrayAuto<F64, StackAllocator<F64>>& out) const
 //==============================================================================
 //==============================================================================
 Error XmlElement::getMat4(Mat4& out) const
 Error XmlElement::getMat4(Mat4& out) const
 {
 {
-	DArrayAuto<F64, StackAllocator<F64>> arr(m_alloc);
+	DArrayAuto<F64> arr(m_alloc);
 	Error err = getFloats(arr);	
 	Error err = getFloats(arr);	
 
 
 	if(!err && arr.getSize() != 16)
 	if(!err && arr.getSize() != 16)
@@ -162,7 +162,7 @@ Error XmlElement::getMat4(Mat4& out) const
 //==============================================================================
 //==============================================================================
 Error XmlElement::getVec3(Vec3& out) const
 Error XmlElement::getVec3(Vec3& out) const
 {
 {
-	DArrayAuto<F64, StackAllocator<F64>> arr(m_alloc);
+	DArrayAuto<F64> arr(m_alloc);
 	Error err = getFloats(arr);
 	Error err = getFloats(arr);
 	
 	
 	if(!err && arr.getSize() != 3)
 	if(!err && arr.getSize() != 3)
@@ -189,7 +189,7 @@ Error XmlElement::getVec3(Vec3& out) const
 //==============================================================================
 //==============================================================================
 Error XmlElement::getVec4(Vec4& out) const
 Error XmlElement::getVec4(Vec4& out) const
 {
 {
-	DArrayAuto<F64, StackAllocator<F64>> arr(m_alloc);
+	DArrayAuto<F64> arr(m_alloc);
 	Error err = getFloats(arr);
 	Error err = getFloats(arr);
 	
 	
 	if(!err && arr.getSize() != 4)
 	if(!err && arr.getSize() != 4)

+ 5 - 12
src/resource/Material.cpp

@@ -538,12 +538,8 @@ Error Material::parseMaterialTag(const XmlElement& materialEl,
 						continue;
 						continue;
 					}
 					}
 
 
-					TempResourceString src;
-					TempResourceString::ScopeDestroyer srcd(
-						&src, rinit.m_tempAlloc);
-
+					TempResourceString src(rinit.m_tempAlloc);
 					ANKI_CHECK(src.sprintf(
 					ANKI_CHECK(src.sprintf(
-						rinit.m_tempAlloc,
 						"%s\n"
 						"%s\n"
 						"#define LOD %u\n"
 						"#define LOD %u\n"
 						"#define PASS %u\n"
 						"#define PASS %u\n"
@@ -552,9 +548,7 @@ Error Material::parseMaterialTag(const XmlElement& materialEl,
 						&rinit.m_resources._getShadersPrependedSource()[0],
 						&rinit.m_resources._getShadersPrependedSource()[0],
 						level, pid, tess, &loader.getProgramSource(shader)[0]));
 						level, pid, tess, &loader.getProgramSource(shader)[0]));
 
 
-					TempResourceString filename;
-					TempResourceString::ScopeDestroyer filenamed(
-						&filename, rinit.m_tempAlloc);
+					TempResourceString filename(rinit.m_tempAlloc);
 
 
 					ANKI_CHECK(createProgramSourceToCache(src, filename));
 					ANKI_CHECK(createProgramSourceToCache(src, filename));
 
 
@@ -589,13 +583,12 @@ Error Material::createProgramSourceToCache(
 
 
 	// Create the hash
 	// Create the hash
 	U64 h = computeHash(&source[0], source.getLength());
 	U64 h = computeHash(&source[0], source.getLength());
-	TempResourceString prefix;
-	TempResourceString::ScopeDestroyer prefixd(&prefix, alloc);
+	TempResourceString prefix(alloc);
 
 
-	ANKI_CHECK(prefix.toString(alloc, h));
+	ANKI_CHECK(prefix.toString(h));
 
 
 	// Create path
 	// Create path
-	ANKI_CHECK(out.sprintf(alloc, "%s/mtl_%s.glsl", 
+	ANKI_CHECK(out.sprintf("%s/mtl_%s.glsl", 
 		&m_resources->_getCacheDirectory()[0],
 		&m_resources->_getCacheDirectory()[0],
 		&prefix[0]));
 		&prefix[0]));
 
 

+ 19 - 27
src/resource/MaterialProgramCreator.cpp

@@ -16,10 +16,6 @@ namespace anki {
 // Misc                                                                        =
 // Misc                                                                        =
 //==============================================================================
 //==============================================================================
 
 
-//==============================================================================
-/// Define string literal
-#define ANKI_STRL(cstr_) MPString(cstr_, m_alloc)
-
 //==============================================================================
 //==============================================================================
 /// Given a string return info about the shader
 /// Given a string return info about the shader
 static ANKI_USE_RESULT Error getShaderInfo(
 static ANKI_USE_RESULT Error getShaderInfo(
@@ -283,7 +279,7 @@ Error MaterialProgramCreator::parseProgramTag(
 	ANKI_CHECK(opsEl.getChildElement("operation", opEl));
 	ANKI_CHECK(opsEl.getChildElement("operation", opEl));
 	do
 	do
 	{
 	{
-		MPString out;
+		String out;
 		ANKI_CHECK(parseOperationTag(opEl, glshader, glshaderbit, out));
 		ANKI_CHECK(parseOperationTag(opEl, glshader, glshaderbit, out));
 		ANKI_CHECK(lines.pushBackSprintf(m_alloc, &out[0]));
 		ANKI_CHECK(lines.pushBackSprintf(m_alloc, &out[0]));
 		out.destroy(m_alloc);
 		out.destroy(m_alloc);
@@ -452,7 +448,7 @@ Error MaterialProgramCreator::parseInputsTag(const XmlElement& programEl)
 			
 			
 			if(inpvar.m_arraySize > 1)
 			if(inpvar.m_arraySize > 1)
 			{
 			{
-				MPString tmp;
+				String tmp;
 				ANKI_CHECK(tmp.sprintf(m_alloc, "[%uU]", inpvar.m_arraySize));
 				ANKI_CHECK(tmp.sprintf(m_alloc, "[%uU]", inpvar.m_arraySize));
 				ANKI_CHECK(inpvar.m_line.append(m_alloc, tmp));
 				ANKI_CHECK(inpvar.m_line.append(m_alloc, tmp));
 				tmp.destroy(m_alloc);
 				tmp.destroy(m_alloc);
@@ -464,7 +460,7 @@ Error MaterialProgramCreator::parseInputsTag(const XmlElement& programEl)
 			if(inpvar.m_type >= ShaderVariableDataType::SAMPLERS_FIRST 
 			if(inpvar.m_type >= ShaderVariableDataType::SAMPLERS_FIRST 
 				&& inpvar.m_type <= ShaderVariableDataType::SAMPLERS_LAST)
 				&& inpvar.m_type <= ShaderVariableDataType::SAMPLERS_LAST)
 			{
 			{
-				MPString tmp;
+				String tmp;
 
 
 				ANKI_CHECK(tmp.sprintf(
 				ANKI_CHECK(tmp.sprintf(
 					m_alloc, "layout(binding = %u) uniform %s",
 					m_alloc, "layout(binding = %u) uniform %s",
@@ -480,7 +476,7 @@ Error MaterialProgramCreator::parseInputsTag(const XmlElement& programEl)
 			else
 			else
 			{
 			{
 				// In block
 				// In block
-				MPString tmp;
+				String tmp;
 
 
 				ANKI_CHECK(tmp.create(m_alloc, inpvar.m_line));
 				ANKI_CHECK(tmp.create(m_alloc, inpvar.m_line));
 				ANKI_CHECK(m_uniformBlock.emplaceBack(m_alloc));
 				ANKI_CHECK(m_uniformBlock.emplaceBack(m_alloc));
@@ -581,7 +577,7 @@ Error MaterialProgramCreator::parseInputsTag(const XmlElement& programEl)
 
 
 			inpvar.m_inBlock = false;
 			inpvar.m_inBlock = false;
 
 
-			MPString initList;
+			String initList;
 			ANKI_CHECK(inpvar.m_value.join(m_alloc, ", ", initList));
 			ANKI_CHECK(inpvar.m_value.join(m_alloc, ", ", initList));
 
 
 			err = inpvar.m_line.sprintf(m_alloc, "const %s %s = %s(%s);",
 			err = inpvar.m_line.sprintf(m_alloc, "const %s %s = %s(%s);",
@@ -610,7 +606,7 @@ Error MaterialProgramCreator::parseOperationTag(
 	const XmlElement& operationTag, 
 	const XmlElement& operationTag, 
 	GLenum glshader, 
 	GLenum glshader, 
 	GLbitfield glshaderbit,
 	GLbitfield glshaderbit,
-	MPString& out)
+	String& out)
 {
 {
 	Error err = ErrorCode::NONE;
 	Error err = ErrorCode::NONE;
 	CString cstr;
 	CString cstr;
@@ -619,8 +615,7 @@ Error MaterialProgramCreator::parseOperationTag(
 	static const char OUT[] = "out";
 	static const char OUT[] = "out";
 
 
 	CString funcName;
 	CString funcName;
-	MPStringList argsList;
-	MPStringList::ScopeDestroyer argsListd(&argsList, m_alloc);
+	StringListAuto argsList(m_alloc);
 
 
 	// <id></id>
 	// <id></id>
 	I64 id;
 	I64 id;
@@ -680,14 +675,14 @@ Error MaterialProgramCreator::parseOperationTag(
 
 
 				if(glshader == GL_VERTEX_SHADER)
 				if(glshader == GL_VERTEX_SHADER)
 				{
 				{
-					ANKI_CHECK(argsList.pushBackSprintf(m_alloc, 
+					ANKI_CHECK(argsList.pushBackSprintf(
 						"%s [gl_InstanceID]", &cstr[0]));
 						"%s [gl_InstanceID]", &cstr[0]));
 
 
 					m_instanceIdMask |= glshaderbit;
 					m_instanceIdMask |= glshaderbit;
 				}
 				}
 				else if(glshader == GL_FRAGMENT_SHADER)
 				else if(glshader == GL_FRAGMENT_SHADER)
 				{
 				{
-					ANKI_CHECK(argsList.pushBackSprintf(m_alloc, 
+					ANKI_CHECK(argsList.pushBackSprintf(
 						"%s [vInstanceId]", &cstr[0]));
 						"%s [vInstanceId]", &cstr[0]));
 					
 					
 					m_instanceIdMask |= glshaderbit;
 					m_instanceIdMask |= glshaderbit;
@@ -701,7 +696,7 @@ Error MaterialProgramCreator::parseOperationTag(
 			else
 			else
 			{
 			{
 				ANKI_CHECK(argEl.getText(cstr));
 				ANKI_CHECK(argEl.getText(cstr));
-				ANKI_CHECK(argsList.pushBackSprintf(m_alloc, &cstr[0]));
+				ANKI_CHECK(argsList.pushBackSprintf(&cstr[0]));
 			}
 			}
 
 
 			// Advance
 			// Advance
@@ -710,45 +705,42 @@ Error MaterialProgramCreator::parseOperationTag(
 	}
 	}
 
 
 	// Now write everything
 	// Now write everything
-	MPStringList lines;
-	MPStringList::ScopeDestroyer linesd(&lines, m_alloc);
+	StringListAuto lines(m_alloc);
 
 
-	ANKI_CHECK(lines.pushBackSprintf(m_alloc,
-		"#if defined(%s_DEFINED)", &funcName[0]));
+	ANKI_CHECK(lines.pushBackSprintf("#if defined(%s_DEFINED)", &funcName[0]));
 
 
 	// Write the defines for the operationOuts
 	// Write the defines for the operationOuts
-	for(const MPString& arg : argsList)
+	for(const String& arg : argsList)
 	{
 	{
 		if(arg.find(OUT) == 0)
 		if(arg.find(OUT) == 0)
 		{
 		{
-			ANKI_CHECK(lines.pushBackSprintf(m_alloc,
+			ANKI_CHECK(lines.pushBackSprintf(
 				" && defined(%s_DEFINED)", &arg[0]));
 				" && defined(%s_DEFINED)", &arg[0]));
 		}
 		}
 	}
 	}
-	ANKI_CHECK(lines.pushBackSprintf(m_alloc, "\n"));
+	ANKI_CHECK(lines.pushBackSprintf("\n"));
 
 
 	if(!retTypeVoid)
 	if(!retTypeVoid)
 	{
 	{
 		ANKI_CHECK(retTypeEl.getText(cstr));
 		ANKI_CHECK(retTypeEl.getText(cstr));
-		ANKI_CHECK(lines.pushBackSprintf(m_alloc,
+		ANKI_CHECK(lines.pushBackSprintf(
 			"#\tdefine out%u_DEFINED\n"
 			"#\tdefine out%u_DEFINED\n"
 			"\t%s out%u = ", id, &cstr[0], id));
 			"\t%s out%u = ", id, &cstr[0], id));
 	}
 	}
 	else
 	else
 	{
 	{
-		ANKI_CHECK(lines.pushBackSprintf(m_alloc, "\t"));
+		ANKI_CHECK(lines.pushBackSprintf("\t"));
 	}
 	}
 	
 	
 	// write the "func(args...)" of "blah = func(args...)"
 	// write the "func(args...)" of "blah = func(args...)"
-	MPString argsStr;
-	MPString::ScopeDestroyer argsStrd(&argsStr, m_alloc);
+	StringAuto argsStr(m_alloc);
 
 
 	if(!argsList.isEmpty())
 	if(!argsList.isEmpty())
 	{
 	{
 		ANKI_CHECK(argsList.join(m_alloc, ", ", argsStr));
 		ANKI_CHECK(argsList.join(m_alloc, ", ", argsStr));
 	}
 	}
 
 
-	ANKI_CHECK(lines.pushBackSprintf(m_alloc, "%s(%s);\n#endif",
+	ANKI_CHECK(lines.pushBackSprintf("%s(%s);\n#endif",
 		&funcName[0], 
 		&funcName[0], 
 		(argsStr.isEmpty()) ? "" : &argsStr[0]));
 		(argsStr.isEmpty()) ? "" : &argsStr[0]));
 
 

+ 1 - 1
src/resource/Mesh.cpp

@@ -38,7 +38,7 @@ Error Mesh::load(const CString& filename, ResourceInitializer& init)
 	Error err = ErrorCode::NONE;
 	Error err = ErrorCode::NONE;
 
 
 	MeshLoader loader;
 	MeshLoader loader;
-	err = loader.load(init.m_tempAlloc, filename);
+	err = loader.load(&init.m_tempAlloc.getMemoryPool(), filename);
 	if(err) return err;
 	if(err) return err;
 
 
 	const MeshLoader::Header& header = loader.getHeader();
 	const MeshLoader::Header& header = loader.getHeader();

+ 2 - 2
src/resource/MeshLoader.cpp

@@ -20,10 +20,10 @@ MeshLoader::~MeshLoader()
 
 
 //==============================================================================
 //==============================================================================
 Error MeshLoader::load(
 Error MeshLoader::load(
-	TempResourceAllocator<U8> alloc,
+	BaseMemoryPool* pool,
 	const CString& filename)
 	const CString& filename)
 {
 {
-	m_alloc = alloc;
+	m_alloc = GenericPoolAllocator<U8, BaseMemoryPool>(pool);
 	
 	
 	Error err = loadInternal(filename);
 	Error err = loadInternal(filename);
 	if(err)
 	if(err)

+ 2 - 1
src/resource/Model.cpp

@@ -336,7 +336,8 @@ Error Model::load(const CString& filename, ResourceInitializer& init)
 			}
 			}
 
 
 			MeshLoader loader;
 			MeshLoader loader;
-			if(err = loader.load(init.m_tempAlloc, fixedFilename.toCString()))
+			if(err = loader.load(
+				&init.m_tempAlloc.getMemoryPool(), fixedFilename.toCString()))
 			{
 			{
 				fixedFilename.destroy(init.m_tempAlloc);
 				fixedFilename.destroy(init.m_tempAlloc);
 				return err;
 				return err;

+ 7 - 13
src/resource/ProgramPrePreprocessor.cpp

@@ -68,23 +68,20 @@ Error ProgramPrePreprocessor::parseFileForPragmas(
 	Error err = ErrorCode::NONE;
 	Error err = ErrorCode::NONE;
 
 
 	// load file in lines
 	// load file in lines
-	PPPString txt;
-	PPPString::ScopeDestroyer txtd(&txt, m_alloc);
-
-	PPPStringList lines;
-	PPPStringList::ScopeDestroyer linesd(&lines, m_alloc);
+	StringAuto txt(m_alloc);
+	StringListAuto lines(m_alloc);
 
 
 	File file;
 	File file;
 	ANKI_CHECK(file.open(filename, File::OpenFlag::READ));
 	ANKI_CHECK(file.open(filename, File::OpenFlag::READ));
 	ANKI_CHECK(file.readAllText(TempResourceAllocator<char>(m_alloc), txt));
 	ANKI_CHECK(file.readAllText(TempResourceAllocator<char>(m_alloc), txt));
-	ANKI_CHECK(lines.splitString(m_alloc, txt.toCString(), '\n'));
+	ANKI_CHECK(lines.splitString(txt.toCString(), '\n'));
 	if(lines.getSize() < 1)
 	if(lines.getSize() < 1)
 	{
 	{
 		ANKI_LOGE("File is empty: %s", &filename[0]);
 		ANKI_LOGE("File is empty: %s", &filename[0]);
 		return ErrorCode::USER_DATA;
 		return ErrorCode::USER_DATA;
 	}
 	}
 
 
-	for(const PPPString& line : lines)
+	for(const String& line : lines)
 	{
 	{
 		PtrSize npos = 0;
 		PtrSize npos = 0;
 
 
@@ -104,16 +101,13 @@ Error ProgramPrePreprocessor::parseFileForPragmas(
 
 
 				if(line.getLength() >= std::strlen(commands[6]) + 2)
 				if(line.getLength() >= std::strlen(commands[6]) + 2)
 				{
 				{
-					PPPString filen;
-					PPPString::ScopeDestroyer filend(&filen, m_alloc);
+					StringAuto filen(m_alloc);
 					
 					
 					ANKI_CHECK(filen.create(
 					ANKI_CHECK(filen.create(
-						m_alloc,
 						line.begin() + std::strlen(commands[6]), 
 						line.begin() + std::strlen(commands[6]), 
 						line.end() - 1));
 						line.end() - 1));
 
 
-					PPPString filenFixed;
-					PPPString::ScopeDestroyer filenFixedd(&filenFixed, m_alloc);
+					StringAuto filenFixed(m_alloc);
 
 
 					ANKI_CHECK(m_manager->fixResourceFilename(
 					ANKI_CHECK(m_manager->fixResourceFilename(
 						filen.toCString(), filenFixed));
 						filen.toCString(), filenFixed));
@@ -148,7 +142,7 @@ Error ProgramPrePreprocessor::parseFileForPragmas(
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-Error ProgramPrePreprocessor::parseType(const PPPString& line, Bool& found)
+Error ProgramPrePreprocessor::parseType(const String& line, Bool& found)
 {
 {
 	Error err = ErrorCode::NONE;
 	Error err = ErrorCode::NONE;
 	U i;
 	U i;

+ 3 - 3
src/resource/ResourceManager.cpp

@@ -103,18 +103,18 @@ Error ResourceManager::create(Initializer& init)
 //==============================================================================
 //==============================================================================
 Error ResourceManager::fixResourceFilename(
 Error ResourceManager::fixResourceFilename(
 	const CString& filename,
 	const CString& filename,
-	TempResourceString& out) const
+	StringAuto& out) const
 {
 {
 	Error err = ErrorCode::NONE;
 	Error err = ErrorCode::NONE;
 
 
 	// If the filename is in cache then dont append the data path
 	// If the filename is in cache then dont append the data path
 	if(filename.find(m_cacheDir.toCString()) != TempResourceString::NPOS)
 	if(filename.find(m_cacheDir.toCString()) != TempResourceString::NPOS)
 	{
 	{
-		err = out.create(m_tmpAlloc, filename);
+		err = out.create(filename);
 	}
 	}
 	else
 	else
 	{
 	{
-		err = out.sprintf(m_tmpAlloc, "%s%s", &m_dataDir[0], &filename[0]);
+		err = out.sprintf("%s%s", &m_dataDir[0], &filename[0]);
 	}
 	}
 
 
 	return err;
 	return err;

+ 15 - 24
src/resource/ShaderResource.cpp

@@ -31,14 +31,13 @@ Error ShaderResource::load(const CString& filename, const CString& extraSrc,
 	ANKI_CHECK(pars.parseFile(filename));
 	ANKI_CHECK(pars.parseFile(filename));
 	
 	
 	// Allocate new source
 	// Allocate new source
-	TempResourceString source;
-	TempResourceString::ScopeDestroyer sourced(&source, alloc);
+	StringAuto source(alloc);
 	if(extraSrc.getLength() > 0)
 	if(extraSrc.getLength() > 0)
 	{
 	{
-		ANKI_CHECK(source.create(alloc, extraSrc));
+		ANKI_CHECK(source.create(extraSrc));
 	}
 	}
 
 
-	ANKI_CHECK(source.append(alloc, pars.getShaderSource()));
+	ANKI_CHECK(source.append(pars.getShaderSource()));
 
 
 	// Create
 	// Create
 	GrManager& gr = manager.getGrManager();
 	GrManager& gr = manager.getGrManager();
@@ -62,37 +61,32 @@ Error ShaderResource::load(const CString& filename, const CString& extraSrc,
 Error ShaderResource::createToCache(
 Error ShaderResource::createToCache(
 	const CString& filename, const CString& preAppendedSrcCode, 
 	const CString& filename, const CString& preAppendedSrcCode, 
 	const CString& filenamePrefix, ResourceManager& manager,
 	const CString& filenamePrefix, ResourceManager& manager,
-	TempResourceString& out)
+	StringAuto& out)
 {
 {
 	Error err = ErrorCode::NONE;
 	Error err = ErrorCode::NONE;
 	auto alloc = manager._getTempAllocator();
 	auto alloc = manager._getTempAllocator();
 
 
 	if(preAppendedSrcCode.getLength() < 1)
 	if(preAppendedSrcCode.getLength() < 1)
 	{
 	{
-		return out.create(alloc, filename);
+		return out.create(filename);
 	}
 	}
 
 
 	// Create suffix
 	// Create suffix
-	TempResourceString unique;
-	TempResourceString::ScopeDestroyer uniqued(&unique, alloc);
+	StringAuto unique(alloc);
 
 
-	ANKI_CHECK(unique.create(alloc, filename));
-
-	ANKI_CHECK(unique.append(alloc, preAppendedSrcCode));
+	ANKI_CHECK(unique.create(filename));
+	ANKI_CHECK(unique.append(preAppendedSrcCode));
 
 
 	U64 h = computeHash(&unique[0], unique.getLength());
 	U64 h = computeHash(&unique[0], unique.getLength());
 
 
-	TempResourceString suffix;
-	TempResourceString::ScopeDestroyer suffixd(&suffix, alloc);
-	ANKI_CHECK(suffix.toString(alloc, h));
+	StringAuto suffix(alloc);
+	ANKI_CHECK(suffix.toString(h));
 
 
 	// Compose cached filename
 	// Compose cached filename
-	TempResourceString newFilename;
-	TempResourceString::ScopeDestroyer newFilenamed(&newFilename, alloc);
+	StringAuto newFilename(alloc);
 
 
 	ANKI_CHECK(
 	ANKI_CHECK(
 		newFilename.sprintf(
 		newFilename.sprintf(
-		alloc,
 		"%s/%s%s.glsl", 
 		"%s/%s%s.glsl", 
 		&manager._getCacheDirectory()[0],
 		&manager._getCacheDirectory()[0],
 		&filenamePrefix[0],
 		&filenamePrefix[0],
@@ -105,20 +99,17 @@ Error ShaderResource::createToCache(
 	}
 	}
 
 
 	// Read file and append code
 	// Read file and append code
-	TempResourceString src;
-	TempResourceString::ScopeDestroyer srcd(&src, alloc);
+	StringAuto src(alloc);
 
 
-	TempResourceString fixedFname;
-	TempResourceString::ScopeDestroyer fixedFnamed(&fixedFname, alloc);
+	StringAuto fixedFname(alloc);
 	ANKI_CHECK(manager.fixResourceFilename(filename, fixedFname));
 	ANKI_CHECK(manager.fixResourceFilename(filename, fixedFname));
 
 
 	File file;
 	File file;
 	ANKI_CHECK(file.open(fixedFname.toCString(), File::OpenFlag::READ));
 	ANKI_CHECK(file.open(fixedFname.toCString(), File::OpenFlag::READ));
 	ANKI_CHECK(file.readAllText(TempResourceAllocator<char>(alloc), src));
 	ANKI_CHECK(file.readAllText(TempResourceAllocator<char>(alloc), src));
 
 
-	TempResourceString srcfull;
-	TempResourceString::ScopeDestroyer srcfulld(&srcfull, alloc);
-	ANKI_CHECK(srcfull.sprintf(alloc, "%s%s", &preAppendedSrcCode[0], &src[0]));
+	StringAuto srcfull(alloc);
+	ANKI_CHECK(srcfull.sprintf("%s%s", &preAppendedSrcCode[0], &src[0]));
 
 
 	// Write cached file
 	// Write cached file
 	File f;
 	File f;

+ 255 - 142
src/scene/Sector.cpp

@@ -5,46 +5,181 @@
 
 
 #include "anki/scene/Sector.h"
 #include "anki/scene/Sector.h"
 #include "anki/scene/SpatialComponent.h"
 #include "anki/scene/SpatialComponent.h"
-#include "anki/scene/SceneNode.h"
-#include "anki/scene/RenderComponent.h"
-#include "anki/scene/Light.h"
-#include "anki/scene/Visibility.h"
 #include "anki/scene/FrustumComponent.h"
 #include "anki/scene/FrustumComponent.h"
+#include "anki/scene/MoveComponent.h"
 #include "anki/scene/SceneGraph.h"
 #include "anki/scene/SceneGraph.h"
 #include "anki/util/Logger.h"
 #include "anki/util/Logger.h"
-#include "anki/renderer/Renderer.h"
+#include "anki/resource/ResourceManager.h"
+#include "anki/resource/MeshLoader.h"
 
 
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-// Portal                                                                      =
+// PortalSectorBase                                                            =
 //==============================================================================
 //==============================================================================
 
 
 //==============================================================================
 //==============================================================================
-Portal::~Portal()
+PortalSectorBase::~PortalSectorBase()
 {
 {
-	auto alloc = m_group->getAllocator();
-	m_shapeStorage.destroy(alloc);
+	auto alloc = getSceneAllocator();
 
 
+	// Clean collision shape
 	if(m_shape)
 	if(m_shape)
 	{
 	{
 		alloc.deleteInstance(m_shape);
 		alloc.deleteInstance(m_shape);
 		m_shape = nullptr;
 		m_shape = nullptr;
 	}
 	}
+
+	m_shapeStorage.destroy(alloc);
+}
+
+//==============================================================================
+Error PortalSectorBase::create(const CString& name, const CString& modelFname)
+{
+	ANKI_CHECK(SceneNode::create(name));
+
+	// Create move component
+	SceneComponent* comp = 
+		getSceneAllocator().newInstance<MoveComponent>(this);
+	ANKI_CHECK_OOM(comp);
+
+	ANKI_CHECK(addComponent(comp, true));
+
+#if 0
+	// Load mesh 
+	TempResourceString newFname;
+	ANKI_CHECK(
+		getSceneGraph()._getResourceManager().fixResourceFilename(
+		modelFname, newFname));
+
+	MeshLoader loader;
+	ANKI_CHECK(loader.load(
+		getSceneGraph()._getResourceManager()._getTempAllocator(),
+		newFname.toCString()));
+
+	// Create shape
+	MeshLoader::Header& header = loader.getHeader();
+	U vertCount = header.m_totalVerticesCount;
+
+	m_shape = getSectorGroup().createConvexHull(vertPositions, m_shapeStorage);
+	ANKI_CHECK_OOM(m_shape);
+#endif
+
+	return ErrorCode::NONE;
+}
+
+//==============================================================================
+SectorGroup& PortalSectorBase::getSectorGroup()
+{
+	return getSceneGraph().getSectorGroup();
+}
+
+//==============================================================================
+// Portal                                                                      =
+//==============================================================================
+
+//==============================================================================
+Portal::~Portal()
+{
+	auto alloc = getSceneAllocator();
+
+	// Remove from sectors
+	for(Sector* s : m_sectors)
+	{
+		s->tryRemovePortal(this);
+	}
+
+	m_sectors.destroy(getSceneAllocator());
+
+	// Remove from group
+	auto& portals = getSectorGroup().m_portals;
+	auto it = portals.getBegin();
+	auto end = portals.getBegin();
+	for(; it != end; ++it)
+	{
+		if(*it == this)
+		{
+			portals.erase(getSceneAllocator(), it);
+			break;
+		}
+	}
+}
+
+//==============================================================================
+Error Portal::create(const CString& name, const CString& modelFname)
+{
+	ANKI_CHECK(PortalSectorBase::create(name, modelFname));
+	ANKI_CHECK(getSectorGroup().m_portals.pushBack(getSceneAllocator(), this));
+	return ErrorCode::NONE;
+}
+
+//==============================================================================
+Error Portal::frameUpdate(F32 prevUpdateTime, F32 crntTime)
+{
+	MoveComponent& move = getComponent<MoveComponent>();
+	if(move.getTimestamp() == getGlobalTimestamp())
+	{
+		// Move comp updated. Inform the group
+		
+		SectorGroup& group = getSectorGroup();
+
+		// Gather the sectors it collides
+		auto it = group.m_sectors.getBegin();
+		auto end = group.m_sectors.getEnd();
+
+		for(; it != end; ++it)
+		{
+			Sector* sector = *it;
+
+			Bool collide = testCollisionShapes(
+				*m_shape, sector->getBoundingShape());
+
+			if(collide)
+			{
+				ANKI_CHECK(tryAddSector(sector));
+				ANKI_CHECK(sector->tryAddPortal(this));
+			}
+			else
+			{
+				tryRemoveSector(sector);
+				sector->tryRemovePortal(this);
+			}
+		}
+	}
+
+	return ErrorCode::NONE;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-Error Portal::create(const SArray<Vec4>& vertPositions)
+Error Portal::tryAddSector(Sector* sector)
 {
 {
-	m_shape = m_group->createConvexHull(vertPositions, m_shapeStorage);
-	return m_shape ? ErrorCode::NONE : ErrorCode::OUT_OF_MEMORY;
+	auto it = m_sectors.getBegin();
+	auto end = m_sectors.getEnd();
+	for(; it != end; ++it)
+	{
+		if(*it == sector)
+		{
+			// Already there, return
+			return ErrorCode::NONE;
+		}
+	}
+
+	return m_sectors.pushBack(getSceneAllocator(), sector);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-Error Portal::addSector(Sector* sector)
+void Portal::tryRemoveSector(Sector* sector)
 {
 {
-	ANKI_ASSERT(sector);
-	return m_sectors.pushBack(m_group->getAllocator(), sector);
+	auto it = m_sectors.getBegin();
+	auto end = m_sectors.getEnd();
+	for(; it != end; ++it)
+	{
+		if(*it == sector)
+		{
+			m_sectors.erase(getSceneAllocator(), it);
+			break;
+		}
+	}
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -54,30 +189,79 @@ Error Portal::addSector(Sector* sector)
 //==============================================================================
 //==============================================================================
 Sector::~Sector()
 Sector::~Sector()
 {
 {
-	auto alloc = m_group->getAllocator();
+	auto alloc = getSceneAllocator();
 
 
-	if(m_shape)
+	// Remove portals
+	for(Portal* p : m_portals)
 	{
 	{
-		alloc.deleteInstance(m_shape);
-		m_shape = nullptr;
+		p->tryRemoveSector(this);
 	}
 	}
 
 
 	m_portals.destroy(alloc);
 	m_portals.destroy(alloc);
-	m_spatials.destroy(alloc);
+
+	// Remove spatials
+	U spatialsCount = m_spatials.getSize();
+	while(spatialsCount-- != 0) // Use counter
+	{
+		tryRemoveSpatialComponent(m_spatials.getFront());
+	}
+
+	// Remove from group
+	auto& sectors = getSectorGroup().m_sectors;
+	auto it = sectors.getBegin();
+	auto end = sectors.getBegin();
+	for(; it != end; ++it)
+	{
+		if(*it == this)
+		{
+			sectors.erase(getSceneAllocator(), it);
+			break;
+		}
+	}
+}
+
+//==============================================================================
+Error Sector::create(const CString& name, const CString& modelFname)
+{
+	ANKI_CHECK(PortalSectorBase::create(name, modelFname));
+	ANKI_CHECK(getSectorGroup().m_sectors.pushBack(getSceneAllocator(), this));
+	return ErrorCode::NONE;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-Error Sector::create(const SArray<Vec4>& vertPositions)
+Error Sector::tryAddPortal(Portal* portal)
 {
 {
-	m_shape = m_group->createConvexHull(vertPositions, m_shapeStorage);
-	return m_shape ? ErrorCode::NONE : ErrorCode::OUT_OF_MEMORY;
+	ANKI_ASSERT(portal);
+
+	auto it = m_portals.getBegin();
+	auto end = m_portals.getEnd();
+	for(; it != end; ++it)
+	{
+		if(*it == portal)
+		{
+			// Already there, return
+			return ErrorCode::NONE;
+		}
+	}
+
+	return m_portals.pushBack(getSceneAllocator(), portal);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-Error Sector::addPortal(Portal* portal)
+void Sector::tryRemovePortal(Portal* portal)
 {
 {
 	ANKI_ASSERT(portal);
 	ANKI_ASSERT(portal);
-	return m_portals.pushBack(m_group->getAllocator(), portal);
+
+	auto it = m_portals.getBegin();
+	auto end = m_portals.getEnd();
+	for(; it != end; ++it)
+	{
+		if(*it == portal)
+		{
+			m_portals.erase(getSceneAllocator(), it);
+			break;
+		}
+	}
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -92,27 +276,26 @@ Error Sector::tryAddSpatialComponent(SpatialComponent* sp)
 	{
 	{
 		if(*itsp == this)
 		if(*itsp == this)
 		{
 		{
-			break;
+			// Found, return
+#if ANKI_ASSERTIONS
+			LockGuard<SpinLock> g(m_lock);
+			ANKI_ASSERT(findSpatialComponent(sp) != m_spatials.getEnd()
+				&& "Spatial has reference to sector but sector not");
+#endif
+			return ErrorCode::NONE;
 		}
 		}
 	}
 	}
 	
 	
-	Error err = ErrorCode::NONE;
-	if(itsp == endsp)
-	{
-		// Not found, add it
+	// Lock since this might be done from a thread
+	LockGuard<SpinLock> g(m_lock);
 
 
-		// Lock since this might be done from a thread
-		LockGuard<SpinLock> g(m_lock);
-
-		ANKI_ASSERT(findSpatialComponent(sp) == m_spatials.getEnd());
+	ANKI_ASSERT(findSpatialComponent(sp) == m_spatials.getEnd());
 
 
-		m_dirty = true;
-		Error err = m_spatials.pushBack(m_group->getAllocator(), sp);
+	Error err = m_spatials.pushBack(getSceneAllocator(), sp);
 
 
-		if(!err)
-		{
-			err = sp->getSectorInfo().pushBack(m_group->getAllocator(), this);
-		}
+	if(!err)
+	{
+		err = sp->getSectorInfo().pushBack(getSceneAllocator(), this);
 	}
 	}
 
 
 	return err;
 	return err;
@@ -138,16 +321,20 @@ void Sector::tryRemoveSpatialComponent(SpatialComponent* sp)
 	{
 	{
 		// Found, remove
 		// Found, remove
 
 
-		// Lock since this might be dont from a thread
-		LockGuard<SpinLock> g(m_lock);
-
-		m_dirty = true;
+		sp->getSectorInfo().erase(getSceneAllocator(), itsp);
 
 
-		sp->getSectorInfo().erase(m_group->getAllocator(), itsp);
+		LockGuard<SpinLock> g(m_lock);
 
 
 		auto it = findSpatialComponent(sp);
 		auto it = findSpatialComponent(sp);
 		ANKI_ASSERT(it != m_spatials.getEnd());
 		ANKI_ASSERT(it != m_spatials.getEnd());
-		m_spatials.erase(m_group->getAllocator(), it);
+		m_spatials.erase(getSceneAllocator(), it);
+	}
+	else
+	{
+#if ANKI_ASSERTIONS
+		LockGuard<SpinLock> g(m_lock);
+		ANKI_ASSERT(findSpatialComponent(sp) == m_spatials.getEnd());
+#endif
 	}
 	}
 }
 }
 
 
@@ -170,112 +357,34 @@ List<SpatialComponent*>::Iterator Sector::findSpatialComponent(
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-// SectorGroup                                                                 =
-//==============================================================================
-
-//==============================================================================
-ConvexHullShape* SectorGroup::createConvexHull(
-	const SArray<Vec4>& vertPositions, DArray<Vec4>& shapeStorage)
+Error Sector::frameUpdate(F32 prevUpdateTime, F32 crntTime)
 {
 {
-	Error err = ErrorCode::NONE;
-
-	auto alloc = getAllocator();
-	U vertCount = vertPositions.getSize();
-	ANKI_ASSERT(vertCount >= 4 && "Minimum shape should be tetrahedron");
-
-	// Create hull
-	ConvexHullShape* hull = alloc.newInstance<ConvexHullShape>();
-	if(!hull)
+	MoveComponent& move = getComponent<MoveComponent>();
+	if(move.getTimestamp() == getGlobalTimestamp())
 	{
 	{
-		err = ErrorCode::OUT_OF_MEMORY;
-	}
-
-	// Alloc storage
-	if(!err)
-	{
-		err = shapeStorage.create(alloc, vertCount);
-	}
-
-	// Assign storage to hull
-	if(!err)
-	{
-		memcpy(&shapeStorage[0], &vertPositions[0], sizeof(Vec4) * vertCount);
-		hull->initStorage(&shapeStorage[0], vertCount);
-	}
-
-	// Cleanup on error
-	if(err)
-	{
-		shapeStorage.destroy(alloc);
+		// Move comp updated. Inform the group
 		
 		
-		if(hull)
-		{
-			alloc.deleteInstance(hull);
-			hull = nullptr;
-		}
-	}
-
-	return hull;
-}
+		SectorGroup& group = getSectorGroup();
 
 
-//==============================================================================
-Sector* SectorGroup::createNewSector(const SArray<Vec4>& vertexPositions)
-{
-	Sector* sector = getAllocator().newInstance<Sector>(this);
-	if(sector)
-	{
-		Error err = sector->create(vertexPositions);
-		if(err)
+		// Gather the portals it collides
+		auto it = group.m_portals.getBegin();
+		auto end = group.m_portals.getEnd();
+		for(; it != end; ++it)
 		{
 		{
-			getAllocator().deleteInstance(sector);
-			sector = nullptr;
-		}
-	}
-
-	return sector;
-}
-
-//==============================================================================
-Portal* SectorGroup::createNewPortal(const SArray<Vec4>& vertexPositions)
-{
-	Portal* portal = getAllocator().newInstance<Portal>(this);
-	if(portal)
-	{
-		Error err = portal->create(vertexPositions);
-		if(err)
-		{
-			getAllocator().deleteInstance(portal);
-			portal = nullptr;
-		}
-	}
-
-	return portal;
-}
-
-//==============================================================================
-Error SectorGroup::bake()
-{
-	// Connect portals with sectors
-	auto it = m_portals.getBegin();
-	auto end = m_portals.getEnd();
-	for(; it != end; ++it)
-	{
-		Portal& portal = *(*it);
-
-		auto sit = m_sectors.getBegin();
-		auto send = m_sectors.getEnd();
-
-		for(; sit != send; ++sit)
-		{
-			Sector& sector = *(*sit);
+			Portal* portal = *it;
 
 
 			Bool collide = testCollisionShapes(
 			Bool collide = testCollisionShapes(
-				portal.getBoundingShape(), sector.getBoundingShape());
+				*m_shape, portal->getBoundingShape());
 
 
 			if(collide)
 			if(collide)
 			{
 			{
-				ANKI_CHECK(portal.addSector(&sector));
-				ANKI_CHECK(sector.addPortal(&portal));
+				ANKI_CHECK(portal->tryAddSector(this));
+				ANKI_CHECK(tryAddPortal(portal));
+			}
+			else
+			{
+				portal->tryRemoveSector(this);
+				tryRemovePortal(portal);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -283,6 +392,10 @@ Error SectorGroup::bake()
 	return ErrorCode::NONE;
 	return ErrorCode::NONE;
 }
 }
 
 
+//==============================================================================
+// SectorGroup                                                                 =
+//==============================================================================
+
 //==============================================================================
 //==============================================================================
 Error SectorGroup::spatialUpdated(SpatialComponent* sp)
 Error SectorGroup::spatialUpdated(SpatialComponent* sp)
 {
 {