Przeglądaj źródła

Ensured that EditorWidgets no longer require 2 step initialization
Fixed various issues with saving/loading of widget layouts (especially dock layouts)
Made core thread accessors threadlocal and added generic command methods to accessors

Marko Pintera 11 lat temu
rodzic
commit
ac6b038635

+ 6 - 3
BansheeEditor/Include/BsDockManager.h

@@ -22,13 +22,17 @@ namespace BansheeEditor
 			~DockContainer();
 
 			void setArea(CM::INT32 x, CM::INT32 y, CM::UINT32 width, CM::UINT32 height);
-			void makeLeaf(BS::GUIWidget* widgetParent, CM::RenderWindow* parentWindow, EditorWidgetBase* widget);
+			void makeLeaf(BS::GUIWidget* widgetParent, CM::RenderWindow* parentWindow);
 			void makeLeaf(EditorWidgetContainer* existingContainer);
+			void splitContainer(BS::GUIWidget* widgetParent, CM::RenderWindow* parentWindow, bool horizontal, bool newChildIsFirst, float splitPosition = 0.5f);
 			void addLeft(BS::GUIWidget* widgetParent, CM::RenderWindow* parentWindow, EditorWidgetBase* widget);
 			void addRight(BS::GUIWidget* widgetParent, CM::RenderWindow* parentWindow, EditorWidgetBase* widget);
 			void addTop(BS::GUIWidget* widgetParent, CM::RenderWindow* parentWindow, EditorWidgetBase* widget);
 			void addBottom(BS::GUIWidget* widgetParent, CM::RenderWindow* parentWindow, EditorWidgetBase* widget);
 
+			void addWidget(EditorWidgetBase* widget);
+			void addWidget(const CM::String& name);
+
 			DockContainer* find(EditorWidgetContainer* widgetContainer);
 
 			/**
@@ -55,7 +59,6 @@ namespace BansheeEditor
 			static const CM::UINT32 MIN_CHILD_SIZE;
 
 		private:
-			void splitContainer(BS::GUIWidget* widgetParent, CM::RenderWindow* parentWindow, EditorWidgetBase* widget, bool horizontal, bool newChildIsFirst);
 			void updateChildAreas();
 
 			void sliderDragged(const CM::Vector2I& delta);
@@ -82,7 +85,7 @@ namespace BansheeEditor
 		void insert(EditorWidgetContainer* relativeTo, EditorWidgetBase* widgetToInsert, DockLocation location);
 
 		DockManagerLayoutPtr getLayout() const;
-		void setLayout(const DockManagerLayoutPtr& layout, const CM::Vector<EditorWidgetBase*>::type& widgets);
+		void setLayout(const DockManagerLayoutPtr& layout);
 
 		void setArea(CM::INT32 x, CM::INT32 y, CM::UINT32 width, CM::UINT32 height);
 

+ 5 - 7
BansheeEditor/Include/BsEditorWidget.h

@@ -9,8 +9,6 @@ namespace BansheeEditor
 	class BS_ED_EXPORT EditorWidgetBase
 	{
 	public:
-		virtual void initialize() { }
-
 		const CM::String& getName() const { return mName; }
 		const CM::HString& getDisplayName() const { return mDisplayName; }
 
@@ -26,7 +24,7 @@ namespace BansheeEditor
 	protected:
 		friend class EditorWidgetManager;
 
-		EditorWidgetBase(const CM::HString& displayName, const CM::String& name);
+		EditorWidgetBase(const CM::HString& displayName, const CM::String& name, EditorWidgetContainer& parentContainer);
 		virtual ~EditorWidgetBase();
 
 		CM::String mName;
@@ -48,9 +46,9 @@ namespace BansheeEditor
 			EditorWidgetManager::preRegisterWidget(Type::getTypeName(), &create);
 		}
 
-		static EditorWidgetBase* create()
+		static EditorWidgetBase* create(EditorWidgetContainer& parentContainer)
 		{
-			return cm_new<Type>(EditorWidget<Type>::ConstructPrivately());
+			return cm_new<Type>(EditorWidget<Type>::ConstructPrivately(), parentContainer);
 		}
 
 		void makeSureIAmInstantiated() { }
@@ -66,8 +64,8 @@ namespace BansheeEditor
 
 		struct ConstructPrivately {};
 
-		EditorWidget(const CM::HString& displayName)
-			:EditorWidgetBase(displayName, Type::getTypeName())
+		EditorWidget(const CM::HString& displayName, EditorWidgetContainer& parentContainer)
+			:EditorWidgetBase(displayName, Type::getTypeName(), parentContainer)
 		{
 			RegisterOnStart.makeSureIAmInstantiated();
 		}

+ 2 - 0
BansheeEditor/Include/BsEditorWidgetContainer.h

@@ -41,6 +41,8 @@ namespace BansheeEditor
 
 		static const CM::UINT32 TitleBarHeight;
 
+		void removeInternal(EditorWidgetBase& widget);
+
 		void setActiveWidget(CM::UINT32 idx);
 		void tabActivated(CM::UINT32 idx);
 		void tabClosed(CM::UINT32 idx);

+ 9 - 7
BansheeEditor/Include/BsEditorWidgetManager.h

@@ -23,7 +23,7 @@ namespace BansheeEditor
 		 * @param	name				  	Unique name for the widget.
 		 * @param 	createCallback			Callback that returns a new instance of the widget.
 		 */
-		void registerWidget(const CM::String& name, std::function<EditorWidgetBase*()> createCallback);
+		void registerWidget(const CM::String& name, std::function<EditorWidgetBase*(EditorWidgetContainer&)> createCallback);
 
 		/**
 		 * @brief	Creates a widget with the given name. If widget is already created it returns the existing instance.
@@ -35,6 +35,11 @@ namespace BansheeEditor
 		 */
 		EditorWidgetBase* open(const CM::String& name);
 
+		/**
+		 * @brief	Creates a new widget an inserts it into the specified container.
+		 */
+		EditorWidgetBase* create(const CM::String& name, EditorWidgetContainer& parentContainer);
+
 		/**
 		 * @brief	Closes the given widget.
 		 */
@@ -59,15 +64,12 @@ namespace BansheeEditor
 		 * @note	Useful primarily when widgets are being registered from static methods, because then there is no
 		 * 			EditorWidgetManager instance yet.
 		 */
-		static void preRegisterWidget(const CM::String& name, std::function<EditorWidgetBase*()> createCallback);
+		static void preRegisterWidget(const CM::String& name, std::function<EditorWidgetBase*(EditorWidgetContainer&)> createCallback);
 
 	private:
 		CM::Map<CM::String, EditorWidgetBase*>::type mActiveWidgets;
-		CM::Map<CM::String, std::function<EditorWidgetBase*()>>::type mCreateCallbacks;
-
-		static CM::Stack<std::pair<CM::String, std::function<EditorWidgetBase*()>>>::type QueuedCreateCallbacks;
+		CM::Map<CM::String, std::function<EditorWidgetBase*(EditorWidgetContainer&)>>::type mCreateCallbacks;
 
-		bool isOpen(const CM::String& name) const;
-		EditorWidgetBase* create(const CM::String& name);
+		static CM::Stack<std::pair<CM::String, std::function<EditorWidgetBase*(EditorWidgetContainer&)>>>::type QueuedCreateCallbacks;
 	};
 }

+ 1 - 4
BansheeEditor/Include/DbgEditorWidget1.h

@@ -8,7 +8,7 @@ namespace BansheeEditor
 	class DbgEditorWidget1 : public EditorWidget<DbgEditorWidget1>
 	{
 	public:
-		DbgEditorWidget1(const ConstructPrivately& dummy);
+		DbgEditorWidget1(const ConstructPrivately& dummy, EditorWidgetContainer& parentContainer);
 		virtual ~DbgEditorWidget1();
 
 		static DbgEditorWidget1* instance();
@@ -16,9 +16,6 @@ namespace BansheeEditor
 		static void close();
 		static const CM::String& getTypeName();
 
-	protected:
-		void initialize();
-
 	private:
 		static DbgEditorWidget1* Instance;
 	};

+ 1 - 4
BansheeEditor/Include/DbgEditorWidget2.h

@@ -8,7 +8,7 @@ namespace BansheeEditor
 	class DbgEditorWidget2 : public EditorWidget<DbgEditorWidget2>
 	{
 	public:
-		DbgEditorWidget2(const ConstructPrivately& dummy);
+		DbgEditorWidget2(const ConstructPrivately& dummy, EditorWidgetContainer& parentContainer);
 		virtual ~DbgEditorWidget2();
 
 		static DbgEditorWidget2* instance();
@@ -16,9 +16,6 @@ namespace BansheeEditor
 		static void close();
 		static const CM::String& getTypeName();
 
-	protected:
-		void initialize();
-
 	private:
 		static DbgEditorWidget2* Instance;
 	};

+ 57 - 55
BansheeEditor/Source/BsDockManager.cpp

@@ -1,6 +1,7 @@
 #include "BsDockManager.h"
 #include "BsEditorWidgetContainer.h"
 #include "BsEditorWidget.h"
+#include "BsEditorWidgetManager.h"
 #include "CmMath.h"
 #include "CmException.h"
 #include "CmMesh.h"
@@ -126,7 +127,7 @@ namespace BansheeEditor
 		}
 	}
 
-	void DockManager::DockContainer::makeLeaf(GUIWidget* widgetParent, RenderWindow* parentWindow, EditorWidgetBase* widget)
+	void DockManager::DockContainer::makeLeaf(GUIWidget* widgetParent, RenderWindow* parentWindow)
 	{
 		mIsLeaf = true;
 		mWidgets = cm_new<EditorWidgetContainer>(widgetParent, parentWindow, nullptr);
@@ -139,7 +140,6 @@ namespace BansheeEditor
 			mSlider = nullptr;
 		}
 
-		mWidgets->add(*widget);
 		mWidgets->setPosition(mArea.x, mArea.y);
 		mWidgets->setSize(mArea.width, mArea.height);
 	}
@@ -163,25 +163,37 @@ namespace BansheeEditor
 
 	void DockManager::DockContainer::addLeft(BS::GUIWidget* widgetParent, RenderWindow* parentWindow, EditorWidgetBase* widget)
 	{
-		splitContainer(widgetParent, parentWindow, widget, false, true);
+		if(mIsLeaf)
+			splitContainer(widgetParent, parentWindow, false, true);
+
+		mChildren[0]->addWidget(widget);
 	}
 
 	void DockManager::DockContainer::addRight(BS::GUIWidget* widgetParent, RenderWindow* parentWindow, EditorWidgetBase* widget)
 	{
-		splitContainer(widgetParent, parentWindow, widget, false, false);
+		if(mIsLeaf)
+			splitContainer(widgetParent, parentWindow, false, false);
+
+		mChildren[1]->addWidget(widget);
 	}
 
 	void DockManager::DockContainer::addTop(BS::GUIWidget* widgetParent, RenderWindow* parentWindow, EditorWidgetBase* widget)
 	{
-		splitContainer(widgetParent, parentWindow, widget, true, true);
+		if(mIsLeaf)
+			splitContainer(widgetParent, parentWindow, true, true);
+
+		mChildren[0]->addWidget(widget);
 	}
 
 	void DockManager::DockContainer::addBottom(BS::GUIWidget* widgetParent, RenderWindow* parentWindow, EditorWidgetBase* widget)
 	{
-		splitContainer(widgetParent, parentWindow, widget, true, false);
+		if(mIsLeaf)
+			splitContainer(widgetParent, parentWindow, true, false);
+
+		mChildren[1]->addWidget(widget);
 	}
 
-	void DockManager::DockContainer::splitContainer(BS::GUIWidget* widgetParent, RenderWindow* parentWindow, EditorWidgetBase* widget, bool horizontal, bool newChildIsFirst)
+	void DockManager::DockContainer::splitContainer(BS::GUIWidget* widgetParent, RenderWindow* parentWindow, bool horizontal, bool newChildIsFirst, float splitPosition)
 	{
 		UINT32 idxA = newChildIsFirst ? 0 : 1;
 		UINT32 idxB = (idxA + 1) % 2;
@@ -191,13 +203,13 @@ namespace BansheeEditor
 
 		mWidgets->onWidgetClosed.disconnect_all_slots();
 
-		mChildren[idxA]->makeLeaf(widgetParent, parentWindow, widget);
+		mChildren[idxA]->makeLeaf(widgetParent, parentWindow);
 		mChildren[idxB]->makeLeaf(mWidgets);
 
 		mIsLeaf = false;
 		mIsHorizontal = horizontal;
 		mWidgets = nullptr;
-		mSplitPosition = 0.5f;
+		mSplitPosition = splitPosition;
 
 		if(horizontal)
 		{
@@ -215,6 +227,22 @@ namespace BansheeEditor
 		setArea(mArea.x, mArea.y, mArea.width, mArea.height);
 	}
 
+	void DockManager::DockContainer::addWidget(EditorWidgetBase* widget)
+	{
+		if(!mIsLeaf)
+			return;
+
+		mWidgets->add(*widget);
+	}
+
+	void DockManager::DockContainer::addWidget(const CM::String& name)
+	{
+		if(!mIsLeaf)
+			return;
+
+		EditorWidgetManager::instance().create(name, *mWidgets);
+	}
+
 	void DockManager::DockContainer::sliderDragged(const CM::Vector2I& delta)
 	{
 		if(mIsHorizontal && delta.y != 0)
@@ -430,7 +458,8 @@ namespace BansheeEditor
 			if(mRootContainer.mWidgets != nullptr)
 				CM_EXCEPT(InternalErrorException, "Trying to insert a widget into dock manager root container but one already exists.");
 
-			mRootContainer.makeLeaf(mParent, mParentWindow, widgetToInsert);
+			mRootContainer.makeLeaf(mParent, mParentWindow);
+			mRootContainer.addWidget(widgetToInsert);
 		}
 	}
 
@@ -510,8 +539,11 @@ namespace BansheeEditor
 					else
 					{
 						currentElem.layoutEntry->children[i] = 
-							DockManagerLayout::Entry::createContainer(currentElem.layoutEntry, i, currentElem.container->mSplitPosition, 
-							currentElem.container->mIsHorizontal);
+							DockManagerLayout::Entry::createContainer(currentElem.layoutEntry, i, 
+							currentElem.container->mChildren[i]->mSplitPosition, 
+							currentElem.container->mChildren[i]->mIsHorizontal);
+
+						todo.push(StackElem(currentElem.layoutEntry->children[i], currentElem.container->mChildren[i]));
 					}
 				}
 			}
@@ -520,7 +552,7 @@ namespace BansheeEditor
 		return layout;
 	}
 
-	void DockManager::setLayout(const DockManagerLayoutPtr& layout, const Vector<EditorWidgetBase*>::type& widgets)
+	void DockManager::setLayout(const DockManagerLayoutPtr& layout)
 	{
 		// Undock all currently docked widgets
 		Vector<EditorWidgetBase*>::type undockedWidgets;
@@ -579,35 +611,22 @@ namespace BansheeEditor
 			return nullptr;
 		};
 
-		auto GetWidgets = [&] (const Vector<String>::type& widgetNames)
+		auto OpenWidgets = [&] (DockContainer* parent, const Vector<String>::type& widgetNames)
 		{
-			Vector<EditorWidgetBase*>::type resultWidgets;
 			for(auto& widgetName : widgetNames)
 			{
-				for(auto& widget : widgets)
-				{
-					if(widgetName == widget->getName())
-					{
-						resultWidgets.push_back(widget);
-						break;
-					}
-				}
+				parent->addWidget(widgetName);
 			}
-
-			return resultWidgets;
 		};
 
 		// Dock elements
 		const DockManagerLayout::Entry* rootEntry = &layout->getRootEntry();
 		const DockManagerLayout::Entry* leafEntry = GetLeafEntry(rootEntry, 0);
-		Vector<EditorWidgetBase*>::type currentWidgets = GetWidgets(leafEntry->widgetNames);
 
-		if(currentWidgets.size() > 0) // If zero, entire layout is empty
+		if(leafEntry->widgetNames.size() > 0) // If zero, entire layout is empty
 		{
-			mRootContainer.makeLeaf(mParent, mParentWindow, currentWidgets[0]);
-
-			for(UINT32 i = 1; i < (UINT32)currentWidgets.size(); i++)
-				mRootContainer.mWidgets->add(*currentWidgets[i]);
+			mRootContainer.makeLeaf(mParent, mParentWindow);
+			OpenWidgets(&mRootContainer, leafEntry->widgetNames);
 
 			if(!rootEntry->isLeaf)
 			{
@@ -620,34 +639,17 @@ namespace BansheeEditor
 					layoutTodo.pop();
 
 					leafEntry = GetLeafEntry(curEntry.layoutEntry->children[1], 0);
-					currentWidgets = GetWidgets(leafEntry->widgetNames);
-
-					bool isEmpty = currentWidgets.size() == 0;
-
-					if(!isEmpty)
-					{
-						if(curEntry.layoutEntry->horizontalSplit)
-							curEntry.container->addBottom(mParent, mParentWindow, currentWidgets[0]);
-						else
-							curEntry.container->addRight(mParent, mParentWindow, currentWidgets[0]);
 
-						curEntry.container->mSplitPosition = curEntry.layoutEntry->splitPosition;
+					curEntry.container->splitContainer(mParent, mParentWindow, curEntry.layoutEntry->horizontalSplit, false, curEntry.layoutEntry->splitPosition);
 
-						DockContainer* otherChild = curEntry.container->mChildren[1];
-						for(UINT32 i = 1; i < (UINT32)currentWidgets.size(); i++)
-							otherChild->mWidgets->add(*currentWidgets[i]);
+					DockContainer* otherChild = curEntry.container->mChildren[1];
+					OpenWidgets(otherChild, leafEntry->widgetNames);
 
-						if(!curEntry.layoutEntry->children[0]->isLeaf)
-							layoutTodo.push(StackEntry(curEntry.layoutEntry->children[0], curEntry.container->mChildren[0]));
+					if(!curEntry.layoutEntry->children[0]->isLeaf)
+						layoutTodo.push(StackEntry(curEntry.layoutEntry->children[0], curEntry.container->mChildren[0]));
 
-						if(!curEntry.layoutEntry->children[1]->isLeaf)
-							layoutTodo.push(StackEntry(curEntry.layoutEntry->children[1], curEntry.container->mChildren[1]));
-					}
-					else
-					{
-						if(!curEntry.layoutEntry->children[0]->isLeaf)
-							layoutTodo.push(StackEntry(curEntry.layoutEntry->children[0], curEntry.container));
-					}
+					if(!curEntry.layoutEntry->children[1]->isLeaf)
+						layoutTodo.push(StackEntry(curEntry.layoutEntry->children[1], curEntry.container->mChildren[1]));
 				}
 			}
 		}

+ 2 - 2
BansheeEditor/Source/BsEditorApplication.cpp

@@ -72,12 +72,12 @@ namespace BansheeEditor
 		MainEditorWindow* mainWindow = MainEditorWindow::create(gApplication().getPrimaryWindow());
 		EditorWidgetManager::startUp(cm_new<EditorWidgetManager>());
 
+		gApplication().loadPlugin("SBansheeEditor"); // Managed part of the editor
+
 		EditorWidgetLayoutPtr layout = loadWidgetLayout();
 		if(layout != nullptr)
 			EditorWidgetManager::instance().setLayout(layout);
 
-		gApplication().loadPlugin("SBansheeEditor"); // Managed part of the editor
-
 		/************************************************************************/
 		/* 								DEBUG CODE                      		*/
 		/************************************************************************/

+ 3 - 2
BansheeEditor/Source/BsEditorWidget.cpp

@@ -14,10 +14,10 @@ using namespace BansheeEngine;
 
 namespace BansheeEditor
 {
-	EditorWidgetBase::EditorWidgetBase(const HString& displayName, const CM::String& name)
+	EditorWidgetBase::EditorWidgetBase(const HString& displayName, const CM::String& name, EditorWidgetContainer& parentContainer)
 		:mDisplayName(displayName), mName(name), mParent(nullptr), mContent(nullptr)
 	{
-		
+		parentContainer.add(*this);
 	}
 
 	EditorWidgetBase::~EditorWidgetBase()
@@ -52,6 +52,7 @@ namespace BansheeEditor
 		mContent->setSize(width, height);
 	}
 
+	// Note: Must not be virtual as parent container uses it in constructor
 	void EditorWidgetBase::_changeParent(EditorWidgetContainer* parent)
 	{
 		if(mParent != parent) 

+ 11 - 3
BansheeEditor/Source/BsEditorWidgetContainer.cpp

@@ -48,6 +48,14 @@ namespace BansheeEditor
 	}
 
 	void EditorWidgetContainer::remove(EditorWidgetBase& widget)
+	{
+		removeInternal(widget);
+
+		if(!onWidgetClosed.empty())
+			onWidgetClosed();
+	}
+
+	void EditorWidgetContainer::removeInternal(EditorWidgetBase& widget)
 	{
 		INT32 tabIdx = 0;
 		for(auto& curWidget : mWidgets)
@@ -68,9 +76,9 @@ namespace BansheeEditor
 
 		if(tabIdx == mActiveWidget)
 		{
+			mActiveWidget = -1;
 			if(mTitleBar->getNumTabs() > 0)
 			{
-				mActiveWidget = -1;
 				setActiveWidget(mTitleBar->getTabIdx(0));
 			}
 		}
@@ -189,7 +197,7 @@ namespace BansheeEditor
 	void EditorWidgetContainer::tabDraggedOff(CM::UINT32 uniqueIdx)
 	{
 		EditorWidgetBase* widget = mWidgets[uniqueIdx];
-		remove(*widget);
+		removeInternal(*widget);
 
 		// TODO - Hook up drag and drop texture
 		DragAndDropManager::instance().startDrag(HTexture(), (UINT32)DragAndDropType::EditorWidget, (void*)widget, 
@@ -243,7 +251,7 @@ namespace BansheeEditor
 		{
 			if(curWidget.second == widget)
 			{
-				remove(*widget);
+				removeInternal(*widget);
 
 				if(!onWidgetClosed.empty())
 					onWidgetClosed();

+ 26 - 49
BansheeEditor/Source/BsEditorWidgetManager.cpp

@@ -13,20 +13,20 @@ using namespace BansheeEngine;
 
 namespace BansheeEditor
 {
-	Stack<std::pair<String, std::function<EditorWidgetBase*()>>>::type EditorWidgetManager::QueuedCreateCallbacks;
+	Stack<std::pair<String, std::function<EditorWidgetBase*(EditorWidgetContainer&)>>>::type EditorWidgetManager::QueuedCreateCallbacks;
 
 	EditorWidgetManager::EditorWidgetManager()
 	{
 		while(!QueuedCreateCallbacks.empty())
 		{
-			std::pair<String, std::function<EditorWidgetBase*()>> curElement = QueuedCreateCallbacks.top();
+			std::pair<String, std::function<EditorWidgetBase*(EditorWidgetContainer&)>> curElement = QueuedCreateCallbacks.top();
 			QueuedCreateCallbacks.pop();
 
 			registerWidget(curElement.first, curElement.second);
 		}
 	}
 
-	void EditorWidgetManager::registerWidget(const String& name, std::function<EditorWidgetBase*()> createCallback)
+	void EditorWidgetManager::registerWidget(const String& name, std::function<EditorWidgetBase*(EditorWidgetContainer&)> createCallback)
 	{
 		auto iterFind = mCreateCallbacks.find(name);
 
@@ -43,13 +43,13 @@ namespace BansheeEditor
 		if(iterFind != mActiveWidgets.end())
 			return iterFind->second;
 
-		EditorWidgetBase* newWidget = create(name);
+		EditorWindow* window = EditorWindow::create();
+		EditorWidgetBase* newWidget = create(name, window->widgets());
 		if(newWidget == nullptr)
+		{
+			window->close();
 			return nullptr;
-
-		EditorWindow* window = EditorWindow::create();
-		window->widgets().add(*newWidget);
-		newWidget->initialize();
+		}
 
 		return newWidget;
 	}
@@ -68,25 +68,28 @@ namespace BansheeEditor
 		EditorWidgetBase::destroy(widget);
 	}
 
-	bool EditorWidgetManager::isOpen(const CM::String& name) const
+	EditorWidgetBase* EditorWidgetManager::create(const CM::String& name, EditorWidgetContainer& parentContainer)
 	{
 		auto iterFind = mActiveWidgets.find(name);
 
-		return iterFind != mActiveWidgets.end();
-	}
+		if(iterFind != mActiveWidgets.end())
+		{
+			EditorWidgetBase* existingWidget = iterFind->second;
+			if(existingWidget->_getParent() != nullptr && existingWidget->_getParent() != &parentContainer)
+				existingWidget->_getParent()->remove(*existingWidget);
 
-	EditorWidgetBase* EditorWidgetManager::create(const CM::String& name)
-	{
-		auto iterFind = mActiveWidgets.find(name);
+			if(existingWidget->_getParent() != &parentContainer)
+				parentContainer.add(*iterFind->second);
 
-		if(iterFind != mActiveWidgets.end())
 			return iterFind->second;
+		}
 
 		auto iterFindCreate = mCreateCallbacks.find(name);
 		if(iterFindCreate == mCreateCallbacks.end())
 			return nullptr;
 
-		EditorWidgetBase* newWidget = mCreateCallbacks[name]();
+		EditorWidgetBase* newWidget = mCreateCallbacks[name](parentContainer);
+		parentContainer.add(*newWidget);
 
 		if(newWidget != nullptr)
 			mActiveWidgets[name] = newWidget;
@@ -152,26 +155,6 @@ namespace BansheeEditor
 
 	void EditorWidgetManager::setLayout(const EditorWidgetLayoutPtr& layout)
 	{
-		Vector<EditorWidgetBase*>::type openWidgets;
-		Vector<EditorWidgetBase*>::type widgetsNeedInitialization;
-
-		// Create any necessary widgets
-		for(auto& entry : layout->getEntries())
-		{
-			for(auto& widgetName : entry.widgetNames)
-			{
-				bool needsInitialization = !isOpen(widgetName);
-				EditorWidgetBase* newWidget = create(widgetName);
-				if(newWidget != nullptr)
-				{
-					openWidgets.push_back(newWidget);
-
-					if(needsInitialization)
-						widgetsNeedInitialization.push_back(newWidget);
-				}
-			}
-		}
-
 		// Unparent all widgets
 		Vector<EditorWidgetBase*>::type unparentedWidgets;
 		for(auto& widget : mActiveWidgets)
@@ -191,27 +174,21 @@ namespace BansheeEditor
 			EditorWindow* window = EditorWindow::create();
 			for(auto& widgetName : entry.widgetNames)
 			{
-				EditorWidgetBase* widget = create(widgetName); // This will returned previously created widget
-				if(widget != nullptr)
-					window->widgets().add(*widget);
+				create(widgetName, window->widgets());
 			}
 
 			window->setPosition(entry.x, entry.y);
 			window->setSize(entry.width, entry.height);
+
+			if(window->widgets().getNumWidgets() == 0)
+				window->close();
 		}
 
 		// Restore docked widgets
 		MainEditorWindow* mainWindow = EditorWindowManager::instance().getMainWindow();
 		DockManager& dockManager = mainWindow->getDockManager();
 
-		dockManager.setLayout(layout->getDockLayout(), openWidgets);
-
-		// Initialize any newly opened widgets
-		for(auto& widget : widgetsNeedInitialization)
-		{
-			if(widget->_getParent() != nullptr)
-				widget->initialize();
-		}
+		dockManager.setLayout(layout->getDockLayout());
 
 		// Destroy any widgets that are no longer have parents
 		for(auto& widget : unparentedWidgets)
@@ -221,8 +198,8 @@ namespace BansheeEditor
 		}
 	}
 
-	void EditorWidgetManager::preRegisterWidget(const String& name, std::function<EditorWidgetBase*()> createCallback)
+	void EditorWidgetManager::preRegisterWidget(const String& name, std::function<EditorWidgetBase*(EditorWidgetContainer&)> createCallback)
 	{
-		QueuedCreateCallbacks.push(std::pair<String, std::function<EditorWidgetBase*()>>(name, createCallback));
+		QueuedCreateCallbacks.push(std::pair<String, std::function<EditorWidgetBase*(EditorWidgetContainer&)>>(name, createCallback));
 	}
 }

+ 7 - 12
BansheeEditor/Source/DbgEditorWidget1.cpp

@@ -15,18 +15,8 @@ namespace BansheeEditor
 {
 	DbgEditorWidget1* DbgEditorWidget1::Instance = nullptr;
 
-	DbgEditorWidget1::DbgEditorWidget1(const ConstructPrivately& dummy)
-		:EditorWidget<DbgEditorWidget1>(HString(L"DbgEditorWidget1"))
-	{
-		
-	}
-
-	DbgEditorWidget1::~DbgEditorWidget1()
-	{
-
-	}
-
-	void DbgEditorWidget1::initialize()
+	DbgEditorWidget1::DbgEditorWidget1(const ConstructPrivately& dummy, EditorWidgetContainer& parentContainer)
+		:EditorWidget<DbgEditorWidget1>(HString(L"DbgEditorWidget1"), parentContainer)
 	{
 		GUILayout& layout = mContent->getLayout();
 		//
@@ -83,6 +73,11 @@ namespace BansheeEditor
 		//mRenderWindow->setVisible(false);
 	}
 
+	DbgEditorWidget1::~DbgEditorWidget1()
+	{
+
+	}
+
 	DbgEditorWidget1* DbgEditorWidget1::instance()
 	{
 		return Instance;

+ 7 - 12
BansheeEditor/Source/DbgEditorWidget2.cpp

@@ -14,18 +14,8 @@ namespace BansheeEditor
 {
 	DbgEditorWidget2* DbgEditorWidget2::Instance = nullptr;
 
-	DbgEditorWidget2::DbgEditorWidget2(const ConstructPrivately& dummy)
-		:EditorWidget<DbgEditorWidget2>(HString(L"DbgEditorWidget2"))
-	{
-
-	}
-
-	DbgEditorWidget2::~DbgEditorWidget2()
-	{
-
-	}
-
-	void DbgEditorWidget2::initialize()
+	DbgEditorWidget2::DbgEditorWidget2(const ConstructPrivately& dummy, EditorWidgetContainer& parentContainer)
+		:EditorWidget<DbgEditorWidget2>(HString(L"DbgEditorWidget2"), parentContainer)
 	{
 		GUILayout& layout = mContent->getLayout();
 
@@ -43,6 +33,11 @@ namespace BansheeEditor
 		scrollLayout.addElement(GUIToggle::create(getParentWidget(), HString(L"Test E"), toggleGroup, getParentWidget().getSkin().getStyle("Button")));
 	}
 
+	DbgEditorWidget2::~DbgEditorWidget2()
+	{
+
+	}
+
 	DbgEditorWidget2* DbgEditorWidget2::instance()
 	{
 		return Instance;

+ 1 - 1
BansheeMono/Include/BsMonoClass.h

@@ -44,7 +44,7 @@ namespace BansheeEngine
 
 		::MonoClass* _getInternalClass() const { return mClass; }
 
-		MonoObject* createInstance() const;
+		MonoObject* createInstance(bool construct = true) const;
 		MonoObject* createInstance(void** params, CM::UINT32 numParams);
 	private:
 		friend class MonoAssembly;

+ 4 - 2
BansheeMono/Source/BsMonoClass.cpp

@@ -144,10 +144,12 @@ namespace BansheeEngine
 		mono_add_internal_call(fullMethodName.c_str(), method);
 	}
 
-	MonoObject* MonoClass::createInstance() const
+	MonoObject* MonoClass::createInstance(bool construct) const
 	{
 		MonoObject* obj = mono_object_new(MonoManager::instance().getDomain(), mClass);
-		mono_runtime_object_init(obj);
+
+		if(construct)
+			mono_runtime_object_init(obj);
 
 		return obj;
 	}

+ 22 - 13
CamelotCore/Include/CmCoreThread.h

@@ -10,26 +10,31 @@ namespace CamelotFramework
 	 * @brief	Manager for the core thread. Takes care of starting, running, queuing commands
 	 * 			and shutting down the core thread.
 	 */
-	class CM_EXPORT CoreThread : public Module<CoreThread>
+	class CoreThread : public Module<CoreThread>
 	{
+		struct AccessorContainer
+		{
+			CoreAccessorPtr accessor;
+		};
+
 public:
-	CoreThread();
-	~CoreThread();
+	CM_EXPORT CoreThread();
+	CM_EXPORT ~CoreThread();
 
 	/**
 		* @brief	Returns the id of the core thread. If a separate core thread
 		* 			is not used, then it returns the id of the thread RenderSystem
 		* 			was initialized on.
 		*/
-	CM_THREAD_ID_TYPE getCoreThreadId() { return mCoreThreadId; }
+	CM_EXPORT CM_THREAD_ID_TYPE getCoreThreadId() { return mCoreThreadId; }
 
 	/**
-		* @brief	Creates an accessor that you can use for executing commands on the core thread from 
+		* @brief	Creates or retrieves an accessor that you can use for executing commands on the core thread from 
 		* 			a non-core thread. You can have as many of these as you wish, the only limitation
 		* 			is that you do not use a single instance on more than one thread. Each thread
 		* 			requires its own accessor. The accessor will be bound to the thread you call this method on.
 		*/
-	CoreAccessorPtr createAccessor();
+	CM_EXPORT CoreAccessorPtr getAccessor();
 
 	/**
 	* @brief	Retrieves an accessor that you can use for executing commands on the core thread from
@@ -37,35 +42,35 @@ public:
 	* 			Note however that it is much more efficient to create a separate non-synchronized accessor using
 	* 			"createCoreAccessor" for each thread you will be using it on.
 		*/
-	SyncedCoreAccessor& getSyncedAccessor();
+	CM_EXPORT SyncedCoreAccessor& getSyncedAccessor();
 
 	/**
 		* @brief	Queues a new command that will be added to the global command queue. You are allowed to call this from any thread,
 		* 			however be aware that it involves possibly slow synchronization primitives, so limit your usage.
 		* 			
-		* @param	blockUntilComplete If true the thread will be blocked until the command executes. Be aware that there be many commands queued before it
+		* @param	blockUntilComplete If true the thread will be blocked until the command executes. Be aware that there may be many commands queued before it
 		* 							   and they all need to be executed in order before the current command is reached, which might take a long time.
 		* 	
 		* @see		CommandQueue::queueReturn
 		*/
-	AsyncOp queueReturnCommand(boost::function<void(AsyncOp&)> commandCallback, bool blockUntilComplete = false);
+	CM_EXPORT AsyncOp queueReturnCommand(boost::function<void(AsyncOp&)> commandCallback, bool blockUntilComplete = false);
 
 	/**
 	* @brief	Queues a new command that will be added to the global command queue.You are allowed to call this from any thread,
 		* 			however be aware that it involves possibly slow synchronization primitives, so limit your usage.
 		* 	
-		* @param	blockUntilComplete If true the thread will be blocked until the command executes. Be aware that there be many commands queued before it
+		* @param	blockUntilComplete If true the thread will be blocked until the command executes. Be aware that there may be many commands queued before it
 		* 							   and they all need to be executed in order before the current command is reached, which might take a long time.
 		* @see		CommandQueue::queue
 		*/
-	void queueCommand(boost::function<void()> commandCallback, bool blockUntilComplete = false);
+	CM_EXPORT void queueCommand(boost::function<void()> commandCallback, bool blockUntilComplete = false);
 
 	/**
 	 * @brief	Called once every frame.
 	 * 			
 	 * @note	Must be called before sim thread schedules any CoreThread operations that frame. 
 	 */
-	void update();
+	CM_EXPORT void update();
 
 	/**
 	 * @brief	Returns a frame allocator that should be used for allocating temporary data being passed to the
@@ -74,7 +79,7 @@ public:
 	 * 			
 	 * @note	Sim thread only.
 	 */
-	FrameAlloc* getFrameAlloc() const;
+	CM_EXPORT FrameAlloc* getFrameAlloc() const;
 private:
 	class CoreThreadWorkerFunc CM_THREAD_WORKER_INHERIT
 	{
@@ -92,6 +97,9 @@ private:
 	FrameAlloc* mFrameAllocs[2]; 
 	UINT32 mActiveFrameAlloc;
 
+	static CM_THREADLOCAL AccessorContainer* mAccessor;
+	Vector<AccessorContainer*>::type mAccessors;
+
 	CoreThreadWorkerFunc* mCoreThreadFunc;
 	volatile bool mCoreThreadStarted;
 	volatile bool mCoreThreadShutdown;
@@ -100,6 +108,7 @@ private:
 	CM_THREAD_SYNCHRONISER(mCoreThreadStartCondition)
 	CM_MUTEX(mCoreThreadStartMutex)
 	CM_MUTEX(mCommandQueueMutex)
+	CM_MUTEX(mAccessorMutex)
 	CM_THREAD_SYNCHRONISER(mCommandReadyCondition)
 	CM_MUTEX(mCommandNotifyMutex)
 	CM_THREAD_SYNCHRONISER(mCommandCompleteCondition)

+ 16 - 0
CamelotCore/Include/CmCoreThreadAccessor.h

@@ -245,6 +245,22 @@ namespace CamelotFramework
 			mCommandQueue->queue(boost::bind(&RenderWindow::setHidden, renderWindow.get(), false));
 		}
 
+		/**
+		* @brief	Queues a new generic command that will be added to the command queue.
+		*/
+		AsyncOp queueReturnCommand(boost::function<void(AsyncOp&)> commandCallback)
+		{
+			return mCommandQueue->queueReturn(commandCallback);
+		}
+
+		/**
+		* @brief	Queues a new generic command that will be added to the command queue.
+		*/
+		void queueCommand(boost::function<void()> commandCallback)
+		{
+			mCommandQueue->queue(commandCallback);
+		}
+
 		/**
 		 * @brief	Makes all the currently queued commands available to the core thread. They will be executed
 		 * 			as soon as the core thread is ready.

+ 1 - 1
CamelotCore/Source/CmApplication.cpp

@@ -74,7 +74,7 @@ namespace CamelotFramework
 		loadPlugin(desc.renderer);
 		RendererManager::instance().setActive(desc.renderer);
 
-		mPrimaryCoreAccessor = gCoreThread().createAccessor();
+		mPrimaryCoreAccessor = gCoreThread().getAccessor();
 		mPrimarySyncedCoreAccessor = &gCoreThread().getSyncedAccessor();
 
 		SceneManager::startUp((SceneManager*)loadPlugin(desc.sceneManager));

+ 2 - 0
CamelotCore/Source/CmCoreObject.cpp

@@ -1,6 +1,7 @@
 #include "CmCoreObject.h"
 #include "CmCoreThread.h"
 #include "CmCoreObjectManager.h"
+#include "CmCoreThreadAccessor.h"
 #include "CmDebug.h"
 
 namespace CamelotFramework
@@ -158,6 +159,7 @@ namespace CamelotFramework
 		// We could have called the function directly using "this" pointer but then we couldn't have used a shared_ptr for the object,
 		// in which case there is a possibility that the object would be released and deleted while still being in the command queue.
 		CoreThread::instance().queueCommand(boost::bind(&CoreObject::executeGpuCommand, obj, func));
+
 	}
 
 	AsyncOp CoreObject::queueReturnGpuCommand(std::shared_ptr<CoreObject>& obj, boost::function<void(AsyncOp&)> func)

+ 24 - 2
CamelotCore/Source/CmCoreThread.cpp

@@ -3,6 +3,8 @@
 
 namespace CamelotFramework
 {
+	CM_THREADLOCAL CoreThread::AccessorContainer* CoreThread::mAccessor = nullptr;
+
 	CoreThread::CoreThread()
 		: mCoreThreadFunc(nullptr)
 		, mCoreThreadStarted(false)
@@ -26,6 +28,16 @@ namespace CamelotFramework
 		// TODO - What if something gets queued between the queued call to destroy_internal and this!?
 		shutdownCoreThread();
 
+		{
+			CM_LOCK_MUTEX(mAccessorMutex);
+			for(auto& accessor : mAccessors)
+			{
+				cm_delete(accessor);
+			}
+
+			mAccessors.clear();
+		}
+
 		if(mCommandQueue != nullptr)
 		{
 			cm_delete(mCommandQueue);
@@ -130,9 +142,19 @@ namespace CamelotFramework
 		mCoreThreadStarted = false;
 	}
 
-	CoreAccessorPtr CoreThread::createAccessor()
+	CoreAccessorPtr CoreThread::getAccessor()
 	{
-		return cm_shared_ptr<CoreThreadAccessor<CommandQueueNoSync>>(CM_THREAD_CURRENT_ID);
+		if(mAccessor == nullptr)
+		{
+			CoreAccessorPtr newAccessor = cm_shared_ptr<CoreThreadAccessor<CommandQueueNoSync>>(CM_THREAD_CURRENT_ID);
+			mAccessor = cm_new<AccessorContainer>();
+			mAccessor->accessor = newAccessor;
+
+			CM_LOCK_MUTEX(mAccessorMutex);
+			mAccessors.push_back(mAccessor);
+		}
+
+		return mAccessor->accessor;
 	}
 
 	SyncedCoreAccessor& CoreThread::getSyncedAccessor()

+ 0 - 2
CamelotCore/Source/CmMeshManager.cpp

@@ -71,8 +71,6 @@ namespace CamelotFramework
 		indices[1] = 0;
 		indices[2] = 0;
 
-		SyncedCoreAccessor& coreAccessor = gMainSyncedCA();
-
 		mDummyMesh = Mesh::create(mDummyMeshData);
 	}
 }

+ 7 - 1
EditorWindowDock.txt

@@ -2,11 +2,18 @@ TODO:
  - Closing all docked widgets causes an exception
  - Test out minimum dock container size and maybe increase it a bit
 
+Fix up DockManager::setLayout and ensure it opens widgets properly
+Check SVN modifications and re-evaluate my changes
+
 I should consider adding multiple C# EditorWindow types (via an enum)
  - Normal dockable EditorWindow, a tool window (unockable, no tabs), a modal window or maybe others
    - Dockable EditorWindow would internally be EditorWidgetBase as it is now and I would create different types for other windows
    - (Other windows should not need layout)
 
+I should try to get rid of two-step EditorWidget initialization
+ - Both C++ and C# scripts require additional calls to initialize() after construction
+ - SOLUTION: Update GUI so it can accept a "null" parent widget. Then it just needs to reintialize on _chageParentWidget which it does anyway
+
 Polish TOOD:
  - Change cursor icon when window is dragged
  - Prevent docking if available size is less than 20 pixels, otherwise there might be some weirdness
@@ -15,7 +22,6 @@ Polish TOOD:
 Layout saving/loading:
 TODO:
  Register a bunch of duplicate widgets and open and dock them
- C# EditorWindows
 
 ------------------------
 

+ 0 - 8
MBansheeEditor/EditorWindow.cs

@@ -14,18 +14,10 @@ namespace BansheeEditor
         }
 
         protected EditorWindow()
-        {
-            Internal_CreateInstance(this);
-        }
-
-        private void Initialize()
         {
             GUI = new EditorGUI(this);
         }
 
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateInstance(EditorWindow instance);
-
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern EditorWindow Internal_CreateOrGetInstance(string ns, string typeName);
     }

+ 5 - 6
SBansheeEditor/Include/BsScriptEditorWindow.h

@@ -26,10 +26,9 @@ namespace BansheeEditor
 	private:
 		friend class ScriptEditorWidget;
 
-		ScriptEditorWindow(const CM::String& windowName, const CM::String& displayName);
+		ScriptEditorWindow(const CM::String& windowName, const CM::String& displayName, EditorWidgetBase* editorWidget);
 
 		static MonoObject* internal_createOrGetInstance(MonoString* ns, MonoString* typeName);
-		static void internal_createInstance(MonoObject* instance);
 		static void internal_destroyInstance(ScriptEditorWindow* nativeInstance);
 
 		static void initRuntimeData();
@@ -39,20 +38,20 @@ namespace BansheeEditor
 
 		// Global editor window management methods
 		static void registerScriptEditorWindow(ScriptEditorWindow* editorWindow);
-		static void unregisterScriptEditorWindow(ScriptEditorWindow* editorWindow);
+		static void unregisterScriptEditorWindow(const CM::String& windowTypeName);
 
 		static CM::UnorderedMap<CM::String, EditorWindowHandle>::type OpenScriptEditorWindows;
 
-		static EditorWidgetBase* openEditorWidgetCallback(CM::String ns, CM::String type);
+		static EditorWidgetBase* openEditorWidgetCallback(CM::String ns, CM::String type, EditorWidgetContainer& parentContainer);
 	};
 
 	class BS_SCR_BED_EXPORT ScriptEditorWidget : public EditorWidgetBase
 	{
 	public:
-		ScriptEditorWidget(const CM::HString& displayName, ScriptEditorWindow* window);
+		ScriptEditorWidget(const CM::String& windowTypeName, const CM::HString& displayName, EditorWidgetContainer& parentContainer);
 		~ScriptEditorWidget();
 
 	private:
-		ScriptEditorWindow* mWindow;
+		CM::String mWindowTypeName;
 	};
 }

+ 26 - 37
SBansheeEditor/Source/BsScriptEditorWindow.cpp

@@ -15,12 +15,10 @@ namespace BansheeEditor
 {
 	UnorderedMap<String, ScriptEditorWindow::EditorWindowHandle>::type ScriptEditorWindow::OpenScriptEditorWindows;
 
-	ScriptEditorWindow::ScriptEditorWindow(const CM::String& windowName, const CM::String& displayName)
-		:mName(windowName)
+	ScriptEditorWindow::ScriptEditorWindow(const CM::String& windowName, const CM::String& displayName, EditorWidgetBase* editorWidget)
+		:mName(windowName), mEditorWidget(editorWidget)
 	{
-		// This will be cleaned up by EditorWidgetManager since technically this should be done in the "create"
-		// callback but we're doing it here for convenience.
-		mEditorWidget = cm_new<ScriptEditorWidget>(HString(toWString(displayName)), this); 
+
 	}
 
 	ScriptEditorWindow::~ScriptEditorWindow()
@@ -38,7 +36,6 @@ namespace BansheeEditor
 	void ScriptEditorWindow::initRuntimeData()
 	{
 		metaData.scriptClass->addInternalCall("Internal_CreateOrGetInstance", &ScriptEditorWindow::internal_createOrGetInstance);
-		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptEditorWindow::internal_createInstance);
 		metaData.scriptClass->addInternalCall("Internal_DestroyInstance", &ScriptEditorWindow::internal_destroyInstance);
 	}
 
@@ -61,17 +58,6 @@ namespace BansheeEditor
 		return nullptr;
 	}
 
-	void ScriptEditorWindow::internal_createInstance(MonoObject* instance)
-	{
-		String windowFullTypeName = MonoManager::instance().getFullTypeName(instance);
-		String displayName = MonoManager::instance().getTypeName(instance);
-
-		ScriptEditorWindow* nativeInstance = new (cm_alloc<ScriptEditorWindow>()) ScriptEditorWindow(windowFullTypeName, displayName);
-		nativeInstance->createInstance(instance);
-
-		metaData.thisPtrField->setValue(instance, nativeInstance);
-	}
-
 	void ScriptEditorWindow::internal_destroyInstance(ScriptEditorWindow* nativeInstance)
 	{
 #if CM_DEBUG_MODE
@@ -102,16 +88,13 @@ namespace BansheeEditor
 				{
 					const String& className = curClass->getFullName();
 					EditorWidgetManager::instance().registerWidget(className, 
-						std::bind(&ScriptEditorWindow::openEditorWidgetCallback, curClass->getNamespace(), curClass->getTypeName()));
-
-					// DEBUG ONLY
-					EditorWidgetManager::instance().open(className);
+						std::bind(&ScriptEditorWindow::openEditorWidgetCallback, curClass->getNamespace(), curClass->getTypeName(), std::placeholders::_1));
 				}
 			}
 		}
 	}
 
-	EditorWidgetBase* ScriptEditorWindow::openEditorWidgetCallback(CM::String ns, CM::String type)
+	EditorWidgetBase* ScriptEditorWindow::openEditorWidgetCallback(CM::String ns, CM::String type, EditorWidgetContainer& parentContainer)
 	{
 		BS::MonoAssembly* assembly = MonoManager::instance().getAssembly("MBansheeEditor");
 
@@ -123,12 +106,24 @@ namespace BansheeEditor
 		if(editorWindowClass == nullptr)
 			return nullptr;
 
-		MonoObject* editorWindowInstance = editorWindowClass->createInstance();
+		MonoObject* editorWindowInstance = editorWindowClass->createInstance(false);
 		if(editorWindowInstance == nullptr)
 			return nullptr;
 
-		ScriptEditorWindow* scriptEditorWindow = ScriptEditorWindow::toNative(editorWindowInstance);
-		return scriptEditorWindow->getEditorWidget();
+		String windowFullTypeName = MonoManager::instance().getFullTypeName(editorWindowInstance);
+		String displayName = MonoManager::instance().getTypeName(editorWindowInstance);
+
+		ScriptEditorWidget* editorWidget = cm_new<ScriptEditorWidget>(windowFullTypeName, HString(toWString(displayName)), parentContainer);
+		ScriptEditorWindow* nativeInstance = new (cm_alloc<ScriptEditorWindow>()) ScriptEditorWindow(windowFullTypeName, displayName, editorWidget);
+		nativeInstance->createInstance(editorWindowInstance);
+
+		metaData.thisPtrField->setValue(editorWindowInstance, nativeInstance);
+
+		ScriptEditorWindow::registerScriptEditorWindow(nativeInstance);
+
+		mono_runtime_object_init(editorWindowInstance); // Construct it
+
+		return editorWidget;
 	}
 
 	void ScriptEditorWindow::registerScriptEditorWindow(ScriptEditorWindow* editorWindow)
@@ -147,12 +142,9 @@ namespace BansheeEditor
 		}
 	}
 
-	void ScriptEditorWindow::unregisterScriptEditorWindow(ScriptEditorWindow* editorWindow)
+	void ScriptEditorWindow::unregisterScriptEditorWindow(const CM::String& windowTypeName)
 	{
-		if(editorWindow == nullptr)
-			return;
-
-		auto findIter = OpenScriptEditorWindows.find(editorWindow->mName);
+		auto findIter = OpenScriptEditorWindows.find(windowTypeName);
 		if(findIter != OpenScriptEditorWindows.end())
 		{
 			EditorWindowHandle& foundHandle = findIter->second;
@@ -162,17 +154,14 @@ namespace BansheeEditor
 		}
 	}
 
-	ScriptEditorWidget::ScriptEditorWidget(const CM::HString& displayName, ScriptEditorWindow* window)
-		:EditorWidgetBase(displayName, window->mName), mWindow(window)
+	ScriptEditorWidget::ScriptEditorWidget(const String& windowTypeName, const HString& displayName, EditorWidgetContainer& parentContainer)
+		:EditorWidgetBase(displayName, windowTypeName, parentContainer), mWindowTypeName(windowTypeName)
 	{
-		ScriptEditorWindow::registerScriptEditorWindow(mWindow);
-
-		// TODO - This is clumsy. Try to create a window in one step
-		window->metaData.scriptClass->invokeMethod("Initialize", window->mManagedInstance);
+		
 	}
 
 	ScriptEditorWidget::~ScriptEditorWidget()
 	{
-		ScriptEditorWindow::unregisterScriptEditorWindow(mWindow);
+		ScriptEditorWindow::unregisterScriptEditorWindow(mWindowTypeName);
 	}
 }