Pārlūkot izejas kodu

Refactored ResourceHandle a bit to make it easier to understand and use

Marko Pintera 12 gadi atpakaļ
vecāks
revīzija
32ed0bb976

+ 7 - 7
CamelotClient/CamelotClient.cpp

@@ -272,7 +272,7 @@ int CALLBACK WinMain(
 
 
 	//Cursor::setCustomCursor(*cursorPixelData, Int2(0, 0));
 	//Cursor::setCustomCursor(*cursorPixelData, Int2(0, 0));
 
 
-	dbgCursor.reset();
+	dbgCursor = nullptr;
 
 
 	/************************************************************************/
 	/************************************************************************/
 	/* 								EDITOR INIT                      		*/
 	/* 								EDITOR INIT                      		*/
@@ -304,7 +304,7 @@ int CALLBACK WinMain(
 
 
 	//testMaterial->destroy();
 	//testMaterial->destroy();
 #ifdef DX11
 #ifdef DX11
-	gpuProgInclude.reset();
+	gpuProgInclude = nullptr;
 #endif
 #endif
 
 
 	gResources().unload(testTexRef);
 	gResources().unload(testTexRef);
@@ -313,11 +313,11 @@ int CALLBACK WinMain(
 	gResources().unload(vertProgRef);
 	gResources().unload(vertProgRef);
 	gResources().unload(testMaterial);
 	gResources().unload(testMaterial);
 
 
-	testMaterial.reset();
-	testTexRef.reset();
-	dbgMeshRef.reset();
-	fragProgRef.reset();
-	vertProgRef.reset();
+	testMaterial = nullptr;
+	testTexRef = nullptr;
+	dbgMeshRef = nullptr;
+	fragProgRef = nullptr;
+	vertProgRef = nullptr;
 
 
 	testModelGO->destroy();
 	testModelGO->destroy();
 
 

+ 47 - 46
CamelotCore/Include/CmResourceHandle.h

@@ -36,44 +36,33 @@ namespace CamelotFramework
 		/**
 		/**
 		 * @brief	Returns the UUID of the resource the handle is referring to.
 		 * @brief	Returns the UUID of the resource the handle is referring to.
 		 */
 		 */
-		const String& getUUID() const { return mData->mUUID; }
+		const String& getUUID() const { return mData != nullptr ? mData->mUUID : StringUtil::BLANK; }
 
 
 		/**
 		/**
 		 * @brief	Gets the handle data. For internal use only.
 		 * @brief	Gets the handle data. For internal use only.
 		 */
 		 */
-		std::shared_ptr<ResourceHandleData> getHandleData() const { return mData; }
+		const std::shared_ptr<ResourceHandleData>& getHandleData() const { return mData; }
 
 
 	protected:
 	protected:
 		ResourceHandleBase();
 		ResourceHandleBase();
 
 
 		std::shared_ptr<ResourceHandleData> mData;
 		std::shared_ptr<ResourceHandleData> mData;
 
 
-		void init(Resource* ptr);
-		void init(std::shared_ptr<Resource> ptr);
+		/**
+		 * @brief	Sets the created flag to true and assigns the resource pointer. Called
+		 * 			by the constructors, or if you constructed just using a UUID, then you need to
+		 * 			call this manually before you can access the resource from this handle.
+		 * 			
+		 * @note	Two set construction is sometimes required due to multithreaded nature of resource loading.
+		 */
+		void setResourcePtr(std::shared_ptr<Resource> ptr);
 
 
-		template <typename T1>
-		void init(const ResourceHandle<T1>& ptr)
-		{
-			mData = ptr.mData;
-		}
 	private:
 	private:
 		friend class Resources;
 		friend class Resources;
 
 
 		CM_STATIC_THREAD_SYNCHRONISER(mResourceCreatedCondition)
 		CM_STATIC_THREAD_SYNCHRONISER(mResourceCreatedCondition)
 		CM_STATIC_MUTEX(mResourceCreatedMutex)
 		CM_STATIC_MUTEX(mResourceCreatedMutex)
 
 
-		/**
-		 * @brief	Sets the created flag to true. Should only be called
-		 * 			by Resources class after loading of the resource is fully done.
-		 */
-		void resolve(std::shared_ptr<Resource> ptr);
-
-		/**
-		 * @brief	Sets an uuid of the ResourceHandle. Should only be called by
-		 * 			Resources class.
-		 */
-		void ResourceHandleBase::setUUID(const String& uuid);
-
 	protected:
 	protected:
 		inline void throwIfNotLoaded() const;
 		inline void throwIfNotLoaded() const;
 
 
@@ -92,7 +81,16 @@ namespace CamelotFramework
 	public:
 	public:
 		ResourceHandle()
 		ResourceHandle()
 			:ResourceHandleBase()
 			:ResourceHandleBase()
-		{	}
+		{ }
+
+		// Note: This constructor requires you to call "resolve" with the actual resource pointer,
+		// before the resource is considered as loaded
+		ResourceHandle(const String& uuid)
+			:ResourceHandleBase()
+		{
+			mData = cm_shared_ptr<ResourceHandleData, PoolAlloc>();
+			mData->mUUID = uuid;
+		}
 
 
 		template <typename T1>
 		template <typename T1>
 		ResourceHandle(const ResourceHandle<T1>& ptr)
 		ResourceHandle(const ResourceHandle<T1>& ptr)
@@ -106,29 +104,13 @@ namespace CamelotFramework
 			return ResourceHandle<Resource>(*this); 
 			return ResourceHandle<Resource>(*this); 
 		}
 		}
 
 
-		// TODO Low priority - User can currently try to access these even if resource ptr is not resolved
-		T* get() const 
-		{ 
-			throwIfNotLoaded();
-
-			return reinterpret_cast<T*>(mData->mPtr.get()); 
-		}
 		T* operator->() const { return get(); }
 		T* operator->() const { return get(); }
 		T& operator*() const { return *get(); }
 		T& operator*() const { return *get(); }
 
 
-		std::shared_ptr<T> getInternalPtr() const
-		{ 
-			throwIfNotLoaded();
-
-			return std::static_pointer_cast<T>(mData->mPtr); 
-		}
-
-		/**
-		 * @brief	Releases the reference held by this handle.
-		 */
-		void reset()
-		{
-			mData = cm_shared_ptr<ResourceHandleData, ScratchAlloc>();
+		ResourceHandle<T>& operator=(std::nullptr_t ptr)
+		{ 	
+			mData = nullptr;
+			return *this;
 		}
 		}
 
 
 		template<class _Ty>
 		template<class _Ty>
@@ -141,7 +123,21 @@ namespace CamelotFramework
 		// (Why not just directly convert to bool? Because then we can assign pointer to bool and that's weird)
 		// (Why not just directly convert to bool? Because then we can assign pointer to bool and that's weird)
 		operator int CM_Bool_struct<T>::*() const
 		operator int CM_Bool_struct<T>::*() const
 		{
 		{
-			return (((mData->mPtr != nullptr)) ? &CM_Bool_struct<T>::_Member : 0);
+			return ((mData != nullptr && mData->mPtr != nullptr) ? &CM_Bool_struct<T>::_Member : 0);
+		}
+
+		T* get() const 
+		{ 
+			throwIfNotLoaded();
+
+			return reinterpret_cast<T*>(mData->mPtr.get()); 
+		}
+
+		std::shared_ptr<T> getInternalPtr() const
+		{ 
+			throwIfNotLoaded();
+
+			return std::static_pointer_cast<T>(mData->mPtr); 
 		}
 		}
 
 
 	private:
 	private:
@@ -150,13 +146,15 @@ namespace CamelotFramework
 		explicit ResourceHandle(T* ptr)
 		explicit ResourceHandle(T* ptr)
 			:ResourceHandleBase()
 			:ResourceHandleBase()
 		{
 		{
-			init(ptr);
+			mData = cm_shared_ptr<ResourceHandleData, PoolAlloc>();
+			setResourcePtr(std::shared_ptr<Resource>(ptr));
 		}
 		}
 
 
 		ResourceHandle(std::shared_ptr<T> ptr)
 		ResourceHandle(std::shared_ptr<T> ptr)
 			:ResourceHandleBase()
 			:ResourceHandleBase()
 		{
 		{
-			init(ptr);
+			mData = cm_shared_ptr<ResourceHandleData, PoolAlloc>();
+			setResourcePtr(ptr);
 		}
 		}
 	};
 	};
 
 
@@ -169,7 +167,10 @@ namespace CamelotFramework
 	template<class _Ty1, class _Ty2>
 	template<class _Ty1, class _Ty2>
 	bool operator==(const ResourceHandle<_Ty1>& _Left, const ResourceHandle<_Ty2>& _Right)
 	bool operator==(const ResourceHandle<_Ty1>& _Left, const ResourceHandle<_Ty2>& _Right)
 	{	
 	{	
-		return (_Left.get() == _Right.get());
+		if(_Left.getHandleData() != nullptr && _Right.getHandleData() != nullptr)
+			return _Left.getHandleData()->mPtr == _Right.getHandleData()->mPtr;
+
+		return _Left.getHandleData() == _Right.getHandleData();
 	}
 	}
 
 
 	template<class _Ty1, class _Ty2>
 	template<class _Ty1, class _Ty2>

+ 12 - 3
CamelotCore/Include/CmResourceHandleRTTI.h

@@ -10,7 +10,13 @@ namespace CamelotFramework
 	class CM_EXPORT ResourceHandleRTTI : public RTTIType<ResourceHandleBase, IReflectable, ResourceHandleRTTI>
 	class CM_EXPORT ResourceHandleRTTI : public RTTIType<ResourceHandleBase, IReflectable, ResourceHandleRTTI>
 	{
 	{
 	private:
 	private:
-		String& getUUID(ResourceHandleBase* obj) { return obj->mData->mUUID; }
+		String& getUUID(ResourceHandleBase* obj) 
+		{ 
+			static String Blank = "";
+
+			return obj->mData != nullptr ? obj->mData->mUUID : Blank; 
+		}
+
 		void setUUID(ResourceHandleBase* obj, String& uuid) { obj->mData->mUUID = uuid; } 
 		void setUUID(ResourceHandleBase* obj, String& uuid) { obj->mData->mUUID = uuid; } 
 	public:
 	public:
 		ResourceHandleRTTI()
 		ResourceHandleRTTI()
@@ -29,7 +35,7 @@ namespace CamelotFramework
 				HResource loadedResource = gResources().loadFromUUID(resourceHandle->mData->mUUID);
 				HResource loadedResource = gResources().loadFromUUID(resourceHandle->mData->mUUID);
 
 
 				if(loadedResource)
 				if(loadedResource)
-					resourceHandle->resolve(loadedResource.getInternalPtr());
+					resourceHandle->setResourcePtr(loadedResource.getInternalPtr());
 			}
 			}
 		}
 		}
 
 
@@ -46,7 +52,10 @@ namespace CamelotFramework
 
 
 		virtual std::shared_ptr<IReflectable> newRTTIObject()
 		virtual std::shared_ptr<IReflectable> newRTTIObject()
 		{
 		{
-			return cm_shared_ptr<ResourceHandleBase, PoolAlloc>(new (cm_alloc<ResourceHandleBase, PoolAlloc>()) ResourceHandleBase());
+			std::shared_ptr<ResourceHandleBase> obj = cm_shared_ptr<ResourceHandleBase, PoolAlloc>(new (cm_alloc<ResourceHandleBase, PoolAlloc>()) ResourceHandleBase());
+			obj->mData = cm_shared_ptr<ResourceHandleData>();
+
+			return obj;
 		}
 		}
 	};
 	};
 }
 }

+ 5 - 7
CamelotCore/Include/CmTextData.h

@@ -113,7 +113,7 @@ namespace CamelotFramework
 		CM_EXPORT UINT32 getNumPages() const { return mNumPageInfos; }
 		CM_EXPORT UINT32 getNumPages() const { return mNumPageInfos; }
 
 
 		CM_EXPORT const TextLine& getLine(UINT32 idx) const { return mLines[idx]; }
 		CM_EXPORT const TextLine& getLine(UINT32 idx) const { return mLines[idx]; }
-		CM_EXPORT const HTexture& getTextureForPage(UINT32 page) const { return mPageInfos[page].texture; }
+		CM_EXPORT const HTexture& getTextureForPage(UINT32 page) const;
 		CM_EXPORT UINT32 getNumQuadsForPage(UINT32 page) const { return mPageInfos[page].numQuads; }
 		CM_EXPORT UINT32 getNumQuadsForPage(UINT32 page) const { return mPageInfos[page].numQuads; }
 
 
 		CM_EXPORT UINT32 getWidth() const;
 		CM_EXPORT UINT32 getWidth() const;
@@ -122,9 +122,9 @@ namespace CamelotFramework
 	private:
 	private:
 		friend class TextLine;
 		friend class TextLine;
 
 
-		INT32 getBaselineOffset() const { return mBaselineOffset; }
-		UINT32 getLineHeight() const { return mLineHeight; }
-		UINT32 getSpaceWidth() const { return mSpaceWidth; }
+		INT32 getBaselineOffset() const;
+		UINT32 getLineHeight() const;
+		UINT32 getSpaceWidth() const;
 
 
 		const CHAR_DESC& getChar(UINT32 idx) const { return *mChars[idx]; }
 		const CHAR_DESC& getChar(UINT32 idx) const { return *mChars[idx]; }
 		const TextWord& getWord(UINT32 idx) const { return mWords[idx]; }
 		const TextWord& getWord(UINT32 idx) const { return mWords[idx]; }
@@ -145,9 +145,7 @@ namespace CamelotFramework
 		void* mData;
 		void* mData;
 
 
 		HFont mFont;
 		HFont mFont;
-		INT32 mBaselineOffset;
-		UINT32 mLineHeight;
-		UINT32 mSpaceWidth;
+		const FontData* mFontData;
 
 
 		// Static buffers
 		// Static buffers
 	private:
 	private:

+ 6 - 18
CamelotCore/Source/CmResourceHandle.cpp

@@ -11,16 +11,19 @@ namespace CamelotFramework
 
 
 	ResourceHandleBase::ResourceHandleBase()
 	ResourceHandleBase::ResourceHandleBase()
 	{
 	{
-		mData = cm_shared_ptr<ResourceHandleData, PoolAlloc>();
+		mData = nullptr;
 	}
 	}
 
 
 	bool ResourceHandleBase::isLoaded() const 
 	bool ResourceHandleBase::isLoaded() const 
 	{ 
 	{ 
-		return (mData->mIsCreated && mData->mPtr != nullptr); 
+		return (mData != nullptr && mData->mIsCreated && mData->mPtr != nullptr); 
 	}
 	}
 
 
 	void ResourceHandleBase::synchronize() const
 	void ResourceHandleBase::synchronize() const
 	{
 	{
+		if(mData == nullptr)
+			return;
+
 		if(!mData->mIsCreated)
 		if(!mData->mIsCreated)
 		{
 		{
 			CM_LOCK_MUTEX_NAMED(mResourceCreatedMutex, lock);
 			CM_LOCK_MUTEX_NAMED(mResourceCreatedMutex, lock);
@@ -33,22 +36,7 @@ namespace CamelotFramework
 		mData->mPtr->synchonize();
 		mData->mPtr->synchonize();
 	}
 	}
 
 
-	void ResourceHandleBase::resolve(std::shared_ptr<Resource> ptr) 
-	{ 
-		init(ptr);
-	}
-
-	void ResourceHandleBase::setUUID(const String& uuid) 
-	{ 
-		mData->mUUID = uuid;
-	}
-
-	void ResourceHandleBase::init(Resource* ptr)
-	{
-		init(std::shared_ptr<Resource>(ptr));
-	}
-
-	void ResourceHandleBase::init(std::shared_ptr<Resource> ptr)
+	void ResourceHandleBase::setResourcePtr(std::shared_ptr<Resource> ptr)
 	{
 	{
 		mData->mPtr = ptr;
 		mData->mPtr = ptr;
 
 

+ 2 - 3
CamelotCore/Source/CmResources.cpp

@@ -45,7 +45,7 @@ namespace CamelotFramework
 			
 			
 			// This should be thread safe without any sync primitives, if other threads read a few cycles out of date value
 			// This should be thread safe without any sync primitives, if other threads read a few cycles out of date value
 			// and think this resource isn't created when it really is, it hardly makes any difference
 			// and think this resource isn't created when it really is, it hardly makes any difference
-			resRequest->resource.resolve(resResponse->rawResource);
+			resRequest->resource.setResourcePtr(resResponse->rawResource);
 
 
 			if(!gResources().metaExists_UUID(resResponse->rawResource->getUUID()))
 			if(!gResources().metaExists_UUID(resResponse->rawResource->getUUID()))
 			{
 			{
@@ -201,8 +201,7 @@ namespace CamelotFramework
 			return HResource();
 			return HResource();
 		}
 		}
 
 
-		HResource newResource;
-		newResource.setUUID(uuid); // UUID needs to be set immediately if the resource gets loaded async
+		HResource newResource(uuid);
 
 
 		ResourceLoadRequestPtr resRequest = cm_shared_ptr<Resources::ResourceLoadRequest, ScratchAlloc>();
 		ResourceLoadRequestPtr resRequest = cm_shared_ptr<Resources::ResourceLoadRequest, ScratchAlloc>();
 		resRequest->filePath = filePath;
 		resRequest->filePath = filePath;

+ 32 - 20
CamelotCore/Source/CmTextData.cpp

@@ -304,35 +304,31 @@ namespace CamelotFramework
 	}
 	}
 
 
 	TextData::TextData(const WString& text, const HFont& font, UINT32 fontSize, UINT32 width, UINT32 height, bool wordWrap)
 	TextData::TextData(const WString& text, const HFont& font, UINT32 fontSize, UINT32 width, UINT32 height, bool wordWrap)
-		:mFont(font), mBaselineOffset(0), mLineHeight(0), mSpaceWidth(0), mChars(nullptr),
+		:mFont(font), mChars(nullptr), mFontData(nullptr),
 		mNumChars(0), mWords(nullptr), mNumWords(0), mLines(nullptr), mNumLines(0), mPageInfos(nullptr), mNumPageInfos(0), mData(nullptr)
 		mNumChars(0), mWords(nullptr), mNumWords(0), mLines(nullptr), mNumLines(0), mPageInfos(nullptr), mNumPageInfos(0), mData(nullptr)
 	{
 	{
 		// In order to reduce number of memory allocations algorithm first calculates data into temporary buffers and then copies the results
 		// In order to reduce number of memory allocations algorithm first calculates data into temporary buffers and then copies the results
 		initAlloc();
 		initAlloc();
 
 
-		const FontData* fontData = nullptr;
 		if(font != nullptr)
 		if(font != nullptr)
 		{
 		{
 			UINT32 nearestSize = font->getClosestAvailableSize(fontSize);
 			UINT32 nearestSize = font->getClosestAvailableSize(fontSize);
-			fontData = font->getFontDataForSize(nearestSize);
+			mFontData = font->getFontDataForSize(nearestSize);
 		}
 		}
 
 
-		if(fontData == nullptr || fontData->texturePages.size() == 0)
+		if(mFontData == nullptr || mFontData->texturePages.size() == 0)
 			return;
 			return;
 
 
-		if(fontData->size != fontSize)
+		if(mFontData->size != fontSize)
 		{
 		{
-			LOGWRN("Unable to find font with specified size (" + toString(fontSize) + "). Using nearest available size: " + toString(fontData->size));
+			LOGWRN("Unable to find font with specified size (" + toString(fontSize) + "). Using nearest available size: " + toString(mFontData->size));
 		}
 		}
 
 
 		bool widthIsLimited = width > 0;
 		bool widthIsLimited = width > 0;
 		mFont = font;
 		mFont = font;
-		mBaselineOffset = fontData->fontDesc.baselineOffset;
-		mLineHeight = fontData->fontDesc.lineHeight;
-		mSpaceWidth = fontData->fontDesc.spaceWidth;
 
 
 		UINT32 curLineIdx = allocLine(this);
 		UINT32 curLineIdx = allocLine(this);
-		UINT32 curHeight = fontData->fontDesc.lineHeight;
+		UINT32 curHeight = mFontData->fontDesc.lineHeight;
 		UINT32 charIdx = 0;
 		UINT32 charIdx = 0;
 
 
 		while(true)
 		while(true)
@@ -341,7 +337,7 @@ namespace CamelotFramework
 				break;
 				break;
 
 
 			UINT32 charId = text[charIdx];
 			UINT32 charId = text[charIdx];
-			const CHAR_DESC& charDesc = fontData->getCharDesc(charId);
+			const CHAR_DESC& charDesc = mFontData->getCharDesc(charId);
 
 
 			TextLine* curLine = &LineBuffer[curLineIdx];
 			TextLine* curLine = &LineBuffer[curLineIdx];
 
 
@@ -352,7 +348,7 @@ namespace CamelotFramework
 				curLineIdx = allocLine(this);
 				curLineIdx = allocLine(this);
 				curLine = &LineBuffer[curLineIdx];
 				curLine = &LineBuffer[curLineIdx];
 
 
-				curHeight += fontData->fontDesc.lineHeight;
+				curHeight += mFontData->fontDesc.lineHeight;
 
 
 				charIdx++;
 				charIdx++;
 				continue;
 				continue;
@@ -361,12 +357,12 @@ namespace CamelotFramework
 			if(charId != SPACE_CHAR)
 			if(charId != SPACE_CHAR)
 			{
 			{
 				curLine->add(charIdx, charDesc);
 				curLine->add(charIdx, charDesc);
-				addCharToPage(charDesc.page, *fontData);
+				addCharToPage(charDesc.page, *mFontData);
 			}
 			}
 			else
 			else
 			{
 			{
 				curLine->addSpace();
 				curLine->addSpace();
-				addCharToPage(0, *fontData);
+				addCharToPage(0, *mFontData);
 			}
 			}
 
 
 			if(widthIsLimited && curLine->getWidth() > width)
 			if(widthIsLimited && curLine->getWidth() > width)
@@ -385,7 +381,7 @@ namespace CamelotFramework
 						curLineIdx = allocLine(this);
 						curLineIdx = allocLine(this);
 						curLine = &LineBuffer[curLineIdx];
 						curLine = &LineBuffer[curLineIdx];
 
 
-						curHeight += fontData->fontDesc.lineHeight;
+						curHeight += mFontData->fontDesc.lineHeight;
 					}
 					}
 
 
 					curLine->addWord(lastWordIdx, lastWord);
 					curLine->addWord(lastWordIdx, lastWord);
@@ -417,7 +413,7 @@ namespace CamelotFramework
 		for(UINT32 i = 0; i < mNumChars; i++)
 		for(UINT32 i = 0; i < mNumChars; i++)
 		{
 		{
 			UINT32 charId = text[i];
 			UINT32 charId = text[i];
-			const CHAR_DESC& charDesc = fontData->getCharDesc(charId);
+			const CHAR_DESC& charDesc = mFontData->getCharDesc(charId);
 
 
 			mChars[i] = &charDesc;
 			mChars[i] = &charDesc;
 		}
 		}
@@ -443,6 +439,26 @@ namespace CamelotFramework
 			cm_free(mData);
 			cm_free(mData);
 	}
 	}
 
 
+	const HTexture& TextData::getTextureForPage(UINT32 page) const 
+	{ 
+		return mFontData->texturePages[page]; 
+	}
+
+	INT32 TextData::getBaselineOffset() const 
+	{ 
+		return mFontData->fontDesc.baselineOffset; 
+	}
+
+	UINT32 TextData::getLineHeight() const 
+	{ 
+		return mFontData->fontDesc.lineHeight; 
+	}
+
+	UINT32 TextData::getSpaceWidth() const 
+	{ 
+		return mFontData->fontDesc.spaceWidth; 
+	}
+
 	bool TextData::BuffersInitialized = false;
 	bool TextData::BuffersInitialized = false;
 
 
 	TextData::TextWord* TextData::WordBuffer = nullptr;
 	TextData::TextWord* TextData::WordBuffer = nullptr;
@@ -532,15 +548,11 @@ namespace CamelotFramework
 		while(page >= NextFreePageInfo)
 		while(page >= NextFreePageInfo)
 		{
 		{
 			PageBuffer[NextFreePageInfo].numQuads = 0;
 			PageBuffer[NextFreePageInfo].numQuads = 0;
-			PageBuffer[NextFreePageInfo].texture = HTexture();
 
 
 			NextFreePageInfo++;
 			NextFreePageInfo++;
 		}
 		}
 
 
 		PageBuffer[page].numQuads++;
 		PageBuffer[page].numQuads++;
-
-		if(PageBuffer[page].texture == nullptr)
-			PageBuffer[page].texture = fontData.texturePages[page];
 	}
 	}
 
 
 	UINT32 TextData::getWidth() const
 	UINT32 TextData::getWidth() const

+ 4 - 0
TextOpts.txt

@@ -2,6 +2,10 @@ Make sure to also update TextSprite and ImageSprite and anything else in UpdateM
 
 
 Profiler does a lot of allocations of its own which can seriously skew the profiling results. Try to eliminate them all or add alloc/free overhead fields
 Profiler does a lot of allocations of its own which can seriously skew the profiling results. Try to eliminate them all or add alloc/free overhead fields
 
 
+When optimizing UpdateLayout make sure to mark elements that are fully culled as Culled
+ - But in order to determine that I first need to update the sprite to find out the elements bounds which defeats the point
+ - TODO - FIgure this out
+
 TODO: TextData does an extra mem alloc in this bit of code: PageBuffer[NextFreePageInfo].texture = HTexture();, try to avoid it
 TODO: TextData does an extra mem alloc in this bit of code: PageBuffer[NextFreePageInfo].texture = HTexture();, try to avoid it
 
 
 Performance stats:
 Performance stats: