Просмотр исходного кода

Integrated HString and ensured it works

Marko Pintera 12 лет назад
Родитель
Сommit
23d99435eb
32 измененных файлов с 230 добавлено и 117 удалено
  1. 2 2
      BansheeEngine/Include/BsGUIButton.h
  2. 2 0
      BansheeEngine/Include/BsGUIButtonBase.h
  3. 10 10
      BansheeEngine/Include/BsGUIContent.h
  4. 3 2
      BansheeEngine/Include/BsGUILabel.h
  5. 4 4
      BansheeEngine/Include/BsGUIListBox.h
  6. 4 4
      BansheeEngine/Include/BsGUIToggle.h
  7. 2 2
      BansheeEngine/Source/BsGUIButton.cpp
  8. 7 0
      BansheeEngine/Source/BsGUIButtonBase.cpp
  9. 5 5
      BansheeEngine/Source/BsGUIContent.cpp
  10. 4 4
      BansheeEngine/Source/BsGUIDropDownBox.cpp
  11. 10 5
      BansheeEngine/Source/BsGUILabel.cpp
  12. 4 4
      BansheeEngine/Source/BsGUIListBox.cpp
  13. 4 4
      BansheeEngine/Source/BsGUIScrollBar.cpp
  14. 4 4
      BansheeEngine/Source/BsGUIToggle.cpp
  15. 3 3
      CamelotClient/Include/BsEditorWidget.h
  16. 6 3
      CamelotClient/Include/BsGUITabButton.h
  17. 2 2
      CamelotClient/Include/BsGUITabbedTitleBar.h
  18. 1 1
      CamelotClient/Source/BsEditorWidget.cpp
  19. 4 4
      CamelotClient/Source/BsGUIMenuBar.cpp
  20. 28 6
      CamelotClient/Source/BsGUITabButton.cpp
  21. 4 4
      CamelotClient/Source/BsGUITabbedTitleBar.cpp
  22. 6 6
      CamelotClient/Source/CmTestTextSprite.cpp
  23. 1 1
      CamelotClient/Source/DbgEditorWidget1.cpp
  24. 6 6
      CamelotClient/Source/DbgEditorWidget2.cpp
  25. 3 0
      CamelotCore/Source/CmApplication.cpp
  26. 26 10
      CamelotUtility/Include/CmHString.h
  27. 1 1
      CamelotUtility/Include/CmPrerequisitesUtil.h
  28. 2 0
      CamelotUtility/Include/CmString.h
  29. 2 1
      CamelotUtility/Include/CmStringTable.h
  30. 60 16
      CamelotUtility/Source/CmHString.cpp
  31. 4 3
      CamelotUtility/Source/CmStringTable.cpp
  32. 6 0
      TODO.txt

+ 2 - 2
BansheeEngine/Include/BsGUIButton.h

@@ -14,8 +14,8 @@ namespace BansheeEngine
 	public:
 		static const CM::String& getGUITypeName();
 
-		static GUIButton* create(GUIWidget& parent, const CM::WString& text, const GUIElementStyle* style = nullptr);
-		static GUIButton* create(GUIWidget& parent, const CM::WString& text, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style = nullptr);
+		static GUIButton* create(GUIWidget& parent, const CM::HString& text, const GUIElementStyle* style = nullptr);
+		static GUIButton* create(GUIWidget& parent, const CM::HString& text, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style = nullptr);
 
 		static GUIButton* create(GUIWidget& parent, const GUIContent& content, const GUIElementStyle* style = nullptr);
 		static GUIButton* create(GUIWidget& parent, const GUIContent& content, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style = nullptr);

+ 2 - 0
BansheeEngine/Include/BsGUIButtonBase.h

@@ -83,5 +83,7 @@ namespace BansheeEngine
 
 		IMAGE_SPRITE_DESC mImageDesc;
 		GUIContent mContent;
+
+		boost::signals::connection mLocStringUpdatedConn;
 	};
 }

+ 10 - 10
BansheeEngine/Include/BsGUIContent.h

@@ -6,22 +6,22 @@ namespace BansheeEngine
 	class BS_EXPORT GUIContent
 	{
 	public:
-		GUIContent(const CM::WString& text);
-		GUIContent(const CM::WString& text, const CM::WString& tooltip);
+		explicit GUIContent(const CM::HString& text);
+		GUIContent(const CM::HString& text, const CM::HString& tooltip);
 
-		GUIContent(const SpriteTexturePtr& image);
-		GUIContent(const SpriteTexturePtr& image, const CM::WString& tooltip);
+		explicit GUIContent(const SpriteTexturePtr& image);
+		GUIContent(const SpriteTexturePtr& image, const CM::HString& tooltip);
 
-		GUIContent(const CM::WString& text, const SpriteTexturePtr& image);
-		GUIContent(const CM::WString& text, const SpriteTexturePtr& image, const CM::WString& tooltip);
+		GUIContent(const CM::HString& text, const SpriteTexturePtr& image);
+		GUIContent(const CM::HString& text, const SpriteTexturePtr& image, const CM::HString& tooltip);
 
-		const CM::WString& getText() const { return mText; }
+		const CM::HString& getText() const { return mText; }
 		const SpriteTexturePtr& getImage() const { return mImage; }
-		const CM::WString& getTooltip() const { return mTooltipText; }
+		const CM::HString& getTooltip() const { return mTooltipText; }
 
 	private:
-		CM::WString mText;
+		CM::HString mText;
 		SpriteTexturePtr mImage;
-		CM::WString mTooltipText;
+		CM::HString mTooltipText;
 	};
 }

+ 3 - 2
BansheeEngine/Include/BsGUILabel.h

@@ -12,8 +12,8 @@ namespace BansheeEngine
 	public:
 		static const CM::String& getGUITypeName();
 
-		static GUILabel* create(GUIWidget& parent, const CM::WString& text, const GUIElementStyle* style = nullptr);
-		static GUILabel* create(GUIWidget& parent, const CM::WString& text, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style = nullptr);
+		static GUILabel* create(GUIWidget& parent, const CM::HString& text, const GUIElementStyle* style = nullptr);
+		static GUILabel* create(GUIWidget& parent, const CM::HString& text, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style = nullptr);
 
 		static GUILabel* create(GUIWidget& parent, const GUIContent& content, const GUIElementStyle* style = nullptr);
 		static GUILabel* create(GUIWidget& parent, const GUIContent& content, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style = nullptr);
@@ -58,6 +58,7 @@ namespace BansheeEngine
 	private:
 		TextSprite* mTextSprite;
 		GUIContent mContent;
+		boost::signals::connection mLocStringUpdatedConn;
 
 		TEXT_SPRITE_DESC mDesc;
 		

+ 4 - 4
BansheeEngine/Include/BsGUIListBox.h

@@ -13,8 +13,8 @@ namespace BansheeEngine
 	public:
 		static const CM::String& getGUITypeName();
 
-		static GUIListBox* create(GUIWidget& parent, const CM::Vector<CM::WString>::type& elements, const GUIElementStyle* style = nullptr);
-		static GUIListBox* create(GUIWidget& parent, const CM::Vector<CM::WString>::type& elements, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style = nullptr);
+		static GUIListBox* create(GUIWidget& parent, const CM::Vector<CM::HString>::type& elements, const GUIElementStyle* style = nullptr);
+		static GUIListBox* create(GUIWidget& parent, const CM::Vector<CM::HString>::type& elements, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style = nullptr);
 
 		boost::signal<void(CM::UINT32)> onSelectionChanged;
 	protected:
@@ -22,10 +22,10 @@ namespace BansheeEngine
 
 	private:
 		CM::UINT32 mSelectedIdx;
-		CM::Vector<CM::WString>::type mElements;
+		CM::Vector<CM::HString>::type mElements;
 		bool mIsListBoxOpen;
 
-		GUIListBox(GUIWidget& parent, const GUIElementStyle* style, const CM::Vector<CM::WString>::type& elements, const GUILayoutOptions& layoutOptions);
+		GUIListBox(GUIWidget& parent, const GUIElementStyle* style, const CM::Vector<CM::HString>::type& elements, const GUILayoutOptions& layoutOptions);
 
 		virtual bool mouseEvent(const GUIMouseEvent& ev);
 

+ 4 - 4
BansheeEngine/Include/BsGUIToggle.h

@@ -15,11 +15,11 @@ namespace BansheeEngine
 	public:
 		static const CM::String& getGUITypeName();
 
-		static GUIToggle* create(GUIWidget& parent, const CM::WString& text, const GUIElementStyle* style = nullptr);
-		static GUIToggle* create(GUIWidget& parent, const GUILayoutOptions& layoutOptions, const CM::WString& text, const GUIElementStyle* style = nullptr);
+		static GUIToggle* create(GUIWidget& parent, const CM::HString& text, const GUIElementStyle* style = nullptr);
+		static GUIToggle* create(GUIWidget& parent, const GUILayoutOptions& layoutOptions, const CM::HString& text, const GUIElementStyle* style = nullptr);
 	
-		static GUIToggle* create(GUIWidget& parent, const CM::WString& text, std::shared_ptr<GUIToggleGroup> toggleGroup, const GUIElementStyle* style = nullptr);
-		static GUIToggle* create(GUIWidget& parent, const GUILayoutOptions& layoutOptions, const CM::WString& text, std::shared_ptr<GUIToggleGroup> toggleGroup, const GUIElementStyle* style = nullptr);
+		static GUIToggle* create(GUIWidget& parent, const CM::HString& text, std::shared_ptr<GUIToggleGroup> toggleGroup, const GUIElementStyle* style = nullptr);
+		static GUIToggle* create(GUIWidget& parent, const GUILayoutOptions& layoutOptions, const CM::HString& text, std::shared_ptr<GUIToggleGroup> toggleGroup, const GUIElementStyle* style = nullptr);
 
 		static GUIToggle* create(GUIWidget& parent, const GUIContent& content, const GUIElementStyle* style = nullptr);
 		static GUIToggle* create(GUIWidget& parent, const GUILayoutOptions& layoutOptions, const GUIContent& content, const GUIElementStyle* style = nullptr);

+ 2 - 2
BansheeEngine/Source/BsGUIButton.cpp

@@ -23,12 +23,12 @@ namespace BansheeEngine
 		:GUIButtonBase(parent, style, content, layoutOptions)
 	{ }
 
-	GUIButton* GUIButton::create(GUIWidget& parent, const WString& text, const GUIElementStyle* style)
+	GUIButton* GUIButton::create(GUIWidget& parent, const HString& text, const GUIElementStyle* style)
 	{
 		return create(parent, GUIContent(text), style);
 	}
 
-	GUIButton* GUIButton::create(GUIWidget& parent, const WString& text, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style)
+	GUIButton* GUIButton::create(GUIWidget& parent, const HString& text, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style)
 	{
 		return create(parent, GUIContent(text), layoutOptions, style);
 	}

+ 7 - 0
BansheeEngine/Source/BsGUIButtonBase.cpp

@@ -35,10 +35,14 @@ namespace BansheeEngine
 		mImageDesc.borderRight = mStyle->border.right;
 		mImageDesc.borderTop = mStyle->border.top;
 		mImageDesc.borderBottom = mStyle->border.bottom;
+
+		mLocStringUpdatedConn = mContent.getText().addOnStringModifiedCallback(boost::bind(&GUIButtonBase::updateRenderElementsInternal, this));
 	}
 
 	GUIButtonBase::~GUIButtonBase()
 	{
+		mLocStringUpdatedConn.disconnect();
+
 		cm_delete<PoolAlloc>(mTextSprite);
 		cm_delete<PoolAlloc>(mImageSprite);
 
@@ -48,6 +52,9 @@ namespace BansheeEngine
 
 	void GUIButtonBase::setContent(const GUIContent& content)
 	{
+		mLocStringUpdatedConn.disconnect();
+		mLocStringUpdatedConn = content.getText().addOnStringModifiedCallback(boost::bind(&GUIButtonBase::updateRenderElementsInternal, this));
+
 		mContent = content;
 
 		markContentAsDirty();

+ 5 - 5
BansheeEngine/Source/BsGUIContent.cpp

@@ -4,11 +4,11 @@ using namespace CamelotFramework;
 
 namespace BansheeEngine
 {
-	GUIContent::GUIContent(const CM::WString& text)
+	GUIContent::GUIContent(const CM::HString& text)
 		:mText(text)
 	{ }
 
-	GUIContent::GUIContent(const CM::WString& text, const CM::WString& tooltip)
+	GUIContent::GUIContent(const CM::HString& text, const CM::HString& tooltip)
 		:mText(text), mTooltipText(tooltip)
 	{ }
 
@@ -16,15 +16,15 @@ namespace BansheeEngine
 		:mImage(image)
 	{ }
 
-	GUIContent::GUIContent(const SpriteTexturePtr& image, const CM::WString& tooltip)
+	GUIContent::GUIContent(const SpriteTexturePtr& image, const CM::HString& tooltip)
 		:mImage(image), mTooltipText(tooltip)
 	{ }
 
-	GUIContent::GUIContent(const CM::WString& text, const SpriteTexturePtr& image)
+	GUIContent::GUIContent(const CM::HString& text, const SpriteTexturePtr& image)
 		:mText(text), mImage(image)
 	{ }
 
-	GUIContent::GUIContent(const CM::WString& text, const SpriteTexturePtr& image, const CM::WString& tooltip)
+	GUIContent::GUIContent(const CM::HString& text, const SpriteTexturePtr& image, const CM::HString& tooltip)
 		:mText(text), mImage(image), mTooltipText(tooltip)
 	{ }
 }

+ 4 - 4
BansheeEngine/Source/BsGUIDropDownBox.cpp

@@ -313,7 +313,7 @@ namespace BansheeEngine
 		{
 			if(mScrollUpBtn == nullptr)
 			{
-				mScrollUpBtn = GUIButton::create(*mOwner, GUIContent(L"", mOwner->mScrollUpBtnArrow), mOwner->mScrollUpStyle);
+				mScrollUpBtn = GUIButton::create(*mOwner, GUIContent(HString(L""), mOwner->mScrollUpBtnArrow), mOwner->mScrollUpStyle);
 				mScrollUpBtn->onClick.connect(boost::bind(&DropDownSubMenu::scrollUp, this));
 			}
 
@@ -361,7 +361,7 @@ namespace BansheeEngine
 				}
 				else
 				{
-					expEntryBtn = GUIButton::create(*mOwner, mElements[i].getLabel(), mOwner->mEntryExpBtnStyle);
+					expEntryBtn = GUIButton::create(*mOwner, HString(mElements[i].getLabel()), mOwner->mEntryExpBtnStyle);
 					expEntryBtn->onHover.connect(boost::bind(&DropDownSubMenu::openSubMenu, this, expEntryBtn, i));
 				}
 
@@ -378,7 +378,7 @@ namespace BansheeEngine
 				}
 				else
 				{
-					entryBtn = GUIButton::create(*mOwner, mElements[i].getLabel(), mOwner->mEntryBtnStyle);
+					entryBtn = GUIButton::create(*mOwner, HString(mElements[i].getLabel()), mOwner->mEntryBtnStyle);
 					entryBtn->onHover.connect(boost::bind(&DropDownSubMenu::closeSubMenu, this));
 					entryBtn->onClick.connect(boost::bind(&DropDownSubMenu::elementClicked, this,  i));
 				}
@@ -407,7 +407,7 @@ namespace BansheeEngine
 		{
 			if(mScrollDownBtn == nullptr)
 			{
-				mScrollDownBtn = GUIButton::create(*mOwner, GUIContent(L"", mOwner->mScrollDownBtnArrow), mOwner->mScrollDownStyle);
+				mScrollDownBtn = GUIButton::create(*mOwner, GUIContent(HString(L""), mOwner->mScrollDownBtnArrow), mOwner->mScrollDownStyle);
 				mScrollDownBtn->onClick.connect(boost::bind(&DropDownSubMenu::scrollDown, this));
 			}
 

+ 10 - 5
BansheeEngine/Source/BsGUILabel.cpp

@@ -16,16 +16,18 @@ namespace BansheeEngine
 	{
 		mTextSprite = cm_new<TextSprite, PoolAlloc>();
 
-		mDesc.text = content.getText();
 		mDesc.font = mStyle->font;
 		mDesc.fontSize = mStyle->fontSize;
 		mDesc.wordWrap = mStyle->wordWrap;
 		mDesc.horzAlign = mStyle->textHorzAlign;
 		mDesc.vertAlign = mStyle->textVertAlign;
+
+		mLocStringUpdatedConn = mContent.getText().addOnStringModifiedCallback(boost::bind(&GUILabel::updateRenderElementsInternal, this));
 	}
 
 	GUILabel::~GUILabel()
 	{
+		mLocStringUpdatedConn.disconnect();
 		cm_delete<PoolAlloc>(mTextSprite);
 	}
 
@@ -48,6 +50,7 @@ namespace BansheeEngine
 	{		
 		mDesc.width = mWidth;
 		mDesc.height = mHeight;
+		mDesc.text = mContent.getText();
 
 		mTextSprite->update(mDesc);
 
@@ -72,18 +75,20 @@ namespace BansheeEngine
 
 	void GUILabel::setContent(const GUIContent& content)
 	{
-		mContent = content;
-		mDesc.text = content.getText();
+		mLocStringUpdatedConn.disconnect();
+		mLocStringUpdatedConn = content.getText().addOnStringModifiedCallback(boost::bind(&GUILabel::updateRenderElementsInternal, this));
 
+		mContent = content;
+		
 		markContentAsDirty();
 	}
 
-	GUILabel* GUILabel::create(GUIWidget& parent, const WString& text, const GUIElementStyle* style)
+	GUILabel* GUILabel::create(GUIWidget& parent, const HString& text, const GUIElementStyle* style)
 	{
 		return create(parent, GUIContent(text), style);
 	}
 
-	GUILabel* GUILabel::create(GUIWidget& parent, const WString& text, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style)
+	GUILabel* GUILabel::create(GUIWidget& parent, const HString& text, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style)
 	{
 		return create(parent, GUIContent(text), layoutOptions, style);
 	}

+ 4 - 4
BansheeEngine/Source/BsGUIListBox.cpp

@@ -21,8 +21,8 @@ namespace BansheeEngine
 		return name;
 	}
 
-	GUIListBox::GUIListBox(GUIWidget& parent, const GUIElementStyle* style, const Vector<WString>::type& elements, const GUILayoutOptions& layoutOptions)
-		:GUIButtonBase(parent, style, GUIContent(L""), layoutOptions), mElements(elements), mSelectedIdx(0), mIsListBoxOpen(false)
+	GUIListBox::GUIListBox(GUIWidget& parent, const GUIElementStyle* style, const Vector<HString>::type& elements, const GUILayoutOptions& layoutOptions)
+		:GUIButtonBase(parent, style, GUIContent(HString(L"")), layoutOptions), mElements(elements), mSelectedIdx(0), mIsListBoxOpen(false)
 	{
 		if(elements.size() > 0)
 			setContent(GUIContent(mElements[mSelectedIdx]));
@@ -33,7 +33,7 @@ namespace BansheeEngine
 		closeListBox();
 	}
 
-	GUIListBox* GUIListBox::create(GUIWidget& parent, const Vector<WString>::type& elements, const GUIElementStyle* style)
+	GUIListBox* GUIListBox::create(GUIWidget& parent, const Vector<HString>::type& elements, const GUIElementStyle* style)
 	{
 		if(style == nullptr)
 		{
@@ -44,7 +44,7 @@ namespace BansheeEngine
 		return new (cm_alloc<GUIListBox, PoolAlloc>()) GUIListBox(parent, style, elements, getDefaultLayoutOptions(style));
 	}
 
-	GUIListBox* GUIListBox::create(GUIWidget& parent, const Vector<WString>::type& elements, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style)
+	GUIListBox* GUIListBox::create(GUIWidget& parent, const Vector<HString>::type& elements, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style)
 	{
 		if(style == nullptr)
 		{

+ 4 - 4
BansheeEngine/Source/BsGUIScrollBar.cpp

@@ -25,8 +25,8 @@ namespace BansheeEngine
 		{
 			mLayout = &addLayoutXInternal(this);
 
-			mUpBtn = GUIButton::create(parent, L"", parent.getSkin().getStyle("ScrollLeftBtn"));
-			mDownBtn = GUIButton::create(parent, L"", parent.getSkin().getStyle("ScrollRightBtn"));
+			mUpBtn = GUIButton::create(parent, HString(L""), parent.getSkin().getStyle("ScrollLeftBtn"));
+			mDownBtn = GUIButton::create(parent, HString(L""), parent.getSkin().getStyle("ScrollRightBtn"));
 
 			mHandleBtn = GUIScrollBarHandle::create(parent, mHorizontal, GUILayoutOptions::expandableX(6), parent.getSkin().getStyle("ScrollBarHorzBtn"));
 		}
@@ -34,8 +34,8 @@ namespace BansheeEngine
 		{
 			mLayout = &addLayoutYInternal(this);
 
-			mUpBtn = GUIButton::create(parent, L"", parent.getSkin().getStyle("ScrollUpBtn"));
-			mDownBtn = GUIButton::create(parent, L"", parent.getSkin().getStyle("ScrollDownBtn"));
+			mUpBtn = GUIButton::create(parent, HString(L""), parent.getSkin().getStyle("ScrollUpBtn"));
+			mDownBtn = GUIButton::create(parent, HString(L""), parent.getSkin().getStyle("ScrollDownBtn"));
 
 			mHandleBtn = GUIScrollBarHandle::create(parent, mHorizontal, GUILayoutOptions::expandableY(6), parent.getSkin().getStyle("ScrollBarVertBtn"));
 		}

+ 4 - 4
BansheeEngine/Source/BsGUIToggle.cpp

@@ -35,22 +35,22 @@ namespace BansheeEngine
 		}
 	}
 
-	GUIToggle* GUIToggle::create(GUIWidget& parent, const WString& text, const GUIElementStyle* style)
+	GUIToggle* GUIToggle::create(GUIWidget& parent, const HString& text, const GUIElementStyle* style)
 	{
 		return create(parent, GUIContent(text), style);
 	}
 
-	GUIToggle* GUIToggle::create(GUIWidget& parent, const GUILayoutOptions& layoutOptions, const WString& text, const GUIElementStyle* style)
+	GUIToggle* GUIToggle::create(GUIWidget& parent, const GUILayoutOptions& layoutOptions, const HString& text, const GUIElementStyle* style)
 	{
 		return create(parent, layoutOptions, GUIContent(text), style);
 	}
 
-	GUIToggle* GUIToggle::create(GUIWidget& parent, const WString& text, std::shared_ptr<GUIToggleGroup> toggleGroup, const GUIElementStyle* style)
+	GUIToggle* GUIToggle::create(GUIWidget& parent, const HString& text, std::shared_ptr<GUIToggleGroup> toggleGroup, const GUIElementStyle* style)
 	{
 		return create(parent, GUIContent(text), toggleGroup, style);
 	}
 
-	GUIToggle* GUIToggle::create(GUIWidget& parent, const GUILayoutOptions& layoutOptions, const WString& text, std::shared_ptr<GUIToggleGroup> toggleGroup, const GUIElementStyle* style)
+	GUIToggle* GUIToggle::create(GUIWidget& parent, const GUILayoutOptions& layoutOptions, const HString& text, std::shared_ptr<GUIToggleGroup> toggleGroup, const GUIElementStyle* style)
 	{
 		return create(parent, layoutOptions, GUIContent(text), toggleGroup, style);
 	}

+ 3 - 3
CamelotClient/Include/BsEditorWidget.h

@@ -10,7 +10,7 @@ namespace BansheeEditor
 	public:
 		virtual ~EditorWidget();
 
-		const CM::WString& getName() const { return mName; }
+		const CM::HString& getName() const { return mName; }
 
 		void _setSize(CM::UINT32 width, CM::UINT32 height);
 		void _setPosition(CM::INT32 x, CM::INT32 y);
@@ -21,9 +21,9 @@ namespace BansheeEditor
 
 		static void destroy(EditorWidget* widget);
 	protected:
-		EditorWidget(const CM::WString& name);
+		EditorWidget(const CM::HString& name);
 
-		CM::WString mName;
+		CM::HString mName;
 		EditorWidgetContainer* mParent;
 		BS::GUIArea* mContent;
 

+ 6 - 3
CamelotClient/Include/BsGUITabButton.h

@@ -13,9 +13,12 @@ namespace BansheeEditor
 	public:
 		static const CM::String& getGUITypeName();
 
-		static GUITabButton* create(BS::GUIWidget& parent, GUITabbedTitleBar* titleBar, CM::UINT32 index, const CM::WString& text, const BS::GUIElementStyle* style = nullptr);
-		static GUITabButton* create(BS::GUIWidget& parent, const BS::GUILayoutOptions& layoutOptions, GUITabbedTitleBar* titleBar, CM::UINT32 index, const CM::WString& text, const BS::GUIElementStyle* style = nullptr);
+		static GUITabButton* create(BS::GUIWidget& parent, GUITabbedTitleBar* titleBar, CM::UINT32 index, const CM::HString& text, const BS::GUIElementStyle* style = nullptr);
+		static GUITabButton* create(BS::GUIWidget& parent, const BS::GUILayoutOptions& layoutOptions, GUITabbedTitleBar* titleBar, CM::UINT32 index, const CM::HString& text, const BS::GUIElementStyle* style = nullptr);
 	
+		static GUITabButton* create(BS::GUIWidget& parent, GUITabbedTitleBar* titleBar, CM::UINT32 index, const BS::GUIContent& content, const BS::GUIElementStyle* style = nullptr);
+		static GUITabButton* create(BS::GUIWidget& parent, const BS::GUILayoutOptions& layoutOptions, GUITabbedTitleBar* titleBar, CM::UINT32 index, const BS::GUIContent& content, const BS::GUIElementStyle* style = nullptr);
+
 		CM::UINT32 getIndex() const { return mIndex; }
 
 		boost::signal<void(CM::UINT32)> onDragged;
@@ -29,6 +32,6 @@ namespace BansheeEditor
 
 		static const CM::UINT32 DRAG_MIN_DISTANCE;
 
-		GUITabButton(BS::GUIWidget& parent, const BS::GUIElementStyle* style, GUITabbedTitleBar* titleBar, CM::UINT32 index, const CM::WString& text, const BS::GUILayoutOptions& layoutOptions);
+		GUITabButton(BS::GUIWidget& parent, const BS::GUIElementStyle* style, GUITabbedTitleBar* titleBar, CM::UINT32 index, const BS::GUIContent& content, const BS::GUILayoutOptions& layoutOptions);
 	};
 }

+ 2 - 2
CamelotClient/Include/BsGUITabbedTitleBar.h

@@ -14,8 +14,8 @@ namespace BansheeEditor
 		void setSize(CM::UINT32 width, CM::UINT32 height);
 		void setPosition(CM::INT32 x, CM::INT32 y);
 
-		void addTab(const CM::WString& name);
-		void insertTab(CM::UINT32 idx, const CM::WString& name);
+		void addTab(const CM::HString& name);
+		void insertTab(CM::UINT32 idx, const CM::HString& name);
 		void removeTab(CM::UINT32 idx);
 
 		boost::signal<void(CM::UINT32)> onTabActivated;

+ 1 - 1
CamelotClient/Source/BsEditorWidget.cpp

@@ -13,7 +13,7 @@ using namespace BansheeEngine;
 
 namespace BansheeEditor
 {
-	EditorWidget::EditorWidget(const WString& name)
+	EditorWidget::EditorWidget(const HString& name)
 		:mName(name), mParent(nullptr), mContent(nullptr)
 	{
 		

+ 4 - 4
CamelotClient/Source/BsGUIMenuBar.cpp

@@ -35,9 +35,9 @@ namespace BansheeEditor
 		mainLayout.addSpace(5);
 		mainLayout.addFlexibleSpace();
 
-		mMinBtn = GUIButton::create(*parent, L"", parent->getSkin().getStyle("WinMinimizeBtn"));
-		mMaxBtn = GUIButton::create(*parent, L"", parent->getSkin().getStyle("WinMaximizeBtn"));
-		mCloseBtn = GUIButton::create(*parent, L"", parent->getSkin().getStyle("WinCloseBtn"));
+		mMinBtn = GUIButton::create(*parent, HString(L""), parent->getSkin().getStyle("WinMinimizeBtn"));
+		mMaxBtn = GUIButton::create(*parent, HString(L""), parent->getSkin().getStyle("WinMaximizeBtn"));
+		mCloseBtn = GUIButton::create(*parent, HString(L""), parent->getSkin().getStyle("WinCloseBtn"));
 
 		mainLayout.addSpace(3);
 		mainLayout.addElement(mMinBtn);
@@ -132,7 +132,7 @@ namespace BansheeEditor
 		newSubMenu.name = name;
 		newSubMenu.menu = cm_new<GUIMenu>();
 
-		GUIButton* newButton = GUIButton::create(*mParentWidget, name, EngineGUI::instance().getSkin().getStyle("MenuBarBtn"));
+		GUIButton* newButton = GUIButton::create(*mParentWidget, HString(name), EngineGUI::instance().getSkin().getStyle("MenuBarBtn"));
 		newButton->onClick.connect(boost::bind(&GUIMenuBar::openSubMenu, this, name));
 		newButton->onHover.connect(boost::bind(&GUIMenuBar::onSubMenuHover, this, name));
 		mMainArea->getLayout().insertElement(mMainArea->getLayout().getNumChildren() - NUM_ELEMENTS_AFTER_CONTENT, newButton);

+ 28 - 6
CamelotClient/Source/BsGUITabButton.cpp

@@ -18,13 +18,13 @@ namespace BansheeEditor
 		return name;
 	}
 
-	GUITabButton::GUITabButton(GUIWidget& parent, const GUIElementStyle* style, GUITabbedTitleBar* titleBar, CM::UINT32 index, const WString& text, const GUILayoutOptions& layoutOptions)
-		:GUIToggle(parent, style, text, nullptr, layoutOptions), mTitleBar(titleBar), mIndex(index)
+	GUITabButton::GUITabButton(GUIWidget& parent, const GUIElementStyle* style, GUITabbedTitleBar* titleBar, CM::UINT32 index, const GUIContent& content, const GUILayoutOptions& layoutOptions)
+		:GUIToggle(parent, style, content, nullptr, layoutOptions), mTitleBar(titleBar), mIndex(index)
 	{
 
 	}
 
-	GUITabButton* GUITabButton::create(GUIWidget& parent, GUITabbedTitleBar* titleBar, CM::UINT32 index, const WString& text, const GUIElementStyle* style)
+	GUITabButton* GUITabButton::create(GUIWidget& parent, GUITabbedTitleBar* titleBar, CM::UINT32 index, const HString& text, const GUIElementStyle* style)
 	{
 		if(style == nullptr)
 		{
@@ -32,10 +32,10 @@ namespace BansheeEditor
 			style = skin.getStyle(getGUITypeName());
 		}
 
-		return new (cm_alloc<GUITabButton, PoolAlloc>()) GUITabButton(parent, style, titleBar, index, text, getDefaultLayoutOptions(style));
+		return new (cm_alloc<GUITabButton, PoolAlloc>()) GUITabButton(parent, style, titleBar, index, GUIContent(text), getDefaultLayoutOptions(style));
 	}
 
-	GUITabButton* GUITabButton::create(GUIWidget& parent, const GUILayoutOptions& layoutOptions, GUITabbedTitleBar* titleBar, CM::UINT32 index, const WString& text, const GUIElementStyle* style)
+	GUITabButton* GUITabButton::create(GUIWidget& parent, const GUILayoutOptions& layoutOptions, GUITabbedTitleBar* titleBar, CM::UINT32 index, const HString& text, const GUIElementStyle* style)
 	{
 		if(style == nullptr)
 		{
@@ -43,7 +43,29 @@ namespace BansheeEditor
 			style = skin.getStyle(getGUITypeName());
 		}
 
-		return new (cm_alloc<GUITabButton, PoolAlloc>()) GUITabButton(parent, style, titleBar, index, text, layoutOptions);
+		return new (cm_alloc<GUITabButton, PoolAlloc>()) GUITabButton(parent, style, titleBar, index, GUIContent(text), layoutOptions);
+	}
+
+	GUITabButton* GUITabButton::create(GUIWidget& parent, GUITabbedTitleBar* titleBar, CM::UINT32 index, const GUIContent& content, const GUIElementStyle* style)
+	{
+		if(style == nullptr)
+		{
+			const GUISkin& skin = parent.getSkin();
+			style = skin.getStyle(getGUITypeName());
+		}
+
+		return new (cm_alloc<GUITabButton, PoolAlloc>()) GUITabButton(parent, style, titleBar, index, content, getDefaultLayoutOptions(style));
+	}
+
+	GUITabButton* GUITabButton::create(GUIWidget& parent, const GUILayoutOptions& layoutOptions, GUITabbedTitleBar* titleBar, CM::UINT32 index, const GUIContent& content, const GUIElementStyle* style)
+	{
+		if(style == nullptr)
+		{
+			const GUISkin& skin = parent.getSkin();
+			style = skin.getStyle(getGUITypeName());
+		}
+
+		return new (cm_alloc<GUITabButton, PoolAlloc>()) GUITabButton(parent, style, titleBar, index, content, layoutOptions);
 	}
 
 	bool GUITabButton::mouseEvent(const GUIMouseEvent& ev)

+ 4 - 4
CamelotClient/Source/BsGUITabbedTitleBar.cpp

@@ -31,8 +31,8 @@ namespace BansheeEditor
 		GUIWindowDropArea* dragDropElement = GUIWindowDropArea::create(*parent, GUILayoutOptions::expandableX(13, 20), parent->getSkin().getStyle("TabbedBarDropArea"));
 		mLastDropElement = dragDropElement;
 
-		mMinBtn = GUIButton::create(*parent, L"", parent->getSkin().getStyle("WinMinimizeBtn"));
-		mCloseBtn = GUIButton::create(*parent, L"", parent->getSkin().getStyle("WinCloseBtn"));
+		mMinBtn = GUIButton::create(*parent, HString(L""), parent->getSkin().getStyle("WinMinimizeBtn"));
+		mCloseBtn = GUIButton::create(*parent, HString(L""), parent->getSkin().getStyle("WinCloseBtn"));
 
 		mCloseBtn->onClick.connect(boost::bind(&GUITabbedTitleBar::tabClosed, this));
 
@@ -67,12 +67,12 @@ namespace BansheeEditor
 		}
 	}
 
-	void GUITabbedTitleBar::addTab(const CM::WString& name)
+	void GUITabbedTitleBar::addTab(const CM::HString& name)
 	{
 		insertTab((UINT32)mTabButtons.size(), name);
 	}
 
-	void GUITabbedTitleBar::insertTab(UINT32 idx, const CM::WString& name)
+	void GUITabbedTitleBar::insertTab(UINT32 idx, const CM::HString& name)
 	{
 		GUITabButton* newTabToggle = GUITabButton::create(*mParentWidget, this, mUniqueTabIdx, name, EngineGUI::instance().getSkin().getStyle("TabbedBarBtn"));
 		GUIWindowDropArea* newDragDropElement = GUIWindowDropArea::create(*mParentWidget, EngineGUI::instance().getSkin().getStyle("TabbedBarDropArea"));

+ 6 - 6
CamelotClient/Source/CmTestTextSprite.cpp

@@ -44,13 +44,13 @@ namespace CamelotFramework
 
 		SpriteTexturePtr spriteTex = std::make_shared<SpriteTexture>(sceneView->getBindableColorTexture());
 		area->getLayout().addElement(GUITexture::create(*this, GUILayoutOptions::fixed(800, 600), spriteTex));
-		mLabel = GUILabel::create(*this, L"");
+		mLabel = GUILabel::create(*this, HString(L""));
 		area->getLayout().addElement(mLabel);
 
-		Vector<WString>::type dropDownElements;
-		dropDownElements.push_back(L"Ejlement #1");
-		dropDownElements.push_back(L"Element #2");
-		dropDownElements.push_back(L"Element #3");
+		Vector<HString>::type dropDownElements;
+		dropDownElements.push_back(HString(L"Ejlement #1"));
+		dropDownElements.push_back(HString(L"Element #2"));
+		dropDownElements.push_back(HString(L"Element #3"));
 		area->getLayout().addElement(GUIListBox::create(*this, dropDownElements, GUILayoutOptions::fixed(50, 13)));
 		area->getLayout().addFlexibleSpace();
 	}
@@ -59,6 +59,6 @@ namespace CamelotFramework
 	{
 		WString value = toWString(toString(Input::instance().getCursorPosition().x) + " - " + toString(Input::instance().getCursorPosition().y));
 
-		mLabel->setContent(GUIContent(value));
+		mLabel->setContent(GUIContent(HString(L"")));
 	}
 }

+ 1 - 1
CamelotClient/Source/DbgEditorWidget1.cpp

@@ -17,7 +17,7 @@ namespace BansheeEditor
 	DbgEditorWidget1* DbgEditorWidget1::Instance = nullptr;
 
 	DbgEditorWidget1::DbgEditorWidget1()
-		:EditorWidget(L"DbgEditorWidget1")
+		:EditorWidget(HString(L"DbgEditorWidget1"))
 	{
 		
 	}

+ 6 - 6
CamelotClient/Source/DbgEditorWidget2.cpp

@@ -16,7 +16,7 @@ namespace BansheeEditor
 	DbgEditorWidget2* DbgEditorWidget2::Instance = nullptr;
 
 	DbgEditorWidget2::DbgEditorWidget2()
-		:EditorWidget(L"DbgEditorWidget2")
+		:EditorWidget(HString(L"DbgEditorWidget2"))
 	{
 
 	}
@@ -37,11 +37,11 @@ namespace BansheeEditor
 
 		std::shared_ptr<GUIToggleGroup> toggleGroup = GUIToggle::createToggleGroup();
 
-		scrollLayout.addElement(GUIToggle::create(getParentWidget(), L"Test A", toggleGroup, EngineGUI::instance().getSkin().getStyle("Button")));
-		scrollLayout.addElement(GUIToggle::create(getParentWidget(), L"Test B", toggleGroup, EngineGUI::instance().getSkin().getStyle("Button")));
-		scrollLayout.addElement(GUIToggle::create(getParentWidget(), L"Test C", toggleGroup, EngineGUI::instance().getSkin().getStyle("Button")));
-		scrollLayout.addElement(GUIToggle::create(getParentWidget(), L"Test D", toggleGroup, EngineGUI::instance().getSkin().getStyle("Button")));
-		scrollLayout.addElement(GUIToggle::create(getParentWidget(), L"Test E", toggleGroup, EngineGUI::instance().getSkin().getStyle("Button")));
+		scrollLayout.addElement(GUIToggle::create(getParentWidget(), HString(L"Test A"), toggleGroup, EngineGUI::instance().getSkin().getStyle("Button")));
+		scrollLayout.addElement(GUIToggle::create(getParentWidget(), HString(L"Test B"), toggleGroup, EngineGUI::instance().getSkin().getStyle("Button")));
+		scrollLayout.addElement(GUIToggle::create(getParentWidget(), HString(L"Test C"), toggleGroup, EngineGUI::instance().getSkin().getStyle("Button")));
+		scrollLayout.addElement(GUIToggle::create(getParentWidget(), HString(L"Test D"), toggleGroup, EngineGUI::instance().getSkin().getStyle("Button")));
+		scrollLayout.addElement(GUIToggle::create(getParentWidget(), HString(L"Test E"), toggleGroup, EngineGUI::instance().getSkin().getStyle("Button")));
 	}
 
 	DbgEditorWidget2* DbgEditorWidget2::instance()

+ 3 - 0
CamelotCore/Source/CmApplication.cpp

@@ -28,6 +28,7 @@
 #include "CmRenderer.h"
 #include "CmDeferredCallManager.h"
 #include "CmCoreThread.h"
+#include "CmStringTable.h"
 
 #include "CmMaterial.h"
 #include "CmShader.h"
@@ -48,6 +49,7 @@ namespace CamelotFramework
 	{
 		MemStack::setupHeap(HID_Main);
 
+		StringTable::startUp(cm_new<StringTable>());
 		DeferredCallManager::startUp(cm_new<DeferredCallManager>());
 		Time::startUp(cm_new<Time>());
 		DynLibManager::startUp(cm_new<DynLibManager>());
@@ -165,6 +167,7 @@ namespace CamelotFramework
 		DynLibManager::shutDown();
 		Time::shutDown();
 		DeferredCallManager::shutDown();
+		StringTable::shutDown();
 	}
 
 	void* Application::loadPlugin(const String& pluginName)

+ 26 - 10
CamelotUtility/Include/CmHString.h

@@ -1,6 +1,5 @@
 #pragma once
 
-#include "CmPrerequisitesUtil.h"
 #include <boost/signals.hpp>
 
 namespace CamelotFramework
@@ -16,20 +15,37 @@ namespace CamelotFramework
 	class CM_UTILITY_EXPORT HString
 	{
 	public:
-		HString(const WString& identifierString);
+		class CM_UTILITY_EXPORT StringData
+		{
+		public:
+			StringData();
+			~StringData();
+
+			mutable boost::signal<void()> onStringModified;
+
+		private:
+			friend class HString;
+
+			LocalizedStringData* mStringData;
+			WString* mParameters;
+			boost::signals::connection mUpdateConn;
+
+			mutable bool mIsDirty;
+			mutable WString mCachedString;
+		};
+
+		explicit HString(const WString& identifierString);
+		HString();
+		HString(const HString& copy);
 		~HString();
 
-		operator const WString& () const { return mCachedString; }
+		operator const WString& () const;
 		void setParameter(UINT32 idx, const WString& value);
 
-		boost::signal<void()> onStringModified;
+		boost::signals::connection addOnStringModifiedCallback(boost::function<void()> callback) const;
 	private:
-		LocalizedStringData* mStringData;
-		WString* mParameters;
-		boost::signals::connection mUpdateConn;
-
-		WString mCachedString;
+		std::shared_ptr<StringData> mData;
 
-		void updateString(const WString& identifierString);
+		void updateString();
 	};
 }

+ 1 - 1
CamelotUtility/Include/CmPrerequisitesUtil.h

@@ -28,7 +28,7 @@ THE SOFTWARE
 #include <assert.h>
 
 // 0 - No thread support
-// 1 - Render system is thread safe (NOT WORKING and will probably be removed)
+// 1 - Render system is thread safe (TODO: NOT WORKING and will probably be removed)
 // 2 - Thread support but render system can only be accessed from main thread
 #define CM_THREAD_SUPPORT 2
 

+ 2 - 0
CamelotUtility/Include/CmString.h

@@ -749,4 +749,6 @@ namespace CamelotFramework
 
 } // namespace CamelotFramework
 
+#include "CmHString.h"
+
 #endif // _String_H__

+ 2 - 1
CamelotUtility/Include/CmStringTable.h

@@ -203,7 +203,8 @@ namespace CamelotFramework
 	{
 		struct Common
 		{
-			boost::signal<void(const WString& identifier)> onStringDataModified;
+			WString identifier;
+			boost::signal<void()> onStringDataModified;
 		};
 
 		struct ParamOffset

+ 60 - 16
CamelotUtility/Source/CmHString.cpp

@@ -1,43 +1,87 @@
+#include "CmPrerequisitesUtil.h"
 #include "CmHString.h"
 #include "CmStringTable.h"
 
 namespace CamelotFramework
 {
+	HString::StringData::StringData()
+		:mParameters(nullptr), mIsDirty(true)
+	{ }
+
+	HString::StringData::~StringData()
+	{
+		mUpdateConn.disconnect();
+
+		if(mParameters != nullptr)
+			cm_deleteN(mParameters, mStringData->numParameters);
+	}
+
+	HString::HString()
+	{
+		mData = cm_shared_ptr<StringData>();
+
+		mData->mStringData = &StringTable::instance().getStringData(L"");
+		mData->mParameters = cm_newN<WString>(mData->mStringData->numParameters);
+		mData->mUpdateConn = mData->mStringData->commonData->onStringDataModified.connect(boost::bind(&HString::updateString, this));
+	}
+
 	HString::HString(const WString& identifierString)
-		:mParameters(nullptr)
 	{
-		mStringData = &StringTable::instance().getStringData(identifierString);
-		mParameters = cm_newN<WString>(mStringData->numParameters);
-		mUpdateConn = mStringData->commonData->onStringDataModified.connect(boost::bind(&HString::updateString, this, _1));
+		mData = cm_shared_ptr<StringData>();
+
+		mData->mStringData = &StringTable::instance().getStringData(identifierString);
+		mData->mParameters = cm_newN<WString>(mData->mStringData->numParameters);
+		mData->mUpdateConn = mData->mStringData->commonData->onStringDataModified.connect(boost::bind(&HString::updateString, this));
+	}
 
-		updateString(identifierString);
+	HString::HString(const HString& copy)
+	{
+		mData = copy.mData;
 	}
 
 	HString::~HString()
 	{
-		mUpdateConn.disconnect();
 
-		if(mParameters != nullptr)
-			cm_deleteN(mParameters, mStringData->numParameters);
+	}
+
+	HString::operator const WString& () const 
+	{ 
+		if(mData->mIsDirty)
+		{
+			mData->mCachedString = mData->mStringData->concatenateString(mData->mParameters, mData->mStringData->numParameters);
+			mData->mIsDirty = false;
+		}
+
+		return mData->mCachedString; 
 	}
 
 	void HString::setParameter(UINT32 idx, const WString& value)
 	{
-		mParameters[idx] = value;
+		mData->mParameters[idx] = value;
+
+		mData->mIsDirty = true;
+		mData->onStringModified();
 	}
 
-	void HString::updateString(const WString& identifierString)
+	boost::signals::connection HString::addOnStringModifiedCallback(boost::function<void()> callback) const
 	{
-		LocalizedStringData* stringData = &StringTable::instance().getStringData(identifierString);
+		return mData->onStringModified.connect(callback);
+	}
+
+	void HString::updateString()
+	{
+		LocalizedStringData* stringData = &StringTable::instance().getStringData(mData->mStringData->commonData->identifier);
 
 		// If common data changed re-apply the connections
-		if(stringData->commonData != mStringData->commonData)
+		if(stringData->commonData != mData->mStringData->commonData)
 		{
-			mUpdateConn.disconnect();
-			mUpdateConn = stringData->commonData->onStringDataModified.connect(boost::bind(&HString::updateString, this, _1));
+			mData->mUpdateConn.disconnect();
+			mData->mUpdateConn = stringData->commonData->onStringDataModified.connect(boost::bind(&HString::updateString, this));
 		}
 
-		mStringData = stringData;
-		mCachedString = mStringData->concatenateString(mParameters, mStringData->numParameters);
+		mData->mStringData = stringData;
+		mData->mIsDirty = true;
+
+		mData->onStringModified();
 	}
 }

+ 4 - 3
CamelotUtility/Source/CmStringTable.cpp

@@ -175,6 +175,7 @@ namespace CamelotFramework
 			if(iterFindCommon == mCommonData.end())
 			{
 				common = cm_new<LocalizedStringData::Common>();
+				common->identifier = identifier;
 				mCommonData[identifier] = common;
 			}
 			else
@@ -194,7 +195,7 @@ namespace CamelotFramework
 		if(mActiveLanguage == language)
 		{
 			if(!stringData->commonData->onStringDataModified.empty())
-				stringData->commonData->onStringDataModified(identifier);
+				stringData->commonData->onStringDataModified();
 		}
 	}
 
@@ -228,7 +229,7 @@ namespace CamelotFramework
 			mCommonData.erase(findIterCommon);
 
 			if(!common->onStringDataModified.empty())
-				common->onStringDataModified(identifier);
+				common->onStringDataModified();
 		}
 
 		if(stringData != nullptr)
@@ -272,7 +273,7 @@ namespace CamelotFramework
 		for(auto& iter : mCommonData)
 		{
 			if(!iter.second->onStringDataModified.empty())
-				iter.second->onStringDataModified(iter.first);
+				iter.second->onStringDataModified();
 		}
 	}
 }

+ 6 - 0
TODO.txt

@@ -1,5 +1,11 @@
 ----------------------- CAMELOT 2D / GUI -----------------------------------------------------------
 
+LONGTERM TODO:
+1. Finish localization
+2. Finish docking manager
+3. Window drag'n'drop detect
+4. Basic profiler
+
 I still re-create GUIWidget mesh every frame instead of just updating it.
 
 MAJOR ISSUE: writeSubresource/readSubresoure doesn't require a shared ptr to GpuResourceData which means it could get destroyed while still in command queue. Right now it only works because I block right after I call those methods, which ensures nothing is destroyed.