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

Tree view now renders properly

Marko Pintera 12 лет назад
Родитель
Сommit
60305ce936

+ 1 - 0
CamelotClient/Include/BsEditorPrerequisites.h

@@ -19,6 +19,7 @@ namespace BansheeEditor
 	class WindowFrameWidget;
 	class WindowFrameWidget;
 	class GUIMenuBar;
 	class GUIMenuBar;
 	class GUIDockSlider;
 	class GUIDockSlider;
+	class GUISceneTreeView;
 
 
 	enum class DragAndDropType
 	enum class DragAndDropType
 	{
 	{

+ 3 - 2
CamelotClient/Include/BsGUISceneTreeView.h

@@ -36,8 +36,7 @@ namespace BansheeEditor
 			BS::GUIElementStyle* backgroundStyle = nullptr, BS::GUIElementStyle* elementBtnStyle = nullptr, 
 			BS::GUIElementStyle* backgroundStyle = nullptr, BS::GUIElementStyle* elementBtnStyle = nullptr, 
 			BS::GUIElementStyle* foldoutBtnStyle = nullptr);
 			BS::GUIElementStyle* foldoutBtnStyle = nullptr);
 
 
-		static GUISceneTreeView* create(BS::GUIWidget& parent, const BS::GUILayoutOptions& layoutOptions);
-		static GUISceneTreeView* create(BS::GUIWidget& parent, const BS::GUILayoutOptions& layoutOptions, 
+		static GUISceneTreeView* create(BS::GUIWidget& parent, const BS::GUIOptions& options, 
 			BS::GUIElementStyle* backgroundStyle = nullptr, BS::GUIElementStyle* elementBtnStyle = nullptr, 
 			BS::GUIElementStyle* backgroundStyle = nullptr, BS::GUIElementStyle* elementBtnStyle = nullptr, 
 			BS::GUIElementStyle* foldoutBtnStyle = nullptr);
 			BS::GUIElementStyle* foldoutBtnStyle = nullptr);
 
 
@@ -46,6 +45,7 @@ namespace BansheeEditor
 	protected:
 	protected:
 		virtual ~GUISceneTreeView();
 		virtual ~GUISceneTreeView();
 
 
+		CM::Vector2I _getOptimalSize() const;
 		void updateClippedBounds();
 		void updateClippedBounds();
 
 
 		void _updateLayoutInternal(CM::INT32 x, CM::INT32 y, CM::UINT32 width, CM::UINT32 height,
 		void _updateLayoutInternal(CM::INT32 x, CM::INT32 y, CM::UINT32 width, CM::UINT32 height,
@@ -53,6 +53,7 @@ namespace BansheeEditor
 	protected:
 	protected:
 		static const CM::UINT32 ELEMENT_EXTRA_SPACING;
 		static const CM::UINT32 ELEMENT_EXTRA_SPACING;
 		static const CM::UINT32 INDENT_SIZE;
 		static const CM::UINT32 INDENT_SIZE;
+		static const CM::UINT32 INITIAL_INDENT_OFFSET;
 
 
 		const BS::GUIElementStyle* mBackgroundStyle;
 		const BS::GUIElementStyle* mBackgroundStyle;
 		const BS::GUIElementStyle* mElementBtnStyle;
 		const BS::GUIElementStyle* mElementBtnStyle;

+ 7 - 6
CamelotClient/Include/CmTestTextSprite.h

@@ -1,25 +1,26 @@
-#include "BsPrerequisites.h"
+#include "BsEditorPrerequisites.h"
 #include "BsGUIWidget.h"
 #include "BsGUIWidget.h"
 
 
-namespace CamelotFramework
+namespace BansheeEditor
 {
 {
-	class TestTextSprite : public BansheeEngine::GUIWidget
+	class TestTextSprite : public BS::GUIWidget
 	{
 	{
 	protected:
 	protected:
 		friend class CM::SceneObject;
 		friend class CM::SceneObject;
 
 
-		TestTextSprite(const HSceneObject& parent, CM::Viewport* target);
+		TestTextSprite(const CM::HSceneObject& parent, CM::Viewport* target);
 	public:
 	public:
 		~TestTextSprite();
 		~TestTextSprite();
 
 
 		virtual void update();
 		virtual void update();
 
 
-		void init(const BS::HCamera& camera, const String& text, CM::RenderTexturePtr sceneView);
+		void init(const BS::HCamera& camera, const CM::String& text, CM::RenderTexturePtr sceneView);
 
 
 	private:
 	private:
 		BS::GUILabel* mLabel;
 		BS::GUILabel* mLabel;
 		BS::GUIListBox* mListBox;
 		BS::GUIListBox* mListBox;
-		HString labelString;
+		GUISceneTreeView* mSceneTreeView;
+		CM::HString labelString;
 
 
 		void dbgBtn();
 		void dbgBtn();
 	};
 	};

+ 92 - 14
CamelotClient/Source/BsGUISceneTreeView.cpp

@@ -18,6 +18,7 @@ namespace BansheeEditor
 {
 {
 	const UINT32 GUISceneTreeView::ELEMENT_EXTRA_SPACING = 3;
 	const UINT32 GUISceneTreeView::ELEMENT_EXTRA_SPACING = 3;
 	const UINT32 GUISceneTreeView::INDENT_SIZE = 10;
 	const UINT32 GUISceneTreeView::INDENT_SIZE = 10;
+	const UINT32 GUISceneTreeView::INITIAL_INDENT_OFFSET = 10;
 
 
 	GUISceneTreeView::TreeElement::TreeElement()
 	GUISceneTreeView::TreeElement::TreeElement()
 		:mParent(nullptr), mFoldoutBtn(nullptr), mElement(nullptr),
 		:mParent(nullptr), mFoldoutBtn(nullptr), mElement(nullptr),
@@ -68,16 +69,11 @@ namespace BansheeEditor
 			GUILayoutOptions::create(&GUISkin::DefaultStyle));
 			GUILayoutOptions::create(&GUISkin::DefaultStyle));
 	}
 	}
 
 
-	GUISceneTreeView* GUISceneTreeView::create(GUIWidget& parent, const GUILayoutOptions& layoutOptions)
-	{
-		return new (cm_alloc<GUISceneTreeView, PoolAlloc>()) GUISceneTreeView(parent, nullptr, nullptr, nullptr, layoutOptions);
-	}
-
-	GUISceneTreeView* GUISceneTreeView::create(GUIWidget& parent, const GUILayoutOptions& layoutOptions, GUIElementStyle* backgroundStyle,
+	GUISceneTreeView* GUISceneTreeView::create(GUIWidget& parent, const GUIOptions& options, GUIElementStyle* backgroundStyle,
 		GUIElementStyle* elementBtnStyle, GUIElementStyle* foldoutBtnStyle)
 		GUIElementStyle* elementBtnStyle, GUIElementStyle* foldoutBtnStyle)
 	{
 	{
 		return new (cm_alloc<GUISceneTreeView, PoolAlloc>()) GUISceneTreeView(parent, backgroundStyle, elementBtnStyle, 
 		return new (cm_alloc<GUISceneTreeView, PoolAlloc>()) GUISceneTreeView(parent, backgroundStyle, elementBtnStyle, 
-			foldoutBtnStyle, layoutOptions);
+			foldoutBtnStyle, GUILayoutOptions::create(options, &GUISkin::DefaultStyle));
 	}
 	}
 
 
 	void GUISceneTreeView::update()
 	void GUISceneTreeView::update()
@@ -140,11 +136,12 @@ namespace BansheeEditor
 					mTempToDelete.resize(current->mChildren.size(), true);
 					mTempToDelete.resize(current->mChildren.size(), true);
 					for(UINT32 i = 0; i < currentSO->getNumChildren(); i++)
 					for(UINT32 i = 0; i < currentSO->getNumChildren(); i++)
 					{
 					{
-						UINT32 curId = currentSO->getChild(i)->getId();
+						HSceneObject currentSOChild = currentSO->getChild(i);
+						UINT32 curId = currentSOChild->getId();
 						bool found = false;
 						bool found = false;
 						for(UINT32 j = 0; j < current->mChildren.size(); j++)
 						for(UINT32 j = 0; j < current->mChildren.size(); j++)
 						{
 						{
-							TreeElement* currentChild = current->mChildren[i];
+							TreeElement* currentChild = current->mChildren[j];
 
 
 							if(curId == currentChild->mId)
 							if(curId == currentChild->mId)
 							{
 							{
@@ -162,9 +159,9 @@ namespace BansheeEditor
 						{
 						{
 							TreeElement* newChild = cm_new<TreeElement>();
 							TreeElement* newChild = cm_new<TreeElement>();
 							newChild->mParent = current;
 							newChild->mParent = current;
-							newChild->mSceneObject = currentSO;
-							newChild->mId = currentSO->getId();
-							newChild->mName = currentSO->getName();
+							newChild->mSceneObject = currentSOChild;
+							newChild->mId = currentSOChild->getId();
+							newChild->mName = currentSOChild->getName();
 							newChild->mSortedIdx = (UINT32)newChildren.size();
 							newChild->mSortedIdx = (UINT32)newChildren.size();
 							newChild->mIsDirty = true;
 							newChild->mIsDirty = true;
 
 
@@ -222,6 +219,12 @@ namespace BansheeEditor
 			{
 			{
 				if(updateElement.visible)
 				if(updateElement.visible)
 				{
 				{
+					if(current->mElement == nullptr)
+					{
+						HString name(toWString(current->mName));
+						current->mElement = GUILabel::create(_getParentWidget(), name);
+					}
+
 					// TODO - If no label exists create it
 					// TODO - If no label exists create it
 					// TODO - If has children and no expand button exists create it
 					// TODO - If has children and no expand button exists create it
 					// TODO - If it has no children but an expand button exists remove it
 					// TODO - If it has no children but an expand button exists remove it
@@ -229,6 +232,11 @@ namespace BansheeEditor
 				else
 				else
 				{
 				{
 					// TODO - If either label or expand button exist remove them
 					// TODO - If either label or expand button exist remove them
+					if(current->mElement != nullptr)
+					{
+						GUIElement::destroy(current->mElement);
+						current->mElement = nullptr;
+					}
 				}
 				}
 
 
 				markContentAsDirty();
 				markContentAsDirty();
@@ -240,7 +248,7 @@ namespace BansheeEditor
 			{
 			{
 				for(UINT32 i = 0; i < (UINT32)current->mChildren.size(); i++)
 				for(UINT32 i = 0; i < (UINT32)current->mChildren.size(); i++)
 				{
 				{
-					todo.push(UpdateTreeElement(current->mChildren[i], i, current->mIsVisible && current->mIsExpanded));
+					todo.push(UpdateTreeElement(current->mChildren[i], i, current->mIsVisible /*&& current->mIsExpanded*/)); // TODO - Not checking for mIsExpanded atm
 				}
 				}
 			}
 			}
 		}
 		}
@@ -253,6 +261,76 @@ namespace BansheeEditor
 		return false;
 		return false;
 	}
 	}
 
 
+	Vector2I GUISceneTreeView::_getOptimalSize() const
+	{
+		struct UpdateTreeElement
+		{
+			UpdateTreeElement(const TreeElement* element, UINT32 indent)
+				:element(element), indent(indent)
+			{ }
+
+			const TreeElement* element;
+			UINT32 indent;
+		};
+
+		Vector2I optimalSize;
+
+		if(_getLayoutOptions().fixedWidth && _getLayoutOptions().fixedHeight)
+		{
+			optimalSize.x = _getLayoutOptions().width;
+			optimalSize.y = _getLayoutOptions().height;
+		}
+		else
+		{
+			Stack<UpdateTreeElement>::type todo;
+			todo.push(UpdateTreeElement(&mRootElement, 0));
+
+			while(!todo.empty())
+			{
+				UpdateTreeElement currentUpdateElement = todo.top();
+				const TreeElement* current = currentUpdateElement.element;
+				todo.pop();
+
+				if(current->mElement != nullptr)
+				{
+					Vector2I curOptimalSize = current->mElement->_getOptimalSize();
+					optimalSize.x = std::max(optimalSize.x, 
+						(INT32)(INITIAL_INDENT_OFFSET + curOptimalSize.x + currentUpdateElement.indent * INDENT_SIZE));
+					optimalSize.y += optimalSize.y + ELEMENT_EXTRA_SPACING;
+				}
+
+				for(auto& child : current->mChildren)
+				{
+					todo.push(UpdateTreeElement(child, currentUpdateElement.indent + 1));
+				}
+			}
+
+			if(_getLayoutOptions().fixedWidth)
+				optimalSize.x = _getLayoutOptions().width;
+			else
+			{
+				if(_getLayoutOptions().minWidth > 0)
+					optimalSize.x = std::max((INT32)_getLayoutOptions().minWidth, optimalSize.y);
+
+				if(_getLayoutOptions().maxWidth > 0)
+					optimalSize.x = std::min((INT32)_getLayoutOptions().maxWidth, optimalSize.y);
+			}
+
+			if(_getLayoutOptions().fixedHeight)
+				optimalSize.y = _getLayoutOptions().height;
+			else
+			{
+				if(_getLayoutOptions().minHeight > 0)
+					optimalSize.y = std::max((INT32)_getLayoutOptions().minHeight, optimalSize.y);
+
+				if(_getLayoutOptions().maxHeight > 0)
+					optimalSize.y = std::min((INT32)_getLayoutOptions().maxHeight, optimalSize.y);
+			}
+		}
+
+		return optimalSize;
+	}
+
 	void GUISceneTreeView::updateClippedBounds()
 	void GUISceneTreeView::updateClippedBounds()
 	{
 	{
 		Vector2I offset = _getOffset();
 		Vector2I offset = _getOffset();
@@ -295,7 +373,7 @@ namespace BansheeEditor
 				{
 				{
 					Vector2I elementSize = child->mElement->_getOptimalSize();
 					Vector2I elementSize = child->mElement->_getOptimalSize();
 
 
-					offset.x = indent * INDENT_SIZE;
+					offset.x = INITIAL_INDENT_OFFSET + indent * INDENT_SIZE;
 
 
 					child->mElement->_setOffset(offset);
 					child->mElement->_setOffset(offset);
 					child->mElement->_setWidth(elementSize.x);
 					child->mElement->_setWidth(elementSize.x);

+ 22 - 16
CamelotClient/Source/CmTestTextSprite.cpp

@@ -24,10 +24,12 @@
 #include "CmPlatform.h"
 #include "CmPlatform.h"
 #include "BsGUIContent.h"
 #include "BsGUIContent.h"
 #include "CmStringTable.h"
 #include "CmStringTable.h"
+#include "BsGUISceneTreeView.h"
 
 
+using namespace CamelotFramework;
 using namespace BansheeEngine;
 using namespace BansheeEngine;
 
 
-namespace CamelotFramework
+namespace BansheeEditor
 {
 {
 	TestTextSprite::TestTextSprite(const HSceneObject& parent, CM::Viewport* target)
 	TestTextSprite::TestTextSprite(const HSceneObject& parent, CM::Viewport* target)
 		:GUIWidget(parent, target), mListBox(nullptr)
 		:GUIWidget(parent, target), mListBox(nullptr)
@@ -45,16 +47,19 @@ namespace CamelotFramework
 
 
 		GUIArea* area = GUIArea::createStretchedXY(*this, 0, 0, 0, 0);
 		GUIArea* area = GUIArea::createStretchedXY(*this, 0, 0, 0, 0);
 
 
-		area->getLayout().addElement(GUIRenderTexture::create(*this, sceneView, GUIOptions(GUIOption::fixedWidth(800), GUIOption::fixedHeight(600))));
-		mLabel = GUILabel::create(*this, HString(L""));
-		area->getLayout().addElement(mLabel);
+		mSceneTreeView = GUISceneTreeView::create(*this, GUIOptions(GUIOption::flexibleWidth(), GUIOption::flexibleHeight()));
+		area->getLayout().addElement(mSceneTreeView);
 
 
-		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"));
-		mListBox = GUIListBox::create(*this, dropDownElements, GUIOptions(GUIOption::fixedWidth(50), GUIOption::fixedHeight(13)));
-		area->getLayout().addElement(mListBox);
+		//area->getLayout().addElement(GUIRenderTexture::create(*this, sceneView, GUIOptions(GUIOption::fixedWidth(800), GUIOption::fixedHeight(600))));
+		//mLabel = GUILabel::create(*this, HString(L""));
+		//area->getLayout().addElement(mLabel);
+
+		//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"));
+		//mListBox = GUIListBox::create(*this, dropDownElements, GUIOptions(GUIOption::fixedWidth(50), GUIOption::fixedHeight(13)));
+		//area->getLayout().addElement(mListBox);
 
 
 		GUIButton* button = GUIButton::create(*this, HString(L"dbgBtn"));
 		GUIButton* button = GUIButton::create(*this, HString(L"dbgBtn"));
 		button->onClick.connect(boost::bind(&TestTextSprite::dbgBtn, this));
 		button->onClick.connect(boost::bind(&TestTextSprite::dbgBtn, this));
@@ -63,12 +68,13 @@ namespace CamelotFramework
 		area->getLayout().addFlexibleSpace();
 		area->getLayout().addFlexibleSpace();
 
 
 		labelString = HString(L"\\{0}, {1}");
 		labelString = HString(L"\\{0}, {1}");
-		mLabel->setContent(GUIContent(labelString));
+		//mLabel->setContent(GUIContent(labelString));
 	}
 	}
 
 
 	void TestTextSprite::update()
 	void TestTextSprite::update()
 	{
 	{
 		labelString.setParameter(0, toWString(Input::instance().getCursorPosition().x));
 		labelString.setParameter(0, toWString(Input::instance().getCursorPosition().x));
+		mSceneTreeView->update();
 		//labelString.setParameter(1, toWString(Input::instance().getCursorPosition().y));
 		//labelString.setParameter(1, toWString(Input::instance().getCursorPosition().y));
 	}
 	}
 
 
@@ -78,12 +84,12 @@ namespace CamelotFramework
 
 
 		if(dbg == 0)
 		if(dbg == 0)
 		{
 		{
-			Vector<HString>::type dropDownElements;
-			dropDownElements.push_back(HString(L"Element #4"));
-			dropDownElements.push_back(HString(L"Element #5"));
-			dropDownElements.push_back(HString(L"Element #6"));
+			//Vector<HString>::type dropDownElements;
+			//dropDownElements.push_back(HString(L"Element #4"));
+			//dropDownElements.push_back(HString(L"Element #5"));
+			//dropDownElements.push_back(HString(L"Element #6"));
 
 
-			mListBox->setElements(dropDownElements);
+			//mListBox->setElements(dropDownElements);
 
 
 			//StringTable::instance().setString(L"dbgBtn", Language::Abkhazian, L"ALOALO");
 			//StringTable::instance().setString(L"dbgBtn", Language::Abkhazian, L"ALOALO");
 			//StringTable::instance().setActiveLanguage(Language::Abkhazian);
 			//StringTable::instance().setActiveLanguage(Language::Abkhazian);