Jelajahi Sumber

Font C# interface

BearishSun 10 tahun lalu
induk
melakukan
098f8865e1

+ 2 - 2
BansheeCore/Include/BsCorePrerequisites.h

@@ -131,7 +131,7 @@ namespace BansheeEngine
 	class TextureImportOptions;
 	class FontImportOptions;
 	class GpuProgramImportOptions;
-	struct FontData;
+	struct FontBitmap;
 	class GameObject;
 	class GpuResourceData;
 	struct RenderOperation;
@@ -321,7 +321,7 @@ namespace BansheeEngine
 		TID_FONT_DESC = 1052,
 		TID_CHAR_DESC = 1053,
 		TID_FontImportOptions = 1056,
-		TID_FontData = 1057,
+		TID_FontBitmap = 1057,
 		TID_SceneObject = 1059,
 		TID_GameObject = 1060,
 		TID_PixelData = 1062,

+ 16 - 16
BansheeCore/Include/BsFont.h

@@ -7,26 +7,24 @@
 namespace BansheeEngine
 {
 	/**
-	 * @brief	Contains data about font characters of a specific size. Contains
-	 *			textures in which the characters are located and information
-	 *			about each individual character.
+	 * @brief	Contains textures and data about every character for a bitmap font of a specific size.
 	 */
-	struct BS_CORE_EXPORT FontData : public IReflectable
+	struct BS_CORE_EXPORT FontBitmap : public IReflectable
 	{
 		/**
-		 * @brief	Returns a character description for the character with the specified ID.
+		 * @brief	Returns a character description for the character with the specified Unicode key.
 		 */
 		const CHAR_DESC& getCharDesc(UINT32 charId) const;
 
 		UINT32 size; /**< Font size for which the data is contained. */
 		FONT_DESC fontDesc; /**< Font description containing per-character and general font data. */
-		Vector<HTexture> texturePages; /**< Textures in which the characters are stored. */
+		Vector<HTexture> texturePages; /**< Textures in which the character's pixels are stored. */
 
 		/************************************************************************/
 		/* 								SERIALIZATION                      		*/
 		/************************************************************************/
 	public:
-		friend class FontDataRTTI;
+		friend class FontBitmapRTTI;
 		static RTTITypeBase* getRTTIStatic();
 		virtual RTTITypeBase* getRTTI() const override;
 	};
@@ -51,17 +49,19 @@ namespace BansheeEngine
 		 *
 		 * @note	Internal method. Factory methods will call this automatically for you.
 		 */
-		void initialize(const Vector<FontData>& fontData);
+		void initialize(const Vector<SPtr<FontBitmap>>& fontData);
 
 		/**
-		 * @brief	Returns font data for a specific size if it exists, null otherwise.
+		 * @brief	Returns font bitmap for a specific size if it exists, null otherwise.
+		 *
+		 * @param	size	Size of the bitmap in points.
 		 */
-		const FontData* getFontDataForSize(UINT32 size) const;
+		SPtr<const FontBitmap> getBitmap(UINT32 size) const;
 
 		/**
-		 * @brief	Attempts to find nearest available size next to the provided size.
+		 * @brief	Finds the available font bitmap size closest to the provided size.
 		 */
-		INT32 getClosestAvailableSize(UINT32 size) const;
+		INT32 getClosestSize(UINT32 size) const;
 
 		/************************************************************************/
 		/* 								STATICS		                     		*/
@@ -70,14 +70,14 @@ namespace BansheeEngine
 		/**
 		 * @brief	Creates a new font from the provided per-size font data.
 		 */
-		static HFont create(const Vector<FontData>& fontInitData);
+		static HFont create(const Vector<SPtr<FontBitmap>>& fontInitData);
 
 		/**
-		 * @brief	Creates a new font pointer.
+		 * @brief	Creates a new font as a pointer instead of a resource handle.
 		 *
 		 * @note	Internal method.
 		 */
-		static FontPtr _createPtr(const Vector<FontData>& fontInitData);
+		static FontPtr _createPtr(const Vector<SPtr<FontBitmap>>& fontInitData);
 
 	protected:
 		friend class FontManager;
@@ -95,7 +95,7 @@ namespace BansheeEngine
 		void getCoreDependencies(FrameVector<SPtr<CoreObject>>& dependencies) override;
 
 	private:
-		Map<UINT32, FontData> mFontDataPerSize;
+		Map<UINT32, SPtr<FontBitmap>> mFontDataPerSize;
 
 		/************************************************************************/
 		/* 								SERIALIZATION                      		*/

+ 9 - 9
BansheeCore/Include/BsFontDesc.h

@@ -5,7 +5,7 @@
 namespace BansheeEngine
 {
 	/**
-	 * @brief	Kerning pair representing extra or less offset between
+	 * @brief	Kerning pair representing larger or smaller offset between
 	 *			a specific pair of characters.
 	 */
 	struct KerningPair
@@ -15,7 +15,7 @@ namespace BansheeEngine
 	};
 
 	/**
-	 * @brief	Describes a single character in a font.
+	 * @brief	Describes a single character in a font of a specific size.
 	 */
 	struct CHAR_DESC
 	{
@@ -24,10 +24,10 @@ namespace BansheeEngine
 		float uvX, uvY; /**< Texture coordinates of the character in the page texture. */
 		float uvWidth, uvHeight; /**< Width/height of the character in texture coordinates. */
 		UINT32 width, height; /**< Width/height of the character in pixels. */
-		INT32 xOffset, yOffset; /**< Determines offset for the visible portion of the character in pixels. */
-		INT32 xAdvance, yAdvance; /**< Determines how much to advance the pen after writing this character. In pixels. */
+		INT32 xOffset, yOffset; /**< Offset for the visible portion of the character in pixels. */
+		INT32 xAdvance, yAdvance; /**< Determines how much to advance the pen after writing this character, in pixels. */
 
-		Vector<KerningPair> kerningPairs; /**< Pairs that determine if certain character pairs should be closer or father together. e.g. "AV" combination */
+		Vector<KerningPair> kerningPairs; /**< Pairs that determine if certain character pairs should be closer or father together. e.g. "AV" combination. */
 	};
 
 	/**
@@ -36,10 +36,10 @@ namespace BansheeEngine
 	struct FONT_DESC
 	{
 		Map<UINT32, CHAR_DESC> characters; /**< All characters in the font referenced by character ID. */
-		INT32 baselineOffset; /**< Y offset to the baseline on which the characters are placed. In pixels. */
-		UINT32 lineHeight; /**< Height of a single line of the font. In pixels. */
-		CHAR_DESC missingGlyph; /**< Character index to use when data for a character is missing. */
-		UINT32 spaceWidth; /**< Determines width of the space in pixels. */
+		INT32 baselineOffset; /**< Y offset to the baseline on which the characters are placed, in pixels. */
+		UINT32 lineHeight; /**< Height of a single line of the font, in pixels. */
+		CHAR_DESC missingGlyph; /**< Character to use when data for a character is missing. */
+		UINT32 spaceWidth; /**< Width of a space in pixels. */
 	};
 
 	// Make CHAR_DESC serializable

+ 1 - 1
BansheeCore/Include/BsFontManager.h

@@ -14,7 +14,7 @@ namespace BansheeEngine
 		/**
 		 * @brief	Creates a new font from the provided populated font data structure.
 		 */
-		FontPtr create(const Vector<FontData>& fontData) const;
+		FontPtr create(const Vector<SPtr<FontBitmap>>& fontData) const;
 
 		/**
 		 * @brief	Creates an empty font.

+ 24 - 23
BansheeCore/Include/BsFontRTTI.h

@@ -8,55 +8,55 @@
 
 namespace BansheeEngine
 {
-	class BS_CORE_EXPORT FontDataRTTI : public RTTIType<FontData, IReflectable, FontDataRTTI>
+	class BS_CORE_EXPORT FontBitmapRTTI : public RTTIType<FontBitmap, IReflectable, FontBitmapRTTI>
 	{
 	private:
-		UINT32& getSize(FontData* obj)
+		UINT32& getSize(FontBitmap* obj)
 		{
 			return obj->size;
 		}
 
-		void setSize(FontData* obj, UINT32& size)
+		void setSize(FontBitmap* obj, UINT32& size)
 		{
 			obj->size = size;
 		}
 
-		FONT_DESC& getFontDesc(FontData* obj)
+		FONT_DESC& getFontDesc(FontBitmap* obj)
 		{
 			return obj->fontDesc;
 		}
 
-		void setFontDesc(FontData* obj, FONT_DESC& val)
+		void setFontDesc(FontBitmap* obj, FONT_DESC& val)
 		{
 			obj->fontDesc = val;
 		}
 
-		HTexture& getTexture(FontData* obj, UINT32 idx)
+		HTexture& getTexture(FontBitmap* obj, UINT32 idx)
 		{
 			return obj->texturePages.at(idx);
 		}
 
-		void setTexture(FontData* obj, UINT32 idx, HTexture& value)
+		void setTexture(FontBitmap* obj, UINT32 idx, HTexture& value)
 		{
 			obj->texturePages[idx] = value;
 		}
 
-		UINT32 getTextureArraySize(FontData* obj)
+		UINT32 getTextureArraySize(FontBitmap* obj)
 		{
 			return (UINT32)obj->texturePages.size();
 		}
 
-		void setTextureArraySize(FontData* obj, UINT32 size)
+		void setTextureArraySize(FontBitmap* obj, UINT32 size)
 		{
 			obj->texturePages.resize(size);
 		}
 
 	public:
-		FontDataRTTI()
+		FontBitmapRTTI()
 		{
-			addPlainField("size", 0, &FontDataRTTI::getSize, &FontDataRTTI::setSize);
-			addPlainField("fontDesc", 1, &FontDataRTTI::getFontDesc, &FontDataRTTI::setFontDesc);
-			addReflectableArrayField("texturePages", 2, &FontDataRTTI::getTexture, &FontDataRTTI::getTextureArraySize, &FontDataRTTI::setTexture, &FontDataRTTI::setTextureArraySize);
+			addPlainField("size", 0, &FontBitmapRTTI::getSize, &FontBitmapRTTI::setSize);
+			addPlainField("fontDesc", 1, &FontBitmapRTTI::getFontDesc, &FontBitmapRTTI::setFontDesc);
+			addReflectableArrayField("texturePages", 2, &FontBitmapRTTI::getTexture, &FontBitmapRTTI::getTextureArraySize, &FontBitmapRTTI::setTexture, &FontBitmapRTTI::setTextureArraySize);
 		}
 
 		virtual const String& getRTTIName() override
@@ -67,12 +67,12 @@ namespace BansheeEngine
 
 		virtual UINT32 getRTTIId() override
 		{
-			return TID_FontData;
+			return TID_FontBitmap;
 		}
 
 		virtual std::shared_ptr<IReflectable> newRTTIObject() override
 		{
-			return bs_shared_ptr_new<FontData>();
+			return bs_shared_ptr_new<FontBitmap>();
 		}
 	};
 
@@ -80,11 +80,11 @@ namespace BansheeEngine
 	{
 		struct FontInitData
 		{
-			Vector<FontData> fontDataPerSize;
+			Vector<SPtr<FontBitmap>> fontDataPerSize;
 		};
 
 	private:
-		FontData& getFontData(Font* obj, UINT32 idx)
+		FontBitmap& getBitmap(Font* obj, UINT32 idx)
 		{
 			if(idx >= obj->mFontDataPerSize.size())
 				BS_EXCEPT(InternalErrorException, "Index out of range: " + toString(idx) + ". Valid range: 0 .. " + toString((int)obj->mFontDataPerSize.size()));
@@ -93,22 +93,23 @@ namespace BansheeEngine
 			for(UINT32 i = 0; i < idx; i++, ++iter)
 			{ }
 
-			return iter->second;
+			return *iter->second;
 		}
 
-		void setFontData(Font* obj, UINT32 idx, FontData& value)
+		void setBitmap(Font* obj, UINT32 idx, FontBitmap& value)
 		{
 			FontInitData* initData = any_cast<FontInitData*>(obj->mRTTIData);
 
-			initData->fontDataPerSize[idx] = value;
+			initData->fontDataPerSize[idx] = bs_shared_ptr_new<FontBitmap>();
+			*initData->fontDataPerSize[idx] = value;
 		}
 
-		UINT32 getNumFontData(Font* obj)
+		UINT32 getNumBitmaps(Font* obj)
 		{
 			return (UINT32)obj->mFontDataPerSize.size();
 		}
 
-		void setNumFontData(Font* obj, UINT32 size)
+		void setNumBitmaps(Font* obj, UINT32 size)
 		{
 			FontInitData* initData = any_cast<FontInitData*>(obj->mRTTIData);
 
@@ -118,7 +119,7 @@ namespace BansheeEngine
 	public:
 		FontRTTI()
 		{
-			addReflectableArrayField("mFontDataPerSize", 0, &FontRTTI::getFontData, &FontRTTI::getNumFontData, &FontRTTI::setFontData, &FontRTTI::setNumFontData);
+			addReflectableArrayField("mBitmaps", 0, &FontRTTI::getBitmap, &FontRTTI::getNumBitmaps, &FontRTTI::setBitmap, &FontRTTI::setNumBitmaps);
 		}
 
 		virtual const String& getRTTIName() override

+ 2 - 2
BansheeCore/Include/BsTextData.h

@@ -359,7 +359,7 @@ namespace BansheeEngine
 		UINT32 mNumPageInfos;
 
 		HFont mFont;
-		const FontData* mFontData;
+		SPtr<const FontBitmap> mFontData;
 
 		// Static buffers used to reduce runtime memory allocation
 	protected:
@@ -391,7 +391,7 @@ namespace BansheeEngine
 			 * @brief	Increments the count of characters for the referenced page, and optionally
 			 *			creates page info if it doesn't already exist.
 			 */
-			void addCharToPage(UINT32 page, const FontData& fontData);
+			void addCharToPage(UINT32 page, const FontBitmap& fontData);
 
 			/**
 			 * @brief	Resets all allocation counters, but doesn't actually release memory.

+ 14 - 14
BansheeCore/Source/BsFont.cpp

@@ -5,7 +5,7 @@
 
 namespace BansheeEngine
 {
-	const CHAR_DESC& FontData::getCharDesc(UINT32 charId) const
+	const CHAR_DESC& FontBitmap::getCharDesc(UINT32 charId) const
 	{
 		auto iterFind = fontDesc.characters.find(charId);
 		if(iterFind != fontDesc.characters.end())
@@ -16,14 +16,14 @@ namespace BansheeEngine
 		return fontDesc.missingGlyph;
 	}
 
-	RTTITypeBase* FontData::getRTTIStatic()
+	RTTITypeBase* FontBitmap::getRTTIStatic()
 	{
-		return FontDataRTTI::instance();
+		return FontBitmapRTTI::instance();
 	}
 
-	RTTITypeBase* FontData::getRTTI() const
+	RTTITypeBase* FontBitmap::getRTTI() const
 	{
-		return FontData::getRTTIStatic();
+		return FontBitmap::getRTTIStatic();
 	}
 
 	Font::Font()
@@ -33,25 +33,25 @@ namespace BansheeEngine
 	Font::~Font()
 	{ }
 
-	void Font::initialize(const Vector<FontData>& fontData)
+	void Font::initialize(const Vector<SPtr<FontBitmap>>& fontData)
 	{
 		for(auto iter = fontData.begin(); iter != fontData.end(); ++iter)
-			mFontDataPerSize[iter->size] = *iter;
+			mFontDataPerSize[(*iter)->size] = *iter;
 
 		Resource::initialize();
 	}
 
-	const FontData* Font::getFontDataForSize(UINT32 size) const
+	SPtr<const FontBitmap> Font::getBitmap(UINT32 size) const
 	{
 		auto iterFind = mFontDataPerSize.find(size);
 
 		if(iterFind == mFontDataPerSize.end())
 			return nullptr;
 
-		return &iterFind->second;
+		return iterFind->second;
 	}
 
-	INT32 Font::getClosestAvailableSize(UINT32 size) const
+	INT32 Font::getClosestSize(UINT32 size) const
 	{
 		UINT32 minDiff = std::numeric_limits<UINT32>::max();
 		UINT32 bestSize = size;
@@ -87,7 +87,7 @@ namespace BansheeEngine
 	{
 		for (auto& fontDataEntry : mFontDataPerSize)
 		{
-			for (auto& texture : fontDataEntry.second.texturePages)
+			for (auto& texture : fontDataEntry.second->texturePages)
 			{
 				if (texture != nullptr)
 					dependencies.push_back(texture);
@@ -99,7 +99,7 @@ namespace BansheeEngine
 	{
 		for (auto& fontDataEntry : mFontDataPerSize)
 		{
-			for (auto& texture : fontDataEntry.second.texturePages)
+			for (auto& texture : fontDataEntry.second->texturePages)
 			{
 				if (texture.isLoaded())
 					dependencies.push_back(texture.getInternalPtr());
@@ -107,14 +107,14 @@ namespace BansheeEngine
 		}
 	}
 
-	HFont Font::create(const Vector<FontData>& fontData)
+	HFont Font::create(const Vector<SPtr<FontBitmap>>& fontData)
 	{
 		FontPtr newFont = _createPtr(fontData);
 
 		return static_resource_cast<Font>(gResources()._createResourceHandle(newFont));
 	}
 
-	FontPtr Font::_createPtr(const Vector<FontData>& fontData)
+	FontPtr Font::_createPtr(const Vector<SPtr<FontBitmap>>& fontData)
 	{
 		return FontManager::instance().create(fontData);
 	}

+ 1 - 1
BansheeCore/Source/BsFontManager.cpp

@@ -3,7 +3,7 @@
 
 namespace BansheeEngine
 {
-	FontPtr FontManager::create(const Vector<FontData>& fontData) const
+	FontPtr FontManager::create(const Vector<SPtr<FontBitmap>>& fontData) const
 	{
 		FontPtr newFont = bs_core_ptr<Font>(new (bs_alloc<Font>()) Font());
 		newFont->_setThisPtr(newFont);

+ 3 - 3
BansheeCore/Source/BsTextData.cpp

@@ -359,8 +359,8 @@ namespace BansheeEngine
 
 		if(font != nullptr)
 		{
-			UINT32 nearestSize = font->getClosestAvailableSize(fontSize);
-			mFontData = font->getFontDataForSize(nearestSize);
+			UINT32 nearestSize = font->getClosestSize(fontSize);
+			mFontData = font->getBitmap(nearestSize);
 		}
 
 		if(mFontData == nullptr || mFontData->texturePages.size() == 0)
@@ -620,7 +620,7 @@ namespace BansheeEngine
 		NextFreePageInfo = 0;
 	}
 
-	void TextDataBase::BufferData::addCharToPage(UINT32 page, const FontData& fontData)
+	void TextDataBase::BufferData::addCharToPage(UINT32 page, const FontBitmap& fontData)
 	{
 		if(NextFreePageInfo >= PageBufferSize)
 		{

+ 1 - 1
BansheeEngine/Source/BsBuiltinResources.cpp

@@ -994,7 +994,7 @@ namespace BansheeEngine
 		manifest->registerResource(font.getUUID(), outputPath);
 
 		// Save font texture pages as well. TODO - Later maybe figure out a more automatic way to do this
-		const FontData* fontData = font->getFontDataForSize(size);
+		SPtr<const FontBitmap> fontData = font->getBitmap(size);
 
 		Path texPageOutputPath = FileSystem::getWorkingDirectoryPath() + outputFolder;
 

+ 2 - 2
BansheeEngine/Source/BsGUIInputCaret.cpp

@@ -280,8 +280,8 @@ namespace BansheeEngine
 		{
 			if(mTextDesc.font != nullptr)
 			{
-				UINT32 nearestSize = mTextDesc.font->getClosestAvailableSize(mTextDesc.fontSize);
-				const FontData* fontData = mTextDesc.font->getFontDataForSize(nearestSize);
+				UINT32 nearestSize = mTextDesc.font->getClosestSize(mTextDesc.fontSize);
+				SPtr<const FontBitmap> fontData = mTextDesc.font->getBitmap(nearestSize);
 
 				if(fontData != nullptr)
 					return fontData->fontDesc.lineHeight;

+ 1 - 1
BansheeEngine/Source/BsImageSprite.cpp

@@ -20,7 +20,7 @@ namespace BansheeEngine
 
 	void ImageSprite::update(const IMAGE_SPRITE_DESC& desc, UINT64 groupId)
 	{
-		const FontData* fontData = nullptr;
+		const FontBitmap* fontData = nullptr;
 		if(desc.texture == nullptr || desc.texture->getTexture() == nullptr)
 		{
 			clearMesh();

+ 10 - 10
BansheeFontImporter/Source/BsFontImporter.cpp

@@ -78,14 +78,14 @@ namespace BansheeEngine
 		if(!fontImportOptions->getAntialiasing())
 			loadFlags |= FT_LOAD_TARGET_MONO | FT_LOAD_NO_AUTOHINT;
 
-		Vector<FontData> dataPerSize;
+		Vector<SPtr<FontBitmap>> dataPerSize;
 		for(size_t i = 0; i < fontSizes.size(); i++)
 		{
 			FT_F26Dot6 ftSize = (FT_F26Dot6)(fontSizes[i] * (1 << 6));
 			if(FT_Set_Char_Size( face, ftSize, 0, dpi, dpi))
 				BS_EXCEPT(InternalErrorException, "Could not set character size." );
 
-			FontData fontData;
+			SPtr<FontBitmap> fontData = bs_shared_ptr_new<FontBitmap>();
 
 			// Get all char sizes so we can generate texture layout
 			Vector<TexAtlasElementDesc> atlasElements;
@@ -263,11 +263,11 @@ namespace BansheeEngine
 							}
 						}
 
-						fontData.fontDesc.characters[charIdx] = charDesc;
+						fontData->fontDesc.characters[charIdx] = charDesc;
 					}
 					else
 					{
-						fontData.fontDesc.missingGlyph = charDesc;
+						fontData->fontDesc.missingGlyph = charDesc;
 					}
 				}
 
@@ -287,15 +287,15 @@ namespace BansheeEngine
 					newTex->writeSubresource(gCoreAccessor(), subresourceIdx, pixelData, false);
 				}
 
-				newTex->setName(L"FontPage" + toWString((UINT32)fontData.texturePages.size()));
-				fontData.texturePages.push_back(newTex);
+				newTex->setName(L"FontPage" + toWString((UINT32)fontData->texturePages.size()));
+				fontData->texturePages.push_back(newTex);
 
 				pageIdx++;
 			}
 
-			fontData.size = fontSizes[i];
-			fontData.fontDesc.baselineOffset = baselineOffset;
-			fontData.fontDesc.lineHeight = lineHeight;
+			fontData->size = fontSizes[i];
+			fontData->fontDesc.baselineOffset = baselineOffset;
+			fontData->fontDesc.lineHeight = lineHeight;
 
 			// Get space size
 			error = FT_Load_Char(face, 32, loadFlags);
@@ -303,7 +303,7 @@ namespace BansheeEngine
 			if(error)
 				BS_EXCEPT(InternalErrorException, "Failed to load a character");
 
-			fontData.fontDesc.spaceWidth = face->glyph->advance.x >> 6;
+			fontData->fontDesc.spaceWidth = face->glyph->advance.x >> 6;
 
 			dataPerSize.push_back(fontData);
 		}

+ 182 - 12
MBansheeEngine/Font.cs

@@ -5,19 +5,10 @@ using System.Runtime.InteropServices;
 namespace BansheeEngine
 {
     /// <summary>
-    /// Marks a range of characters in a font.
+    /// Font resource containing data about textual characters and how to render text. Contains one or multiple font 
+    /// bitmaps, each for a specific size.
     /// </summary>
-    [StructLayout(LayoutKind.Sequential)]
-    public struct CharRange
-    {
-        public UInt32 start;
-        public UInt32 end;
-    }
-
-    /// <summary>
-    /// Font resource containing data about textual characters and how to render text.
-    /// </summary>
-    public sealed class Font : Resource // TODO - Dummy class
+    public sealed class Font : Resource
     {
         /// <summary>
         /// Creates a new font resource. For runtime use only.
@@ -29,7 +20,186 @@ namespace BansheeEngine
                 Internal_CreateInstance(this);
         }
 
+        /// <summary>
+        /// Returns font bitmap for a specific font size.
+        /// </summary>
+        /// <param name="size">Size of the bitmap in points.</param>
+        /// <returns>Bitmap object if size was found, null otherwise.</returns>
+        public FontBitmap GetBitmap(int size)
+        {
+            return Internal_GetBitmap(mCachedPtr, size);
+        }
+
+        /// <summary>
+        /// Finds the available font bitmap size closest to the provided size.
+        /// </summary>
+        /// <param name="size">Size of the bitmap in points.</param>
+        /// <returns>Nearest available bitmap size.</returns>
+        public int GetClosestSize(int size)
+        {
+            return Internal_GetClosestSize(mCachedPtr, size);
+        }
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_CreateInstance(Font instance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern FontBitmap Internal_GetBitmap(IntPtr instance, int size);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern int Internal_GetClosestSize(IntPtr instance, int size);
+    }
+
+    /// <summary>
+    /// Contains textures and data about every character for a bitmap font of a specific size.
+    /// </summary>
+    public sealed class FontBitmap : ScriptObject
+    {
+        /// <summary>
+        /// Constructor for internal runtime use only.
+        /// </summary>
+        internal FontBitmap()
+        { }
+
+        /// <summary>
+        /// Size of the font in the bitmap, in points.
+        /// </summary>
+        public int Size { get { return Internal_GetSize(mCachedPtr); } }
+
+        /// <summary>
+        /// Y offset to the baseline on which the characters are placed, in pixels.
+        /// </summary>
+        public int BaselineOffset { get { return Internal_GetBaselineOffset(mCachedPtr); } }
+
+        /// <summary>
+        /// Height of a single line of the font, in pixels.
+        /// </summary>
+        public int LineHeight { get { return Internal_GetLineHeight(mCachedPtr); } }
+
+        /// <summary>
+        /// Width of a space in pixels.
+        /// </summary>
+        public int SpaceWidth { get { return Internal_GetSpaceWidth(mCachedPtr); } }
+
+        /// <summary>
+        /// Character to use when data for a character is missing.
+        /// </summary>
+        public CharDesc MissingChar { get { CharDesc value; Internal_GetMissingChar(mCachedPtr, out value); return value; } }
+
+        /// <summary>
+        /// Textures in which the character's pixels are stored.
+        /// </summary>
+        public Texture2D[] Pages { get { return Internal_GetPages(mCachedPtr); } }
+
+        /// <summary>
+        /// Returns a description of the character in the bitmap.
+        /// </summary>
+        /// <param name="id">Unicode key of the character to retrieve.</param>
+        /// <returns>Character data if it was found in the bitmap, missing character data otherwise.</returns>
+        public CharDesc GetChar(int id)
+        {
+            CharDesc value;
+            Internal_GetChar(mCachedPtr, id, out value);
+            return value;
+        }
+
+        /// <summary>
+        /// Returns a set of pairs that determine if the provided character should be closer or father together than normal
+        /// with a specific other character. e.g. the combination of "A" and "V" characters is normally a kerning pair "AV" 
+        /// as their bounds overlap and are closer together than characters would be normally.
+        /// </summary>
+        /// <param name="id">Unicode key of the character to retrieve kerning pairs for.</param>
+        /// <returns>A set of kerning pairs for the character.</returns>
+        public KerningPair[] GetKerning(int id)
+        {
+            return Internal_GetKerning(mCachedPtr, id);
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern int Internal_GetSize(IntPtr instance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern int Internal_GetBaselineOffset(IntPtr instance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern int Internal_GetLineHeight(IntPtr instance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern int Internal_GetSpaceWidth(IntPtr instance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetMissingChar(IntPtr instance, out CharDesc output);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern Texture2D[] Internal_GetPages(IntPtr instance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetChar(IntPtr instance, int id, out CharDesc output);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern KerningPair[] Internal_GetKerning(IntPtr instance, int id);
+    }
+
+    /// <summary>
+    /// Marks a range of characters in a font.
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential), SerializeObject]
+    public struct CharRange
+    {
+        public UInt32 start;
+        public UInt32 end;
+    }
+
+    /// <summary>
+    /// Kerning pair representing larger or smaller offset between a specific pair of characters.
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential), SerializeObject]
+    public struct KerningPair // Note: Must match C++ struct KerningPair
+    {
+        public int OtherChar;
+        public int Amount;
+    }
+
+    /// <summary>
+    /// Describes a single character in a font of a specific size.
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential), SerializeObject]
+    public struct CharDesc // Note: Must match C++ struct ScriptCharDesc
+    {
+        /// <summary>Character ID, corresponding to a Unicode key.</summary>
+        public int Id;
+
+        /// <summary>Index of the texture the character is located on.</summary>
+        public int Page; 
+
+        /// <summary>Texture coordinates of the character in the page texture.</summary>
+        public float UVX;
+
+        /// <summary>Texture coordinates of the character in the page texture.</summary>
+        public float UVY;
+
+        /// <summary>Size of the character in texture coordinates.</summary>
+        public float UVWidth;
+
+        /// <summary>Size of the character in texture coordinates.</summary>
+        public float UVHeight;
+
+        /// <summary>Size of the character in pixels.</summary>
+        public int Width;
+
+        /// <summary>Size of the character in pixels.</summary>
+        public int Height;
+
+        /// <summary>Offset for the visible portion of the character in pixels.</summary>
+        public int XOffset;
+
+        /// <summary>Offset for the visible portion of the character in pixels.</summary>
+        public int YOffset;
+
+        /// <summary>Determines how much to advance the pen after writing this character, in pixels.</summary>
+        public int XAdvance;
+
+        /// <summary>Determines how much to advance the pen after writing this character, in pixels.</summary>
+        public int YAdvance;
     }
 }

+ 6 - 0
SBansheeEngine/Include/BsScriptFont.h

@@ -35,6 +35,12 @@ namespace BansheeEngine
 		void _onManagedInstanceDeleted() override;
 
 		HFont mFont;
+
+		/************************************************************************/
+		/* 								CLR HOOKS						   		*/
+		/************************************************************************/
+		static MonoObject* internal_GetBitmap(ScriptFont* instance, int size);
+		static int internal_GetClosestSize(ScriptFont* instance, int size);
 	};
 
 	/**

+ 75 - 0
SBansheeEngine/Include/BsScriptFontBitmap.h

@@ -0,0 +1,75 @@
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "BsScriptResource.h"
+#include "BsScriptObject.h"
+#include "BsFont.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	Describes a single character in a font of a specific size.
+	 */
+	struct ScriptCharDesc // Note: Must match C# struct CharDesc
+	{
+		UINT32 charId; /**< Character ID, corresponding to a Unicode key. */
+		UINT32 page; /**< Index of the texture the character is located on. */
+		float uvX, uvY; /**< Texture coordinates of the character in the page texture. */
+		float uvWidth, uvHeight; /**< Width/height of the character in texture coordinates. */
+		UINT32 width, height; /**< Width/height of the character in pixels. */
+		INT32 xOffset, yOffset; /**< Offset for the visible portion of the character in pixels. */
+		INT32 xAdvance, yAdvance; /**< Determines how much to advance the pen after writing this character, in pixels. */
+	};
+
+	/**
+	 * @brief	Interop class between C++ & CLR for FontBitmap.
+	 */
+	class BS_SCR_BE_EXPORT ScriptFontBitmap : public ScriptObject<ScriptFontBitmap>
+	{
+	public:
+		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "FontBitmap")
+
+		/**
+		 * @brief	Creates a new managed instance of a font bitmap.
+		 *
+		 * @param	bitmap	Native font bitmap to initialize the managed instance with.
+		 */
+		static MonoObject* create(SPtr<const FontBitmap> bitmap);
+
+	private:
+		friend class ScriptResourceManager;
+
+		ScriptFontBitmap(MonoObject* instance, SPtr<const FontBitmap> bitmap);
+
+		/**
+		 * @brief	Converts the native character description into a script character description.
+		 */
+		static ScriptCharDesc convertCharDesc(const CHAR_DESC& desc);
+
+		SPtr<const FontBitmap> mBitmap;
+
+		/************************************************************************/
+		/* 								CLR HOOKS						   		*/
+		/************************************************************************/
+		static UINT32 internal_GetSize(ScriptFontBitmap* instance);
+		static INT32 internal_GetBaselineOffset(ScriptFontBitmap* instance);
+		static UINT32 internal_GetLineHeight(ScriptFontBitmap* instance);
+		static UINT32 internal_GetSpaceWidth(ScriptFontBitmap* instance);
+		static void internal_GetMissingChar(ScriptFontBitmap* instance, ScriptCharDesc* output);
+		static MonoArray* internal_GetPages(ScriptFontBitmap* instance);
+		static void internal_GetChar(ScriptFontBitmap* instance, UINT32 id, ScriptCharDesc* output);
+		static MonoArray* internal_GetKerning(ScriptFontBitmap* instance, UINT32 id);
+	};
+
+	/**
+	 * @brief	Interop class between C++ & CLR for KerningPair.
+	 */
+	class BS_SCR_BE_EXPORT ScriptKerningPair : public ScriptObject <ScriptKerningPair>
+	{
+	public:
+		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "KerningPair")
+
+	private:
+		ScriptKerningPair(MonoObject* instance);
+	};
+}

+ 2 - 0
SBansheeEngine/SBansheeEngine.vcxproj

@@ -264,6 +264,7 @@
     <ClInclude Include="Include\BsScriptCursor.h" />
     <ClInclude Include="Include\BsScriptDebug.h" />
     <ClInclude Include="Include\BsScriptEnginePrerequisites.h" />
+    <ClInclude Include="Include\BsScriptFontBitmap.h" />
     <ClInclude Include="Include\BsScriptGameObject.h" />
     <ClInclude Include="Include\BsScriptGameObjectManager.h" />
     <ClInclude Include="Include\BsScriptGUIButton.h" />
@@ -356,6 +357,7 @@
     <ClCompile Include="Source\BsScriptCursor.cpp" />
     <ClCompile Include="Source\BsScriptDebug.cpp" />
     <ClCompile Include="Source\BsScriptEnginePlugin.cpp" />
+    <ClCompile Include="Source\BsScriptFontBitmap.cpp" />
     <ClCompile Include="Source\BsScriptGameObject.cpp" />
     <ClCompile Include="Source\BsScriptGameObjectManager.cpp" />
     <ClCompile Include="Source\BsScriptGUIButton.cpp" />

+ 6 - 0
SBansheeEngine/SBansheeEngine.vcxproj.filters

@@ -342,6 +342,9 @@
     <ClInclude Include="Include\BsScriptLight.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsScriptFontBitmap.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsScriptTexture2D.cpp">
@@ -623,5 +626,8 @@
     <ClCompile Include="Source\BsScriptLight.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsScriptFontBitmap.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 23 - 2
SBansheeEngine/Source/BsScriptFont.cpp

@@ -3,8 +3,8 @@
 #include "BsMonoField.h"
 #include "BsMonoClass.h"
 #include "BsMonoManager.h"
-#include "BsSpriteTexture.h"
 #include "BsScriptResourceManager.h"
+#include "BsScriptFontBitmap.h"
 
 namespace BansheeEngine
 {
@@ -16,7 +16,8 @@ namespace BansheeEngine
 
 	void ScriptFont::initRuntimeData()
 	{
-
+		metaData.scriptClass->addInternalCall("Internal_GetBitmap", &ScriptFont::internal_GetBitmap);
+		metaData.scriptClass->addInternalCall("Internal_GetClosestSize", &ScriptFont::internal_GetClosestSize);
 	}
 
 	void ScriptFont::_onManagedInstanceDeleted()
@@ -32,6 +33,26 @@ namespace BansheeEngine
 		mFont = static_resource_cast<Font>(resource);
 	}
 
+	MonoObject* ScriptFont::internal_GetBitmap(ScriptFont* instance, int size)
+	{
+		if (!instance->mFont.isLoaded())
+			return nullptr;
+
+		SPtr<const FontBitmap> bitmap = instance->mFont->getBitmap(size);
+		if (bitmap != nullptr)
+			return ScriptFontBitmap::create(bitmap);
+
+		return nullptr;
+	}
+
+	int ScriptFont::internal_GetClosestSize(ScriptFont* instance, int size)
+	{
+		if (!instance->mFont.isLoaded())
+			return 0;
+
+		return instance->mFont->getClosestSize(size);
+	}
+
 	ScriptCharRange::ScriptCharRange(MonoObject* instance)
 		:ScriptObject(instance)
 	{ }

+ 123 - 0
SBansheeEngine/Source/BsScriptFontBitmap.cpp

@@ -0,0 +1,123 @@
+#include "BsScriptFontBitmap.h"
+#include "BsScriptMeta.h"
+#include "BsMonoField.h"
+#include "BsMonoClass.h"
+#include "BsMonoManager.h"
+#include "BsScriptResourceManager.h"
+#include "BsScriptTexture2D.h"
+#include "BsMonoUtil.h"
+
+namespace BansheeEngine
+{
+	ScriptFontBitmap::ScriptFontBitmap(MonoObject* instance, SPtr<const FontBitmap> bitmap)
+		:ScriptObject(instance), mBitmap(bitmap)
+	{
+
+	}
+
+	void ScriptFontBitmap::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_GetSize", &ScriptFontBitmap::internal_GetSize);
+		metaData.scriptClass->addInternalCall("Internal_GetBaselineOffset", &ScriptFontBitmap::internal_GetBaselineOffset);
+		metaData.scriptClass->addInternalCall("Internal_GetLineHeight", &ScriptFontBitmap::internal_GetLineHeight);
+		metaData.scriptClass->addInternalCall("Internal_GetSpaceWidth", &ScriptFontBitmap::internal_GetSpaceWidth);
+		metaData.scriptClass->addInternalCall("Internal_GetMissingChar", &ScriptFontBitmap::internal_GetMissingChar);
+		metaData.scriptClass->addInternalCall("Internal_GetPages", &ScriptFontBitmap::internal_GetPages);
+		metaData.scriptClass->addInternalCall("Internal_GetChar", &ScriptFontBitmap::internal_GetChar);
+		metaData.scriptClass->addInternalCall("Internal_GetKerning", &ScriptFontBitmap::internal_GetKerning);
+	}
+
+	ScriptCharDesc ScriptFontBitmap::convertCharDesc(const CHAR_DESC& desc)
+	{
+		ScriptCharDesc output;
+
+		output.charId = desc.charId;
+		output.page = desc.page;
+		output.uvX = desc.uvX;
+		output.uvY = desc.uvY;
+		output.uvWidth = desc.uvWidth;
+		output.uvHeight = desc.uvHeight;
+		output.width = desc.width;
+		output.height = desc.height;
+		output.xOffset = desc.xOffset;
+		output.yOffset = desc.yOffset;
+		output.xAdvance = desc.xAdvance;
+		output.yAdvance = desc.yAdvance;
+
+		return output;
+	}
+
+	MonoObject* ScriptFontBitmap::create(SPtr<const FontBitmap> bitmap)
+	{
+		MonoObject* managedInstance = metaData.scriptClass->createInstance();
+		ScriptFontBitmap* fontBitmap = new (bs_alloc<ScriptFontBitmap>()) ScriptFontBitmap(managedInstance, bitmap);
+
+		return managedInstance;
+	}
+
+	UINT32 ScriptFontBitmap::internal_GetSize(ScriptFontBitmap* instance)
+	{
+		return instance->mBitmap->size;
+	}
+
+	INT32 ScriptFontBitmap::internal_GetBaselineOffset(ScriptFontBitmap* instance)
+	{
+		return instance->mBitmap->fontDesc.baselineOffset;
+	}
+
+	UINT32 ScriptFontBitmap::internal_GetLineHeight(ScriptFontBitmap* instance)
+	{
+		return instance->mBitmap->fontDesc.lineHeight;
+	}
+
+	UINT32 ScriptFontBitmap::internal_GetSpaceWidth(ScriptFontBitmap* instance)
+	{
+		return instance->mBitmap->fontDesc.spaceWidth;
+	}
+
+	void ScriptFontBitmap::internal_GetMissingChar(ScriptFontBitmap* instance, ScriptCharDesc* output)
+	{
+		*output = convertCharDesc(instance->mBitmap->fontDesc.missingGlyph);
+	}
+
+	MonoArray* ScriptFontBitmap::internal_GetPages(ScriptFontBitmap* instance)
+	{
+		const Vector<HTexture>& texturePages = instance->mBitmap->texturePages;
+
+		UINT32 numPages = texturePages.size();
+		ScriptArray output = ScriptArray::create<ScriptTexture2D>(numPages);
+		for (UINT32 i = 0; i < numPages; i++)
+		{
+			ScriptTexture2D* scriptTexture = nullptr;
+			ScriptResourceManager::instance().getScriptResource(texturePages[i], &scriptTexture, true);
+
+			output.set(i, scriptTexture->getManagedInstance());
+		}
+
+		return output.getInternal();
+	}
+
+	void ScriptFontBitmap::internal_GetChar(ScriptFontBitmap* instance, UINT32 id, ScriptCharDesc* output)
+	{
+		*output = convertCharDesc(instance->mBitmap->getCharDesc(id));
+	}
+
+	MonoArray* ScriptFontBitmap::internal_GetKerning(ScriptFontBitmap* instance, UINT32 id)
+	{
+		const CHAR_DESC& charDesc = instance->mBitmap->getCharDesc(id);
+
+		UINT32 numPairs = (UINT32)charDesc.kerningPairs.size();
+		ScriptArray outArray = ScriptArray::create<ScriptKerningPair>(numPairs);
+		for (UINT32 i = 0; i < numPairs; i++)
+			outArray.set(i, charDesc.kerningPairs[i]);
+
+		return outArray.getInternal();
+	}
+
+	ScriptKerningPair::ScriptKerningPair(MonoObject* instance)
+		:ScriptObject(instance)
+	{ }
+
+	void ScriptKerningPair::initRuntimeData()
+	{ }
+}

+ 2 - 2
TODO.txt

@@ -56,8 +56,8 @@ Ribek use:
  - Hook up color picker to guicolor field
  - When hiding a component in inspector, it doesn't immediately reposition the components below it
  - Having en empty component in inspector shows a small empty background, it shouldn't show anything
- - Component inspectors for: Camera, Renderable, Point/Spot/Directional lights
- - Resource inspectors for: Material, Texture, Mesh, Font, Shader, Script Code, Plain Text, Sprite Texture, GUISkin, StringTable, Prefab (just something basic for now)
+ - Component inspector for Renderable
+ - Resource inspectors for: Texture, Mesh, Font, Shader, Script Code, Plain Text, Sprite Texture, GUISkin, StringTable, Prefab (just something basic for now)
  - Test release mode
  - Add temporary icon textures too all icon buttons currently containing only text so that Ribek can modify them
   - Also add dummy icons to toolbar (Open Project, Save Scene, Undo, Redo, Basic shapes, Camera, Renderable, Lights, Play, Pause, Step)