Jelajahi Sumber

Refactored how builtin resources are processed and loaded

Marko Pintera 10 tahun lalu
induk
melakukan
fbbe8659aa

+ 6 - 10
BansheeCore/Source/BsResources.cpp

@@ -75,15 +75,7 @@ namespace BansheeEngine
 	HResource Resources::loadInternal(const Path& filePath, bool synchronous)
 	{
 		String uuid;
-		bool foundUUID = false;
-		for(auto iter = mResourceManifests.rbegin(); iter != mResourceManifests.rend(); ++iter) 
-		{
-			if((*iter)->filePathToUUID(filePath, uuid))
-			{
-				foundUUID = true;
-				break;
-			}
-		}
+		bool foundUUID = getUUIDFromFilePath(filePath, uuid);
 
 		if(!foundUUID)
 			uuid = UUIDGenerator::instance().generateRandom();
@@ -367,9 +359,13 @@ namespace BansheeEngine
 
 	bool Resources::getUUIDFromFilePath(const Path& path, String& uuid) const
 	{
+		Path manifestPath = path;
+		if (!manifestPath.isAbsolute())
+			manifestPath.makeAbsolute(FileSystem::getWorkingDirectoryPath());
+
 		for(auto iter = mResourceManifests.rbegin(); iter != mResourceManifests.rend(); ++iter) 
 		{
-			if((*iter)->filePathToUUID(path, uuid))
+			if ((*iter)->filePathToUUID(manifestPath, uuid))
 				return true;
 		}
 

+ 23 - 10
BansheeEditor/Include/BsBuiltinEditorResources.h

@@ -11,6 +11,7 @@ namespace BansheeEngine
 	{
 	public:
 		BuiltinEditorResources();
+		~BuiltinEditorResources();
 
 		const HGUISkin& getSkin() const { return mSkin; }
 
@@ -79,8 +80,10 @@ namespace BansheeEngine
 		static const String ObjectFieldDropBtnStyleName;
 		static const String ObjectFieldClearBtnStyleName;
 
-		static const Path DefaultSkinFolder;
-		static const Path DefaultShaderFolder;
+		static const Path BuiltinDataFolder;
+		static const Path EditorSkinFolder;
+		static const Path EditorShaderFolder;
+		static const Path EditorShaderIncludeFolder;
 
 	private:
 		/**
@@ -92,16 +95,14 @@ namespace BansheeEngine
 		void preprocess();
 
 		/**
-		 * @brief	Loads a GUI skin texture with the specified filename.
+		 * @brief	Generates the default editor skin and all GUI element styles.
 		 */
-		static HSpriteTexture getGUITexture(const WString& name);
+		HGUISkin generateGUISkin();
 
 		/**
-		 * @brief	Imports a GUI skin texture with the specified filename.
-		 *			Saves the imported texture in engine-ready format in the corresponding
-		 *			output folder.
+		 * @brief	Loads a GUI skin texture with the specified filename.
 		 */
-		static void importGUITexture(const WString& name);
+		static HSpriteTexture getGUITexture(const WString& name);
 
 		/**
 		 * @brief	Loads a shader with the specified filename
@@ -123,12 +124,24 @@ namespace BansheeEngine
 
 		HGUISkin mSkin;
 
-		static const Path DefaultSkinFolderRaw;
-		static const Path DefaultShaderFolderRaw;
+		ResourceManifestPtr mResourceManifest;
+
+		static const Path ShaderFolder;
+		static const Path SkinFolder;
+		static const Path ShaderIncludeFolder;
+
+		static const Path BuiltinRawDataFolder;
+		static const Path EditorRawSkinFolder;
+		static const Path EditorRawShaderIncludeFolder;
+		static const Path EditorRawShaderFolder;
+
+		static const Path ResourceManifestPath;
 
 		static const WString DefaultFontFilename;
 		static const UINT32 DefaultFontSize;
 
+		static const WString GUISkinFile;
+
 		static const WString WindowBackgroundTexture;
 
 		static const WString WindowFrameNormal;

+ 162 - 229
BansheeEditor/Source/BsBuiltinEditorResources.cpp

@@ -1,4 +1,5 @@
 #include "BsBuiltinEditorResources.h"
+#include "BsBuiltinResources.h"
 #include "BsGUIElementStyle.h"
 
 #include "BsGUILabel.h"
@@ -39,6 +40,7 @@
 #include "BsResources.h"
 #include "BsRTTIType.h"
 #include "BsFileSystem.h"
+#include "BsResourceManifest.h"
 
 namespace BansheeEngine
 {
@@ -47,15 +49,27 @@ namespace BansheeEngine
 	const String BuiltinEditorResources::ObjectFieldDropBtnStyleName = "DropButton";
 	const String BuiltinEditorResources::ObjectFieldClearBtnStyleName = "ObjectClearButton";
 
-	const Path BuiltinEditorResources::DefaultSkinFolderRaw = L"..\\..\\..\\..\\Data\\Raw\\Editor\\Skin\\";
-	const Path BuiltinEditorResources::DefaultShaderFolderRaw = L"..\\..\\..\\..\\Data\\Raw\\Editor\\Shaders\\";
-
-	const Path BuiltinEditorResources::DefaultSkinFolder = L"..\\..\\..\\..\\Data\\Editor\\Skin\\";
-	const Path BuiltinEditorResources::DefaultShaderFolder = L"..\\..\\..\\..\\Data\\Editor\\Shaders\\";
-
 	const WString BuiltinEditorResources::DefaultFontFilename = L"arial.ttf";
 	const UINT32 BuiltinEditorResources::DefaultFontSize = 10;
 
+	const WString BuiltinEditorResources::GUISkinFile = L"GUISkin";
+
+	const Path BuiltinEditorResources::ShaderFolder = L"Shaders\\";
+	const Path BuiltinEditorResources::SkinFolder = L"Skin\\";
+	const Path BuiltinEditorResources::ShaderIncludeFolder = L"Includes\\";
+
+	const Path BuiltinEditorResources::BuiltinRawDataFolder = L"..\\..\\..\\..\\Data\\Raw\\Editor\\";
+	const Path BuiltinEditorResources::EditorRawSkinFolder = BuiltinRawDataFolder + SkinFolder;
+	const Path BuiltinEditorResources::EditorRawShaderFolder = BuiltinRawDataFolder + ShaderFolder;
+	const Path BuiltinEditorResources::EditorRawShaderIncludeFolder = BuiltinRawDataFolder + ShaderIncludeFolder;
+
+	const Path BuiltinEditorResources::BuiltinDataFolder = L"..\\..\\..\\..\\Data\\Editor\\";
+	const Path BuiltinEditorResources::EditorSkinFolder = BuiltinDataFolder + SkinFolder;
+	const Path BuiltinEditorResources::EditorShaderFolder = BuiltinDataFolder + ShaderFolder;
+	const Path BuiltinEditorResources::EditorShaderIncludeFolder = BuiltinDataFolder + ShaderIncludeFolder;
+
+	const Path BuiltinEditorResources::ResourceManifestPath = BuiltinDataFolder + "ResourceManifest.asset";
+
 	const WString BuiltinEditorResources::WindowBackgroundTexture = L"WindowBgTile.psd";
 
 	const WString BuiltinEditorResources::ButtonNormalTex = L"ButtonNormal.psd";
@@ -204,7 +218,29 @@ namespace BansheeEngine
 
 	BuiltinEditorResources::BuiltinEditorResources()
 	{
-		preprocess();
+		Path absoluteDataPath = FileSystem::getWorkingDirectoryPath();
+		absoluteDataPath.append(BuiltinDataFolder);
+
+		if (FileSystem::exists(ResourceManifestPath))
+			mResourceManifest = ResourceManifest::load(ResourceManifestPath, absoluteDataPath);
+
+		if (mResourceManifest == nullptr)
+			mResourceManifest = ResourceManifest::create("BuiltinResources");
+
+		gResources().registerResourceManifest(mResourceManifest);
+
+#if BS_DEBUG_MODE
+		if (BuiltinResourcesHelper::checkForModifications(BuiltinRawDataFolder, BuiltinDataFolder + L"Timestamp.asset"))
+		{
+			preprocess();
+			BuiltinResourcesHelper::writeTimestamp(BuiltinDataFolder + L"Timestamp.asset");
+
+			Path absoluteDataPath = FileSystem::getWorkingDirectoryPath();
+			absoluteDataPath.append(BuiltinDataFolder);
+
+			ResourceManifest::save(mResourceManifest, ResourceManifestPath, absoluteDataPath);
+		}
+#endif
 
 		mShaderDockOverlay = getShader(ShaderDockOverlayFile);
 		mShaderSceneGrid = getShader(ShaderSceneGridFile);
@@ -223,10 +259,45 @@ namespace BansheeEngine
 		mShaderHandleWire = getShader(ShaderWireHandleFile);
 		mShaderSelection = getShader(ShaderSelectionFile);
 
-		mSkin = GUISkin::create();
+		mSkin = gResources().load<GUISkin>(BuiltinDataFolder + (GUISkinFile + L".asset"));
+	}
+
+	BuiltinEditorResources::~BuiltinEditorResources()
+	{ }
+
+	void BuiltinEditorResources::preprocess()
+	{
+		FileSystem::remove(EditorShaderIncludeFolder);
+		FileSystem::remove(EditorShaderFolder);
+		FileSystem::remove(EditorSkinFolder);
+
+		BuiltinResourcesHelper::importAssets(EditorRawShaderIncludeFolder, EditorShaderIncludeFolder, mResourceManifest); // Hidden dependency: Includes must be imported before shaders
+		BuiltinResourcesHelper::importAssets(EditorRawShaderFolder, EditorShaderFolder, mResourceManifest);
+		BuiltinResourcesHelper::importAssets(EditorRawSkinFolder, EditorSkinFolder, mResourceManifest);
+
+		// Import font
+		BuiltinResourcesHelper::importFont(BuiltinRawDataFolder + DefaultFontFilename, BuiltinDataFolder, DefaultFontSize, false, mResourceManifest);
+
+		// Generate & save GUI sprite textures
+		BuiltinResourcesHelper::generateSpriteTextures(EditorSkinFolder, mResourceManifest);
+
+		// Generate & save GUI skin
+		{
+			HGUISkin skin = generateGUISkin();
+			Path outputPath = FileSystem::getWorkingDirectoryPath() + BuiltinDataFolder + (GUISkinFile + L".asset");
+			Resources::instance().save(skin, outputPath, true);
+			mResourceManifest->registerResource(skin.getUUID(), outputPath);
+		}
+
+		Resources::instance().unloadAllUnused();
+	}
+
+	HGUISkin BuiltinEditorResources::generateGUISkin()
+	{
+		HGUISkin skin = GUISkin::create();
 
 		Path fontPath = FileSystem::getWorkingDirectoryPath();
-		fontPath.append(DefaultSkinFolder);
+		fontPath.append(BuiltinDataFolder);
 		fontPath.append(DefaultFontFilename + L".asset");
 
 		HFont font = Resources::instance().load<Font>(fontPath);
@@ -240,7 +311,7 @@ namespace BansheeEngine
 		labelStyle.height = 11;
 		labelStyle.minWidth = 10;
 
-		mSkin->setStyle(GUILabel::getGUITypeName(), labelStyle);
+		skin->setStyle(GUILabel::getGUITypeName(), labelStyle);
 
 		// Window frame
 		GUIElementStyle windowFrameStyle;
@@ -251,7 +322,7 @@ namespace BansheeEngine
 		windowFrameStyle.border.top = 1;
 		windowFrameStyle.border.bottom = 1;
 
-		mSkin->setStyle("WindowFrame", windowFrameStyle);
+		skin->setStyle("WindowFrame", windowFrameStyle);
 
 		// Button
 		GUIElementStyle buttonStyle;
@@ -275,7 +346,7 @@ namespace BansheeEngine
 		buttonStyle.textHorzAlign = THA_Center;
 		buttonStyle.textVertAlign = TVA_Center;
 
-		mSkin->setStyle(GUIButton::getGUITypeName(), buttonStyle);
+		skin->setStyle(GUIButton::getGUITypeName(), buttonStyle);
 
 		// Toggle
 		GUIElementStyle toggleStyle;
@@ -290,7 +361,7 @@ namespace BansheeEngine
 		toggleStyle.height = 15;
 		toggleStyle.width = 15;
 
-		mSkin->setStyle(GUIToggle::getGUITypeName(), toggleStyle);
+		skin->setStyle(GUIToggle::getGUITypeName(), toggleStyle);
 
 		// Color
 		GUIElementStyle colorStyle;
@@ -302,13 +373,13 @@ namespace BansheeEngine
 		colorStyle.height = 10;
 		colorStyle.minWidth = 10;
 
-		mSkin->setStyle(GUIColor::getGUITypeName(), colorStyle);
+		skin->setStyle(GUIColor::getGUITypeName(), colorStyle);
 
 		// Window background texture
 		GUIElementStyle windowBgStyle;
 		windowBgStyle.normal.texture = getGUITexture(WindowBackgroundTexture);
 
-		mSkin->setStyle("WindowBackground", windowBgStyle);
+		skin->setStyle("WindowBackground", windowBgStyle);
 
 		// Window title bar background
 		GUIElementStyle titleBarBgStyle;
@@ -316,7 +387,7 @@ namespace BansheeEngine
 		titleBarBgStyle.fixedHeight = true;
 		titleBarBgStyle.height = 13;
 
-		mSkin->setStyle("TitleBarBackground", titleBarBgStyle);
+		skin->setStyle("TitleBarBackground", titleBarBgStyle);
 
 		// Tabbed title bar tab button
 		GUIElementStyle tabbedBarButton;
@@ -335,7 +406,7 @@ namespace BansheeEngine
 		tabbedBarButton.textHorzAlign = THA_Center;
 		tabbedBarButton.textVertAlign = TVA_Center;
 
-		mSkin->setStyle("TabbedBarBtn", tabbedBarButton);
+		skin->setStyle("TabbedBarBtn", tabbedBarButton);
 
 		// Tabbed title bar drag/drop button
 		GUIElementStyle tabbedBarDropButton;
@@ -344,7 +415,7 @@ namespace BansheeEngine
 		tabbedBarDropButton.height = 13;
 		tabbedBarDropButton.width = 6;
 
-		mSkin->setStyle("TabbedBarDropArea", tabbedBarDropButton);
+		skin->setStyle("TabbedBarDropArea", tabbedBarDropButton);
 
 		// Window minimize button
 		GUIElementStyle winMinButtonStyle;
@@ -356,7 +427,7 @@ namespace BansheeEngine
 		winMinButtonStyle.height = 7;
 		winMinButtonStyle.width = 8;
 
-		mSkin->setStyle("WinMinimizeBtn", winMinButtonStyle);
+		skin->setStyle("WinMinimizeBtn", winMinButtonStyle);
 
 		// Window maximize button
 		GUIElementStyle winMaxButtonStyle;
@@ -368,7 +439,7 @@ namespace BansheeEngine
 		winMaxButtonStyle.height = 8;
 		winMaxButtonStyle.width = 8;
 
-		mSkin->setStyle("WinMaximizeBtn", winMaxButtonStyle);
+		skin->setStyle("WinMaximizeBtn", winMaxButtonStyle);
 
 		// Window close button
 		GUIElementStyle winCloseButtonStyle;
@@ -380,7 +451,7 @@ namespace BansheeEngine
 		winCloseButtonStyle.height = 7;
 		winCloseButtonStyle.width = 8;
 
-		mSkin->setStyle("WinCloseBtn", winCloseButtonStyle);
+		skin->setStyle("WinCloseBtn", winCloseButtonStyle);
 
 		// Input box
 		GUIElementStyle inputBoxStyle;
@@ -404,7 +475,7 @@ namespace BansheeEngine
 		inputBoxStyle.textHorzAlign = THA_Left;
 		inputBoxStyle.textVertAlign = TVA_Top;
 
-		mSkin->setStyle(GUIInputBox::getGUITypeName(), inputBoxStyle);
+		skin->setStyle(GUIInputBox::getGUITypeName(), inputBoxStyle);
 
 		/************************************************************************/
 		/* 								SCROLL BAR                      		*/
@@ -420,7 +491,7 @@ namespace BansheeEngine
 		scrollUpBtnStyle.height = 4;
 		scrollUpBtnStyle.width = 8;
 
-		mSkin->setStyle("ScrollUpBtn", scrollUpBtnStyle);
+		skin->setStyle("ScrollUpBtn", scrollUpBtnStyle);
 
 		// Down button
 		GUIElementStyle scrollDownBtnStyle;
@@ -432,7 +503,7 @@ namespace BansheeEngine
 		scrollDownBtnStyle.height = 4;
 		scrollDownBtnStyle.width = 8;
 
-		mSkin->setStyle("ScrollDownBtn", scrollDownBtnStyle);
+		skin->setStyle("ScrollDownBtn", scrollDownBtnStyle);
 
 		// Left button
 		GUIElementStyle scrollLeftBtnStyle;
@@ -444,7 +515,7 @@ namespace BansheeEngine
 		scrollLeftBtnStyle.height = 8;
 		scrollLeftBtnStyle.width = 4;
 
-		mSkin->setStyle("ScrollLeftBtn", scrollLeftBtnStyle);
+		skin->setStyle("ScrollLeftBtn", scrollLeftBtnStyle);
 
 		// Right button
 		GUIElementStyle scrollRightBtnStyle;
@@ -456,7 +527,7 @@ namespace BansheeEngine
 		scrollRightBtnStyle.height = 8;
 		scrollRightBtnStyle.width = 4;
 
-		mSkin->setStyle("ScrollRightBtn", scrollRightBtnStyle);
+		skin->setStyle("ScrollRightBtn", scrollRightBtnStyle);
 
 		// Horizontal handle
 		GUIElementStyle scrollBarHorzBtnStyle;
@@ -468,7 +539,7 @@ namespace BansheeEngine
 		scrollBarHorzBtnStyle.height = 6;
 		scrollBarHorzBtnStyle.width = 4;
 
-		mSkin->setStyle("ScrollBarHorzBtn", scrollBarHorzBtnStyle);
+		skin->setStyle("ScrollBarHorzBtn", scrollBarHorzBtnStyle);
 
 		// Vertical handle
 		GUIElementStyle scrollBarVertBtnStyle;
@@ -480,7 +551,7 @@ namespace BansheeEngine
 		scrollBarVertBtnStyle.height = 4;
 		scrollBarVertBtnStyle.width = 6;
 
-		mSkin->setStyle("ScrollBarVertBtn", scrollBarVertBtnStyle);
+		skin->setStyle("ScrollBarVertBtn", scrollBarVertBtnStyle);
 
 		HSpriteTexture scrollBarBgPtr = getGUITexture(ScrollBarBgTex);
 
@@ -494,7 +565,7 @@ namespace BansheeEngine
 		vertScrollBarStyle.minHeight = 16;
 		vertScrollBarStyle.width = 8;
 
-		mSkin->setStyle("ScrollBarVert", vertScrollBarStyle);
+		skin->setStyle("ScrollBarVert", vertScrollBarStyle);
 
 		// Horizontal scroll bar
 		GUIElementStyle horzScrollBarStyle;
@@ -506,7 +577,7 @@ namespace BansheeEngine
 		horzScrollBarStyle.minWidth = 16;
 		horzScrollBarStyle.height = 8;
 
-		mSkin->setStyle("ScrollBarHorz", horzScrollBarStyle);
+		skin->setStyle("ScrollBarHorz", horzScrollBarStyle);
 
 		/************************************************************************/
 		/* 								DROP DOWN BOX                      		*/
@@ -537,7 +608,7 @@ namespace BansheeEngine
 		dropDownListStyle.textHorzAlign = THA_Left;
 		dropDownListStyle.textVertAlign = TVA_Top;
 
-		mSkin->setStyle("ListBox", dropDownListStyle);
+		skin->setStyle("ListBox", dropDownListStyle);
 
 		// DropDown scroll up button arrow
 		HSpriteTexture dropDownBtnScrollUpArrow = getGUITexture(DropDownBoxBtnUpArrowTex);
@@ -555,9 +626,9 @@ namespace BansheeEngine
 		dropDownScrollUpBtnArrowStyle.border.top = 1;
 		dropDownScrollUpBtnArrowStyle.border.bottom = 1;
 
-		mSkin->setStyle("ListBoxScrollUpBtnArrow", dropDownScrollUpBtnArrowStyle);
-		mSkin->setStyle("MenuBarScrollUpBtnArrow", dropDownScrollUpBtnArrowStyle);
-		mSkin->setStyle("ContextMenuScrollUpBtnArrow", dropDownScrollUpBtnArrowStyle);
+		skin->setStyle("ListBoxScrollUpBtnArrow", dropDownScrollUpBtnArrowStyle);
+		skin->setStyle("MenuBarScrollUpBtnArrow", dropDownScrollUpBtnArrowStyle);
+		skin->setStyle("ContextMenuScrollUpBtnArrow", dropDownScrollUpBtnArrowStyle);
 
 		// DropDown scroll up button
 		GUIElementStyle dropDownScrollUpBtnStyle;
@@ -573,9 +644,9 @@ namespace BansheeEngine
 		dropDownScrollUpBtnStyle.border.top = 1;
 		dropDownScrollUpBtnStyle.border.bottom = 1;
 
-		mSkin->setStyle("ListBoxScrollUpBtn", dropDownScrollUpBtnStyle);
-		mSkin->setStyle("MenuBarScrollUpBtn", dropDownScrollUpBtnStyle);
-		mSkin->setStyle("ContextMenuScrollUpBtn", dropDownScrollUpBtnStyle);
+		skin->setStyle("ListBoxScrollUpBtn", dropDownScrollUpBtnStyle);
+		skin->setStyle("MenuBarScrollUpBtn", dropDownScrollUpBtnStyle);
+		skin->setStyle("ContextMenuScrollUpBtn", dropDownScrollUpBtnStyle);
 
 		// DropDown scroll down button arrow
 		GUIElementStyle dropDownScrollDownBtnArrowStyle;
@@ -591,9 +662,9 @@ namespace BansheeEngine
 		dropDownScrollDownBtnArrowStyle.border.top = 1;
 		dropDownScrollDownBtnArrowStyle.border.bottom = 1;
 
-		mSkin->setStyle("ListBoxScrollDownBtnArrow", dropDownScrollDownBtnArrowStyle);
-		mSkin->setStyle("MenuBarScrollDownBtnArrow", dropDownScrollDownBtnArrowStyle);
-		mSkin->setStyle("ContextMenuScrollDownBtnArrow", dropDownScrollDownBtnArrowStyle);
+		skin->setStyle("ListBoxScrollDownBtnArrow", dropDownScrollDownBtnArrowStyle);
+		skin->setStyle("MenuBarScrollDownBtnArrow", dropDownScrollDownBtnArrowStyle);
+		skin->setStyle("ContextMenuScrollDownBtnArrow", dropDownScrollDownBtnArrowStyle);
 
 		// DropDown scroll down button
 		GUIElementStyle dropDownScrollDownBtnStyle;
@@ -609,9 +680,9 @@ namespace BansheeEngine
 		dropDownScrollDownBtnStyle.border.top = 1;
 		dropDownScrollDownBtnStyle.border.bottom = 1;
 
-		mSkin->setStyle("ListBoxScrollDownBtn", dropDownScrollDownBtnStyle);
-		mSkin->setStyle("MenuBarScrollDownBtn", dropDownScrollDownBtnStyle);
-		mSkin->setStyle("ContextMenuScrollDownBtn", dropDownScrollDownBtnStyle);
+		skin->setStyle("ListBoxScrollDownBtn", dropDownScrollDownBtnStyle);
+		skin->setStyle("MenuBarScrollDownBtn", dropDownScrollDownBtnStyle);
+		skin->setStyle("ContextMenuScrollDownBtn", dropDownScrollDownBtnStyle);
 
 		// DropDown entry button
 		GUIElementStyle dropDownEntryBtnStyle;
@@ -634,7 +705,7 @@ namespace BansheeEngine
 		dropDownEntryBtnStyle.textHorzAlign = THA_Left;
 		dropDownEntryBtnStyle.textVertAlign = TVA_Top;
 
-		mSkin->setStyle(GUIDropDownContent::ENTRY_STYLE_TYPE, dropDownEntryBtnStyle);
+		skin->setStyle(GUIDropDownContent::ENTRY_STYLE_TYPE, dropDownEntryBtnStyle);
 
 		// DropDown entry button with expand
 		GUIElementStyle dropDownEntryExpBtnStyle;
@@ -657,7 +728,7 @@ namespace BansheeEngine
 		dropDownEntryExpBtnStyle.textHorzAlign = THA_Left;
 		dropDownEntryExpBtnStyle.textVertAlign = TVA_Top;
 
-		mSkin->setStyle(GUIDropDownContent::ENTRY_EXP_STYLE_TYPE, dropDownEntryExpBtnStyle);
+		skin->setStyle(GUIDropDownContent::ENTRY_EXP_STYLE_TYPE, dropDownEntryExpBtnStyle);
 
 		// Drop down separator
 		GUIElementStyle dropDownSeparatorStyle;
@@ -671,7 +742,7 @@ namespace BansheeEngine
 		dropDownSeparatorStyle.border.top = 1;
 		dropDownSeparatorStyle.border.bottom = 1;
 
-		mSkin->setStyle(GUIDropDownContent::SEPARATOR_STYLE_TYPE, dropDownSeparatorStyle);
+		skin->setStyle(GUIDropDownContent::SEPARATOR_STYLE_TYPE, dropDownSeparatorStyle);
 
 		// Drop down content
 		GUIElementStyle dropDownContentStyle;
@@ -681,9 +752,9 @@ namespace BansheeEngine
 		dropDownContentStyle.subStyles[GUIDropDownContent::ENTRY_EXP_STYLE_TYPE] = GUIDropDownContent::ENTRY_EXP_STYLE_TYPE;
 		dropDownContentStyle.subStyles[GUIDropDownContent::SEPARATOR_STYLE_TYPE] = GUIDropDownContent::SEPARATOR_STYLE_TYPE;
 
-		mSkin->setStyle("ListBoxContent", dropDownContentStyle);
-		mSkin->setStyle("MenuBarContent", dropDownContentStyle);
-		mSkin->setStyle("ContextMenuContent", dropDownContentStyle);
+		skin->setStyle("ListBoxContent", dropDownContentStyle);
+		skin->setStyle("MenuBarContent", dropDownContentStyle);
+		skin->setStyle("ContextMenuContent", dropDownContentStyle);
 
 		// DropDown box frame
 		GUIElementStyle dropDownBoxStyle;
@@ -701,9 +772,9 @@ namespace BansheeEngine
 		dropDownBoxStyle.margins.top = 1;
 		dropDownBoxStyle.margins.bottom = 1;
 
-		mSkin->setStyle("ListBoxFrame", dropDownBoxStyle);
-		mSkin->setStyle("MenuBarFrame", dropDownBoxStyle);
-		mSkin->setStyle("ContextMenuFrame", dropDownBoxStyle);
+		skin->setStyle("ListBoxFrame", dropDownBoxStyle);
+		skin->setStyle("MenuBarFrame", dropDownBoxStyle);
+		skin->setStyle("ContextMenuFrame", dropDownBoxStyle);
 
 		/************************************************************************/
 		/* 								MENU BAR	                     		*/
@@ -717,7 +788,7 @@ namespace BansheeEngine
 		menuBarBgStyle.height = 4;
 		menuBarBgStyle.width = 4;
 
-		mSkin->setStyle("MenuBarBg", menuBarBgStyle);
+		skin->setStyle("MenuBarBg", menuBarBgStyle);
 
 		// MenuBar Banshee logo
 		GUIElementStyle menuBarBansheeLogoStyle;
@@ -727,7 +798,7 @@ namespace BansheeEngine
 		menuBarBansheeLogoStyle.height = 7;
 		menuBarBansheeLogoStyle.width = 51;
 
-		mSkin->setStyle("MenuBarBansheeLogo", menuBarBansheeLogoStyle);
+		skin->setStyle("MenuBarBansheeLogo", menuBarBansheeLogoStyle);
 
 		// MenuBar button
 		GUIElementStyle menuBarBtnStyle;
@@ -750,7 +821,7 @@ namespace BansheeEngine
 		menuBarBtnStyle.textHorzAlign = THA_Left;
 		menuBarBtnStyle.textVertAlign = TVA_Top;
 
-		mSkin->setStyle("MenuBarBtn", menuBarBtnStyle);
+		skin->setStyle("MenuBarBtn", menuBarBtnStyle);
 
 		/************************************************************************/
 		/* 								DOCK SLIDER	                     		*/
@@ -763,7 +834,7 @@ namespace BansheeEngine
 		dockSliderBtnStyle.height = 2;
 		dockSliderBtnStyle.width = 2;
 
-		mSkin->setStyle("DockSliderBtn", dockSliderBtnStyle);
+		skin->setStyle("DockSliderBtn", dockSliderBtnStyle);
 
 		/************************************************************************/
 		/* 								TREE VIEW	                     		*/
@@ -786,7 +857,7 @@ namespace BansheeEngine
 		treeViewExpandButtonStyle.height = 16;
 		treeViewExpandButtonStyle.width = 16;
 
-		mSkin->setStyle("TreeViewFoldoutBtn", treeViewExpandButtonStyle);
+		skin->setStyle("TreeViewFoldoutBtn", treeViewExpandButtonStyle);
 
 		// Entry
 		GUIElementStyle treeViewEntryStyle;
@@ -797,7 +868,7 @@ namespace BansheeEngine
 		treeViewEntryStyle.height = 16;
 		treeViewEntryStyle.minWidth = 10;
 
-		mSkin->setStyle("TreeViewElementBtn", treeViewEntryStyle);
+		skin->setStyle("TreeViewElementBtn", treeViewEntryStyle);
 
 		// Selection background
 		GUIElementStyle treeViewSelBackgroundStyle;
@@ -807,7 +878,7 @@ namespace BansheeEngine
 		treeViewSelBackgroundStyle.height = 2;
 		treeViewSelBackgroundStyle.width = 2;
 
-		mSkin->setStyle("TreeViewSelectionBackground", treeViewSelBackgroundStyle);
+		skin->setStyle("TreeViewSelectionBackground", treeViewSelBackgroundStyle);
 
 		// Edit box
 		GUIElementStyle treeViewEditBox;
@@ -831,7 +902,7 @@ namespace BansheeEngine
 		treeViewEditBox.textHorzAlign = THA_Left;
 		treeViewEditBox.textVertAlign = TVA_Top;
 
-		mSkin->setStyle(GUITreeViewEditBox::getGUITypeName(), treeViewEditBox);
+		skin->setStyle(GUITreeViewEditBox::getGUITypeName(), treeViewEditBox);
 
 		// Element highlight
 		GUIElementStyle treeViewElementHighlight;
@@ -841,7 +912,7 @@ namespace BansheeEngine
 		treeViewElementHighlight.border.top = 1;
 		treeViewElementHighlight.border.bottom = 1;
 
-		mSkin->setStyle("TreeViewElementHighlight", treeViewElementHighlight);
+		skin->setStyle("TreeViewElementHighlight", treeViewElementHighlight);
 
 		// Element separator highlight
 		GUIElementStyle treeViewElementSepHighlight;
@@ -851,8 +922,8 @@ namespace BansheeEngine
 		treeViewElementSepHighlight.border.top = 1;
 		treeViewElementSepHighlight.border.bottom = 1;
 
-		mSkin->setStyle("TreeViewElementSepHighlight", treeViewElementSepHighlight);
-	
+		skin->setStyle("TreeViewElementSepHighlight", treeViewElementSepHighlight);
+
 		/************************************************************************/
 		/* 							OBJECT DROP FIELD                      		*/
 		/************************************************************************/
@@ -867,7 +938,7 @@ namespace BansheeEngine
 		objectDropStyle.textHorzAlign = THA_Center;
 		objectDropStyle.textVertAlign = TVA_Center;
 
-		mSkin->setStyle(ObjectFieldDropBtnStyleName, objectDropStyle);
+		skin->setStyle(ObjectFieldDropBtnStyleName, objectDropStyle);
 
 		GUIElementStyle objectClearBtnStyle;
 		objectClearBtnStyle.normal.texture = getGUITexture(ObjectClearBtnNormalTex);
@@ -878,7 +949,7 @@ namespace BansheeEngine
 		objectClearBtnStyle.height = 15;
 		objectClearBtnStyle.width = 13;
 
-		mSkin->setStyle(ObjectFieldClearBtnStyleName, objectClearBtnStyle);
+		skin->setStyle(ObjectFieldClearBtnStyleName, objectClearBtnStyle);
 
 		GUIElementStyle editorObjectFieldStyle;
 		editorObjectFieldStyle.fixedHeight = true;
@@ -888,7 +959,7 @@ namespace BansheeEngine
 		editorObjectFieldStyle.subStyles[ObjectFieldDropBtnStyleName] = ObjectFieldDropBtnStyleName;
 		editorObjectFieldStyle.subStyles[ObjectFieldClearBtnStyleName] = ObjectFieldClearBtnStyleName;
 
-		mSkin->setStyle(ObjectFieldStyleName, editorObjectFieldStyle);
+		skin->setStyle(ObjectFieldStyleName, editorObjectFieldStyle);
 
 		/************************************************************************/
 		/* 								EDITOR FIELDS                      		*/
@@ -903,7 +974,7 @@ namespace BansheeEngine
 		editorFieldLabelStyle.minWidth = 10;
 		editorFieldLabelStyle.textHorzAlign = THA_Left;
 
-		mSkin->setStyle(GUITextField::getLabelStyleType(), editorFieldLabelStyle);
+		skin->setStyle(GUITextField::getLabelStyleType(), editorFieldLabelStyle);
 
 		GUIElementStyle editorIntFieldStyle;
 		editorIntFieldStyle.fixedHeight = true;
@@ -912,7 +983,7 @@ namespace BansheeEngine
 		editorIntFieldStyle.subStyles[GUIIntField::getLabelStyleType()] = GUITextField::getLabelStyleType();
 		editorIntFieldStyle.subStyles[GUIIntField::getInputStyleType()] = GUIInputBox::getGUITypeName();
 
-		mSkin->setStyle(GUIIntField::getGUITypeName(), editorIntFieldStyle);
+		skin->setStyle(GUIIntField::getGUITypeName(), editorIntFieldStyle);
 
 		GUIElementStyle editorFloatFieldStyle;
 		editorFloatFieldStyle.fixedHeight = true;
@@ -921,7 +992,7 @@ namespace BansheeEngine
 		editorFloatFieldStyle.subStyles[GUIFloatField::getLabelStyleType()] = GUITextField::getLabelStyleType();
 		editorFloatFieldStyle.subStyles[GUIFloatField::getInputStyleType()] = GUIInputBox::getGUITypeName();
 
-		mSkin->setStyle(GUIFloatField::getGUITypeName(), editorFloatFieldStyle);
+		skin->setStyle(GUIFloatField::getGUITypeName(), editorFloatFieldStyle);
 
 		GUIElementStyle editorTextFieldStyle;
 		editorTextFieldStyle.fixedHeight = true;
@@ -930,7 +1001,7 @@ namespace BansheeEngine
 		editorTextFieldStyle.subStyles[GUITextField::getLabelStyleType()] = GUITextField::getLabelStyleType();
 		editorTextFieldStyle.subStyles[GUITextField::getInputStyleType()] = GUIInputBox::getGUITypeName();
 
-		mSkin->setStyle(GUITextField::getGUITypeName(), editorTextFieldStyle);
+		skin->setStyle(GUITextField::getGUITypeName(), editorTextFieldStyle);
 
 		GUIElementStyle editorColorFieldStyle;
 		editorColorFieldStyle.fixedHeight = true;
@@ -939,7 +1010,7 @@ namespace BansheeEngine
 		editorColorFieldStyle.subStyles[GUIColorField::getLabelStyleType()] = GUITextField::getLabelStyleType();
 		editorColorFieldStyle.subStyles[GUIColorField::getColorInputStyleType()] = GUIColor::getGUITypeName();
 
-		mSkin->setStyle(GUIColorField::getGUITypeName(), editorColorFieldStyle);
+		skin->setStyle(GUIColorField::getGUITypeName(), editorColorFieldStyle);
 
 		GUIElementStyle editorToggleFieldStyle;
 		editorToggleFieldStyle.fixedHeight = true;
@@ -948,7 +1019,7 @@ namespace BansheeEngine
 		editorToggleFieldStyle.subStyles[GUIToggleField::getLabelStyleType()] = GUITextField::getLabelStyleType();
 		editorToggleFieldStyle.subStyles[GUIToggleField::getToggleStyleType()] = GUIToggle::getGUITypeName();
 
-		mSkin->setStyle(GUIToggleField::getGUITypeName(), editorToggleFieldStyle);
+		skin->setStyle(GUIToggleField::getGUITypeName(), editorToggleFieldStyle);
 
 		GUIElementStyle editorVector2FieldStyle;
 		editorVector2FieldStyle.fixedHeight = true;
@@ -957,7 +1028,7 @@ namespace BansheeEngine
 		editorVector2FieldStyle.subStyles[GUIVector2Field::getLabelStyleType()] = GUITextField::getLabelStyleType();
 		editorVector2FieldStyle.subStyles[GUIVector2Field::getFloatFieldStyleType()] = GUIFloatField::getGUITypeName();
 
-		mSkin->setStyle(GUIVector2Field::getGUITypeName(), editorVector2FieldStyle);
+		skin->setStyle(GUIVector2Field::getGUITypeName(), editorVector2FieldStyle);
 
 		GUIElementStyle editorVector3FieldStyle;
 		editorVector3FieldStyle.fixedHeight = true;
@@ -966,7 +1037,7 @@ namespace BansheeEngine
 		editorVector3FieldStyle.subStyles[GUIVector3Field::getLabelStyleType()] = GUITextField::getLabelStyleType();
 		editorVector3FieldStyle.subStyles[GUIVector3Field::getFloatFieldStyleType()] = GUIFloatField::getGUITypeName();
 
-		mSkin->setStyle(GUIVector3Field::getGUITypeName(), editorVector3FieldStyle);
+		skin->setStyle(GUIVector3Field::getGUITypeName(), editorVector3FieldStyle);
 
 		GUIElementStyle editorVector4FieldStyle;
 		editorVector4FieldStyle.fixedHeight = true;
@@ -975,7 +1046,7 @@ namespace BansheeEngine
 		editorVector4FieldStyle.subStyles[GUIVector4Field::getLabelStyleType()] = GUITextField::getLabelStyleType();
 		editorVector4FieldStyle.subStyles[GUIVector4Field::getFloatFieldStyleType()] = GUIFloatField::getGUITypeName();
 
-		mSkin->setStyle(GUIVector4Field::getGUITypeName(), editorVector4FieldStyle);
+		skin->setStyle(GUIVector4Field::getGUITypeName(), editorVector4FieldStyle);
 
 		/************************************************************************/
 		/* 							COMPONENT FOLDOUT                      		*/
@@ -998,7 +1069,7 @@ namespace BansheeEngine
 		cmpFoldoutBtnStyle.contentOffset = RectOffset(12, 0, 0, 0);
 		cmpFoldoutBtnStyle.border.left = 8;
 
-		mSkin->setStyle(GUIComponentFoldout::getFoldoutButtonStyleType(), cmpFoldoutBtnStyle);
+		skin->setStyle(GUIComponentFoldout::getFoldoutButtonStyleType(), cmpFoldoutBtnStyle);
 
 		GUIElementStyle cmpFoldoutStyle;
 		cmpFoldoutStyle.fixedHeight = true;
@@ -1006,7 +1077,7 @@ namespace BansheeEngine
 		cmpFoldoutStyle.minWidth = 30;
 		cmpFoldoutStyle.subStyles[GUIComponentFoldout::getFoldoutButtonStyleType()] = GUIComponentFoldout::getFoldoutButtonStyleType();
 
-		mSkin->setStyle(GUIComponentFoldout::getGUITypeName(), cmpFoldoutStyle);
+		skin->setStyle(GUIComponentFoldout::getGUITypeName(), cmpFoldoutStyle);
 
 		/************************************************************************/
 		/* 							     FOLDOUT                      		    */
@@ -1023,7 +1094,7 @@ namespace BansheeEngine
 		foldoutBtnStyle.height = 10;
 		foldoutBtnStyle.width = 8;
 
-		mSkin->setStyle(GUIFoldout::getFoldoutButtonStyleType(), foldoutBtnStyle);
+		skin->setStyle(GUIFoldout::getFoldoutButtonStyleType(), foldoutBtnStyle);
 
 		GUIElementStyle foldoutStyle;
 		foldoutStyle.fixedHeight = true;
@@ -1032,7 +1103,7 @@ namespace BansheeEngine
 		foldoutStyle.subStyles[GUIFoldout::getLabelStyleType()] = GUIFoldout::getLabelStyleType();
 		foldoutStyle.subStyles[GUIFoldout::getFoldoutButtonStyleType()] = GUIFoldout::getFoldoutButtonStyleType();
 
-		mSkin->setStyle(GUIFoldout::getGUITypeName(), foldoutStyle);
+		skin->setStyle(GUIFoldout::getGUITypeName(), foldoutStyle);
 
 		/************************************************************************/
 		/* 								PROGRESS BAR                      		*/
@@ -1042,14 +1113,14 @@ namespace BansheeEngine
 		progressBarBgStyle.height = 18;
 		progressBarBgStyle.normal.texture = getGUITexture(ProgressBarBgTex);
 
-		mSkin->setStyle(GUIProgressBar::getBackgroundStyleType(), progressBarBgStyle);
+		skin->setStyle(GUIProgressBar::getBackgroundStyleType(), progressBarBgStyle);
 
 		GUIElementStyle progressBarFillStyle;
 		progressBarFillStyle.fixedHeight = true;
 		progressBarFillStyle.height = 12;
 		progressBarFillStyle.normal.texture = getGUITexture(ProgressBarFillTex);
 
-		mSkin->setStyle(GUIProgressBar::getBarStyleType(), progressBarFillStyle);
+		skin->setStyle(GUIProgressBar::getBarStyleType(), progressBarFillStyle);
 
 		GUIElementStyle progressBarStyle;
 		progressBarStyle.fixedHeight = true;
@@ -1061,7 +1132,7 @@ namespace BansheeEngine
 		progressBarStyle.subStyles[GUIProgressBar::getBarStyleType()] = GUIProgressBar::getBarStyleType();
 		progressBarStyle.subStyles[GUIProgressBar::getBackgroundStyleType()] = GUIProgressBar::getBackgroundStyleType();
 
-		mSkin->setStyle(GUIProgressBar::getGUITypeName(), progressBarStyle);
+		skin->setStyle(GUIProgressBar::getGUITypeName(), progressBarStyle);
 
 		/************************************************************************/
 		/* 							COLOR PICKER SLIDER                      	*/
@@ -1076,7 +1147,7 @@ namespace BansheeEngine
 		colorPickerSliderHorzHandleStyle.hover.texture = colorPickerSliderHorzHandleStyle.normal.texture;
 		colorPickerSliderHorzHandleStyle.active.texture = colorPickerSliderHorzHandleStyle.normal.texture;
 
-		mSkin->setStyle("ColorSliderHorzHandle", colorPickerSliderHorzHandleStyle);
+		skin->setStyle("ColorSliderHorzHandle", colorPickerSliderHorzHandleStyle);
 
 		GUIElementStyle colorPickerSliderHorzStyle;
 		colorPickerSliderHorzHandleStyle.fixedHeight = true;
@@ -1084,7 +1155,7 @@ namespace BansheeEngine
 		colorPickerSliderHorzHandleStyle.minWidth = 20;
 		colorPickerSliderHorzStyle.subStyles[GUISlider::getHandleStyleType()] = "ColorSliderHorzHandle";
 
-		mSkin->setStyle("ColorSliderHorz", colorPickerSliderHorzStyle);
+		skin->setStyle("ColorSliderHorz", colorPickerSliderHorzStyle);
 
 		GUIElementStyle colorPickerSliderVertHandleStyle;
 		colorPickerSliderVertHandleStyle.fixedHeight = true;
@@ -1095,7 +1166,7 @@ namespace BansheeEngine
 		colorPickerSliderVertHandleStyle.hover.texture = colorPickerSliderVertHandleStyle.normal.texture;
 		colorPickerSliderVertHandleStyle.active.texture = colorPickerSliderVertHandleStyle.normal.texture;
 
-		mSkin->setStyle("ColorSliderVertHandle", colorPickerSliderVertHandleStyle);
+		skin->setStyle("ColorSliderVertHandle", colorPickerSliderVertHandleStyle);
 
 		GUIElementStyle colorPickerSliderVertStyle;
 		colorPickerSliderVertStyle.fixedWidth = true;
@@ -1103,7 +1174,7 @@ namespace BansheeEngine
 		colorPickerSliderVertStyle.minHeight = 20;
 		colorPickerSliderVertStyle.subStyles[GUISlider::getHandleStyleType()] = "ColorSliderVertHandle";
 
-		mSkin->setStyle("ColorSliderVert", colorPickerSliderVertStyle);
+		skin->setStyle("ColorSliderVert", colorPickerSliderVertStyle);
 
 		GUIElementStyle colorPickerSlider2DHandleStyle;
 		colorPickerSlider2DHandleStyle.fixedHeight = true;
@@ -1114,7 +1185,7 @@ namespace BansheeEngine
 		colorPickerSlider2DHandleStyle.hover.texture = colorPickerSlider2DHandleStyle.normal.texture;
 		colorPickerSlider2DHandleStyle.active.texture = colorPickerSlider2DHandleStyle.normal.texture;
 
-		mSkin->setStyle("ColorSlider2DHandle", colorPickerSlider2DHandleStyle);
+		skin->setStyle("ColorSlider2DHandle", colorPickerSlider2DHandleStyle);
 
 		/************************************************************************/
 		/* 									OTHER                      			*/
@@ -1130,153 +1201,15 @@ namespace BansheeEngine
 		rightAlignedLabelStyle.minWidth = 10;
 		rightAlignedLabelStyle.textHorzAlign = THA_Right;
 
-		mSkin->setStyle("RightAlignedLabel", rightAlignedLabelStyle);
-	}
-
-	void BuiltinEditorResources::preprocess()
-	{
-		static const WString GUI_TEXTURES[] = 
-		{   WindowBackgroundTexture, ButtonNormalTex, ButtonHoverTex, ButtonActiveTex, ToggleNormalTex,
-			ToggleHoverTex, ToggleActiveTex, ToggleNormalOnTex, ToggleHoverOnTex, ToggleActiveOnTex,
-			ObjectDropBtnNormalTex, ObjectDropBtnNormalOnTex, ObjectClearBtnNormalTex, ObjectClearBtnHoverTex,
-			ObjectClearBtnActiveTex, FoldoutOpenNormalTex, FoldoutOpenHoverTex, FoldoutClosedNormalTex,
-			FoldoutClosedHoverTex, CmpFoldoutOpenNormalTex, CmpFoldoutOpenHoverTex, CmpFoldoutOpenActiveTex,
-			CmpFoldoutClosedNormalTex, CmpFoldoutClosedHoverTex, CmpFoldoutClosedActiveTex, WindowFrameNormal,
-			WindowFrameFocused, WindowTitleBarBg, WindowCloseButtonNormal, WindowCloseButtonHover, WindowMinButtonNormal,
-			WindowMinButtonHover, WindowMaxButtonNormal, WindowMaxButtonHover, TabbedBarBtnNormal, TabbedBarBtnActive,
-			InputBoxNormalTex, InputBoxHoverTex, InputBoxFocusedTex, ScrollBarUpNormalTex, ScrollBarUpHoverTex,
-			ScrollBarUpActiveTex, ScrollBarDownNormalTex, ScrollBarDownHoverTex, ScrollBarDownActiveTex, ScrollBarLeftNormalTex,
-			ScrollBarLeftHoverTex, ScrollBarLeftActiveTex, ScrollBarRightNormalTex, ScrollBarRightHoverTex, ScrollBarRightActiveTex,
-			ScrollBarHandleHorzNormalTex, ScrollBarHandleHorzHoverTex, ScrollBarHandleHorzActiveTex, ScrollBarHandleVertNormalTex,
-			ScrollBarHandleVertHoverTex, ScrollBarHandleVertActiveTex, DropDownBtnNormalTex, DropDownBtnHoverTex,
-			DropDownBoxBgTex, DropDownBoxEntryNormalTex, DropDownBoxEntryHoverTex, DropDownBoxBtnUpNormalTex,
-			DropDownBoxBtnUpHoverTex, DropDownBoxBtnDownNormalTex, DropDownBoxBtnDownHoverTex, DropDownBoxEntryExpNormalTex,
-			DropDownBoxEntryExpHoverTex, DropDownSeparatorTex, DropDownBoxBtnUpArrowTex, DropDownBoxBtnDownArrowTex,
-			ScrollBarBgTex, MenuBarBgTex, MenuBarBtnNormalTex, MenuBarBtnHoverTex, MenuBarBansheeLogoTex, DockSliderNormalTex,
-			TreeViewExpandButtonOffNormal, TreeViewExpandButtonOffHover, TreeViewExpandButtonOnNormal, TreeViewExpandButtonOnHover,
-			TreeViewSelectionBackground, TreeViewEditBox, TreeViewElementHighlight, TreeViewElementSepHighlight, ProgressBarBgTex,
-			ProgressBarFillTex, ColorPickerSliderHorzHandleTex, ColorPickerSliderVertHandleTex, ColorPickerSlider2DHandleTex };
-
-		if (FileSystem::exists(DefaultSkinFolderRaw))
-		{
-			FileSystem::remove(DefaultSkinFolder);
-
-			for (auto& tex : GUI_TEXTURES)
-				importGUITexture(tex);
-
-			{
-				Path fontPath = FileSystem::getWorkingDirectoryPath();
-				fontPath.append(DefaultSkinFolderRaw);
-				fontPath.append(DefaultFontFilename);
-
-				ImportOptionsPtr fontImportOptions = Importer::instance().createImportOptions(fontPath);
-				if (rtti_is_of_type<FontImportOptions>(fontImportOptions))
-				{
-					FontImportOptions* importOptions = static_cast<FontImportOptions*>(fontImportOptions.get());
-
-					Vector<UINT32> fontSizes;
-					fontSizes.push_back(DefaultFontSize);
-					importOptions->setFontSizes(fontSizes);
-					importOptions->setAntialiasing(false);
-				}
-
-				HFont font = Importer::instance().import<Font>(fontPath, fontImportOptions);
-
-				Path outputPath = FileSystem::getWorkingDirectoryPath();
-				outputPath.append(DefaultSkinFolder);
-				outputPath.append(DefaultFontFilename + L".asset");
-
-				Resources::instance().save(font, outputPath, true);
-
-				// Save font texture pages as well. TODO - Later maybe figure out a more automatic way to do this
-				const FontData* fontData = font->getFontDataForSize(DefaultFontSize);
-
-				Path texPageOutputPath = FileSystem::getWorkingDirectoryPath();
-				texPageOutputPath.append(DefaultSkinFolder);
-
-				UINT32 pageIdx = 0;
-				for (auto tex : fontData->texturePages)
-				{
-					texPageOutputPath.setFilename(DefaultFontFilename + L"_texpage_" + toWString(pageIdx) + L".asset");
-					Resources::instance().save(tex, texPageOutputPath, true);
-				}
-			}
-		}
-
-		if (FileSystem::exists(DefaultShaderFolderRaw))
-		{
-			FileSystem::remove(DefaultShaderFolder);
-
-			Vector<Path> directories;
-			Vector<Path> files;
-			FileSystem::getChildren(DefaultShaderFolderRaw, files, directories);
-
-			// Process includes first since shaders reference them
-			for (auto& shaderFile : files)
-			{
-				if (shaderFile.getExtension() != ".bslinc")
-					continue;
-
-				HResource resource = Importer::instance().import(shaderFile);
-
-				if (resource != nullptr)
-				{
-					if (rtti_is_of_type<ShaderInclude>(resource.getInternalPtr()))
-					{
-						Path outputLoc = DefaultShaderFolder;
-						outputLoc.append(shaderFile.getWFilename() + L".asset");
-
-						Resources::instance().save(resource, outputLoc, true);
-					}
-				}
-			}
-
-			for (auto& shaderFile : files)
-			{
-				if (shaderFile.getExtension() != ".bsl")
-					continue;
-
-				HResource resource = Importer::instance().import(shaderFile);
-
-				if (resource != nullptr)
-				{
-					if (rtti_is_of_type<Shader>(resource.getInternalPtr()))
-					{
-						Path outputLoc = DefaultShaderFolder;
-						outputLoc.append(shaderFile.getWFilename() + L".asset");
-
-						Resources::instance().save(resource, outputLoc, true);
-					}
-				}
-			}
-		}
-
-		Resources::instance().unloadAllUnused();
-	}
-
-	void BuiltinEditorResources::importGUITexture(const WString& name)
-	{
-		Path texturePath = FileSystem::getWorkingDirectoryPath();
-		texturePath.append(DefaultSkinFolderRaw);
-		texturePath.append(name);
-
-		Path texOutputPath = FileSystem::getWorkingDirectoryPath();
-		texOutputPath.append(DefaultSkinFolder);
-		Path spriteTexOutputPath = texOutputPath;
-		texOutputPath.append(name + L".asset");
-		spriteTexOutputPath.append(L"sprite_" + name + L".asset");
-
-		HTexture tex = Importer::instance().import<Texture>(texturePath);
-		Resources::instance().save(tex, texOutputPath, true);
+		skin->setStyle("RightAlignedLabel", rightAlignedLabelStyle);
 
-		HSpriteTexture spriteTex = SpriteTexture::create(tex);
-		Resources::instance().save(spriteTex, spriteTexOutputPath, true);
+		return skin;
 	}
 
 	HSpriteTexture BuiltinEditorResources::getGUITexture(const WString& name)
 	{
 		Path texturePath = FileSystem::getWorkingDirectoryPath();
-		texturePath.append(DefaultSkinFolder);
+		texturePath.append(EditorSkinFolder);
 		texturePath.append(L"sprite_" + name + L".asset");
 
 		return Resources::instance().load<SpriteTexture>(texturePath);
@@ -1284,7 +1217,7 @@ namespace BansheeEngine
 
 	HShader BuiltinEditorResources::getShader(const WString& name)
 	{
-		Path programPath = DefaultShaderFolder;
+		Path programPath = EditorShaderFolder;
 		programPath.append(name + L".asset");
 
 		return gResources().load<Shader>(programPath);

+ 2 - 2
BansheeEditor/Source/BsShaderIncludeHandler.cpp

@@ -36,7 +36,7 @@ namespace BansheeEngine
 		{
 			if (name.size() > 8)
 			{
-				Path fullPath = BuiltinResources::DefaultShaderFolder;
+				Path fullPath = BuiltinResources::EngineShaderIncludeFolder;
 				Path includePath = name.substr(9, name.size() - 9);
 
 				fullPath.append(includePath);
@@ -49,7 +49,7 @@ namespace BansheeEngine
 		{
 			if (name.size() > 8)
 			{
-				Path fullPath = BuiltinEditorResources::DefaultShaderFolder;
+				Path fullPath = BuiltinEditorResources::EditorShaderIncludeFolder;
 				Path includePath = name.substr(9, name.size() - 9);
 
 				fullPath.append(includePath);

+ 66 - 20
BansheeEngine/Include/BsBuiltinResources.h

@@ -98,9 +98,11 @@ namespace BansheeEngine
 		 */
 		HMaterial createDummyMaterial() const;
 
-		static const Path DefaultSkinFolder;
-		static const Path DefaultCursorFolder;
-		static const Path DefaultShaderFolder;
+		static const Path BuiltinDataFolder;
+		static const Path EngineSkinFolder;
+		static const Path EngineCursorFolder;
+		static const Path EngineShaderFolder;
+		static const Path EngineShaderIncludeFolder;
 
 	private:
 		/**
@@ -111,6 +113,11 @@ namespace BansheeEngine
 		 */
 		void preprocess();
 
+		/**
+		 * @brief	Generates the default engine skin and all GUI element styles.
+		 */
+		HGUISkin generateGUISkin();
+
 		/**
 		 * @brief	Loads a GUI skin texture with the specified filename.
 		 */
@@ -121,20 +128,6 @@ namespace BansheeEngine
 		 */
 		static HTexture getCursorTexture(const WString& name);
 
-		/**
-		 * @brief	Imports a GUI skin texture with the specified filename.
-		 *			Saves the imported texture in engine-ready format in the corresponding
-		 *			output folder.
-		 */
-		static void importSkinTexture(const WString& name);
-
-		/**
-		 * @brief	Imports a cursor texture with the specified filename.
-		 *			Saves the imported texture in engine-ready format in the corresponding
-		 *			output folder.
-		 */
-		static void importCursorTexture(const WString& name);
-
 		/**
 		 * @brief	Loads a shader with the specified filename
 		 */
@@ -160,13 +153,25 @@ namespace BansheeEngine
 		HShader mShaderSpriteNonAlphaImage;
 		HShader mShaderDummy;
 
-		static const Path DefaultSkinFolderRaw;
-		static const Path DefaultCursorFolderRaw;
-		static const Path DefaultShaderFolderRaw;
+		ResourceManifestPtr mResourceManifest;
+
+		static const Path BuiltinRawDataFolder;
+		static const Path EngineRawCursorFolder;
+		static const Path EngineRawShaderFolder;
+		static const Path EngineRawShaderIncludeFolder;
+		static const Path EngineRawSkinFolder;
+
+		static const Path CursorFolder;
+		static const Path ShaderFolder;
+		static const Path ShaderIncludeFolder;
+		static const Path SkinFolder;
+
+		static const Path ResourceManifestPath;
 
 		static const WString DefaultFontFilename;
 		static const UINT32 DefaultFontSize;
 
+		static const WString GUISkinFile;
 		static const WString WhiteTex;
 
 		static const WString ButtonNormalTex;
@@ -258,4 +263,45 @@ namespace BansheeEngine
 		static const WString ShaderSpriteImageNoAlphaFile;
 		static const WString ShaderDummyFile;
 	};
+
+	/**
+	 * @brief	Provides various methods commonly used for managing builtin resources.
+	 */
+	class BS_EXPORT BuiltinResourcesHelper
+	{
+	public:
+		/**
+		 * @brief	Imports all recognized assets in the specified folder and saves
+		 *			them to the specified output folder. All saved resources are registered in the
+		 *			provided resource manifest.
+		 */
+		static void importAssets(const Path& inputFolder, const Path& outputFolder, const ResourceManifestPtr& manifest);
+
+		/**
+		 * @brief	Imports a font from the specified file. Imported font assets
+		 *			are saved in the output folder. All saved resources are registered in the
+		 *			provided resource manifest.
+		 */
+		static void importFont(const Path& inputFile, const Path& outputFolder, UINT32 size, 
+			bool antialiasing, const ResourceManifestPtr& manifest);
+
+		/**
+		 * @brief	Generates sprite textures for all texture assets in the specified folder.
+		 *			Results are written in the same folder with a "sprite_" prefix. All saved 
+		 *			resources are registered in the provided resource manifest.
+		 */
+		static void generateSpriteTextures(const Path& folder, const ResourceManifestPtr& manifest);
+
+		/**
+		 * @brief	Writes a timestamp with the current date and time in the specified file.
+		 */
+		static void writeTimestamp(const Path& file);
+
+		/**
+		 * @brief	Checks all files in the specified folder for modifications compared to the
+		 *			time stored in the timestamp file. Timestamp file must have been saved
+		 *			using "writeTimestamp".
+		 */
+		static bool checkForModifications(const Path& folder, const Path& timeStampFile);
+	};
 }

+ 253 - 201
BansheeEngine/Source/BsBuiltinResources.cpp

@@ -26,19 +26,35 @@
 #include "BsCoreApplication.h"
 #include "BsCoreThread.h"
 #include "BsApplication.h"
+#include "BsDataStream.h"
+#include "BsTime.h"
+#include "BsResourceManifest.h"
 
 namespace BansheeEngine
 {
 	const WString BuiltinResources::DefaultFontFilename = L"arial.ttf";
 	const UINT32 BuiltinResources::DefaultFontSize = 10;
 
-	const Path BuiltinResources::DefaultSkinFolderRaw = L"..\\..\\..\\..\\Data\\Raw\\Engine\\Skin\\";
-	const Path BuiltinResources::DefaultCursorFolderRaw = L"..\\..\\..\\..\\Data\\Raw\\Engine\\Cursors\\";
-	const Path BuiltinResources::DefaultShaderFolderRaw = L"..\\..\\..\\..\\Data\\Raw\\Engine\\Shaders\\";
+	const WString BuiltinResources::GUISkinFile = L"GUISkin";
 
-	const Path BuiltinResources::DefaultSkinFolder = L"..\\..\\..\\..\\Data\\Engine\\Skin\\";
-	const Path BuiltinResources::DefaultCursorFolder = L"..\\..\\..\\..\\Data\\Engine\\Cursors\\";
-	const Path BuiltinResources::DefaultShaderFolder = L"..\\..\\..\\..\\Data\\Engine\\Shaders\\";
+	const Path BuiltinResources::CursorFolder = L"Cursors\\";
+	const Path BuiltinResources::ShaderFolder = L"Shaders\\";
+	const Path BuiltinResources::SkinFolder = L"Skin\\";
+	const Path BuiltinResources::ShaderIncludeFolder = L"Includes\\";
+
+	const Path BuiltinResources::BuiltinRawDataFolder = L"..\\..\\..\\..\\Data\\Raw\\Engine\\";
+	const Path BuiltinResources::EngineRawSkinFolder = BuiltinRawDataFolder + SkinFolder;
+	const Path BuiltinResources::EngineRawCursorFolder = BuiltinRawDataFolder + CursorFolder;
+	const Path BuiltinResources::EngineRawShaderFolder = BuiltinRawDataFolder + ShaderFolder;
+	const Path BuiltinResources::EngineRawShaderIncludeFolder = BuiltinRawDataFolder + ShaderIncludeFolder;
+
+	const Path BuiltinResources::BuiltinDataFolder = L"..\\..\\..\\..\\Data\\Engine\\";
+	const Path BuiltinResources::EngineSkinFolder = BuiltinDataFolder + SkinFolder;
+	const Path BuiltinResources::EngineCursorFolder = BuiltinDataFolder + CursorFolder;
+	const Path BuiltinResources::EngineShaderFolder = BuiltinDataFolder + ShaderFolder;
+	const Path BuiltinResources::EngineShaderIncludeFolder = BuiltinDataFolder + ShaderIncludeFolder;
+
+	const Path BuiltinResources::ResourceManifestPath = BuiltinDataFolder + "ResourceManifest.asset";
 
 	/************************************************************************/
 	/* 								GUI TEXTURES                      		*/
@@ -159,8 +175,30 @@ namespace BansheeEngine
 
 	BuiltinResources::BuiltinResources()
 	{
-		preprocess();
+		Path absoluteDataPath = FileSystem::getWorkingDirectoryPath();
+		absoluteDataPath.append(BuiltinDataFolder);
+
+		if (FileSystem::exists(ResourceManifestPath))
+			mResourceManifest = ResourceManifest::load(ResourceManifestPath, absoluteDataPath);
+
+		if (mResourceManifest == nullptr)
+			mResourceManifest = ResourceManifest::create("BuiltinResources");
+
+		gResources().registerResourceManifest(mResourceManifest);
+
+#if BS_DEBUG_MODE
+		if (BuiltinResourcesHelper::checkForModifications(BuiltinRawDataFolder, BuiltinDataFolder + L"Timestamp.asset"))
+		{
+			preprocess();
+			BuiltinResourcesHelper::writeTimestamp(BuiltinDataFolder + L"Timestamp.asset");
+
+			Path absoluteDataPath = FileSystem::getWorkingDirectoryPath();
+			absoluteDataPath.append(BuiltinDataFolder);
 
+			ResourceManifest::save(mResourceManifest, ResourceManifestPath, absoluteDataPath);
+		}
+#endif
+		
 		mShaderSpriteText = getShader(ShaderSpriteTextFile);
 		mShaderSpriteImage = getShader(ShaderSpriteImageAlphaFile);
 		mShaderSpriteNonAlphaImage = getShader(ShaderSpriteImageNoAlphaFile);
@@ -168,6 +206,8 @@ namespace BansheeEngine
 
 		mWhiteSpriteTexture = getSkinTexture(WhiteTex);
 
+		mSkin = gResources().load<GUISkin>(BuiltinDataFolder + (GUISkinFile + L".asset"));
+
 		/************************************************************************/
 		/* 								CURSOR		                     		*/
 		/************************************************************************/
@@ -214,13 +254,45 @@ namespace BansheeEngine
 		cursorSizeWETex->readSubresource(gCoreAccessor(), 0, mCursorSizeWE);
 
 		gCoreAccessor().submitToCoreThread(true);
+	}
+
+	void BuiltinResources::preprocess()
+	{
+		FileSystem::remove(EngineCursorFolder);
+		FileSystem::remove(EngineShaderIncludeFolder);
+		FileSystem::remove(EngineShaderFolder);
+		FileSystem::remove(EngineSkinFolder);
+
+		BuiltinResourcesHelper::importAssets(EngineRawCursorFolder, EngineCursorFolder, mResourceManifest);
+		BuiltinResourcesHelper::importAssets(EngineRawShaderIncludeFolder, EngineShaderIncludeFolder, mResourceManifest); // Hidden dependency: Includes must be imported before shaders
+		BuiltinResourcesHelper::importAssets(EngineRawShaderFolder, EngineShaderFolder, mResourceManifest);
+		BuiltinResourcesHelper::importAssets(EngineRawSkinFolder, EngineSkinFolder, mResourceManifest);
 
+		// Import font
+		BuiltinResourcesHelper::importFont(BuiltinRawDataFolder + DefaultFontFilename, BuiltinDataFolder, DefaultFontSize, false, mResourceManifest);
+
+		// Generate & save GUI sprite textures
+		BuiltinResourcesHelper::generateSpriteTextures(EngineSkinFolder, mResourceManifest);
+
+		// Generate & save GUI skin
+		{
+			HGUISkin skin = generateGUISkin();
+			Path outputPath = FileSystem::getWorkingDirectoryPath() + BuiltinDataFolder + (GUISkinFile + L".asset");
+			Resources::instance().save(skin, outputPath, true);
+			mResourceManifest->registerResource(skin.getUUID(), outputPath);
+		}
+		
+		Resources::instance().unloadAllUnused();
+	}
+
+	HGUISkin BuiltinResources::generateGUISkin()
+	{
 		Path fontPath = FileSystem::getWorkingDirectoryPath();
-		fontPath.append(DefaultSkinFolder);
+		fontPath.append(BuiltinDataFolder);
 		fontPath.append(DefaultFontFilename + L".asset");
 
 		HFont font = Resources::instance().load<Font>(fontPath);
-		mSkin = GUISkin::create();
+		HGUISkin skin = GUISkin::create();
 
 		// Label
 		GUIElementStyle labelStyle;
@@ -231,7 +303,7 @@ namespace BansheeEngine
 		labelStyle.height = 11;
 		labelStyle.minWidth = 10;
 
-		mSkin->setStyle(GUILabel::getGUITypeName(), labelStyle);
+		skin->setStyle(GUILabel::getGUITypeName(), labelStyle);
 
 		// Button
 		GUIElementStyle buttonStyle;
@@ -252,7 +324,7 @@ namespace BansheeEngine
 		buttonStyle.textHorzAlign = THA_Center;
 		buttonStyle.textVertAlign = TVA_Center;
 
-		mSkin->setStyle(GUIButton::getGUITypeName(), buttonStyle);
+		skin->setStyle(GUIButton::getGUITypeName(), buttonStyle);
 
 		// Toggle
 		GUIElementStyle toggleStyle;
@@ -267,7 +339,7 @@ namespace BansheeEngine
 		toggleStyle.height = 15;
 		toggleStyle.width = 15;
 
-		mSkin->setStyle(GUIToggle::getGUITypeName(), toggleStyle);
+		skin->setStyle(GUIToggle::getGUITypeName(), toggleStyle);
 
 		// Input box
 		GUIElementStyle inputBoxStyle;
@@ -291,7 +363,7 @@ namespace BansheeEngine
 		inputBoxStyle.textHorzAlign = THA_Left;
 		inputBoxStyle.textVertAlign = TVA_Top;
 
-		mSkin->setStyle(GUIInputBox::getGUITypeName(), inputBoxStyle);
+		skin->setStyle(GUIInputBox::getGUITypeName(), inputBoxStyle);
 
 		/************************************************************************/
 		/* 								SCROLL BAR                      		*/
@@ -307,7 +379,7 @@ namespace BansheeEngine
 		scrollUpBtnStyle.height = 4;
 		scrollUpBtnStyle.width = 8;
 
-		mSkin->setStyle("ScrollUpBtn", scrollUpBtnStyle);
+		skin->setStyle("ScrollUpBtn", scrollUpBtnStyle);
 
 		// Down button
 		GUIElementStyle scrollDownBtnStyle;
@@ -319,7 +391,7 @@ namespace BansheeEngine
 		scrollDownBtnStyle.height = 4;
 		scrollDownBtnStyle.width = 8;
 
-		mSkin->setStyle("ScrollDownBtn", scrollDownBtnStyle);
+		skin->setStyle("ScrollDownBtn", scrollDownBtnStyle);
 
 		// Left button
 		GUIElementStyle scrollLeftBtnStyle;
@@ -331,7 +403,7 @@ namespace BansheeEngine
 		scrollLeftBtnStyle.height = 8;
 		scrollLeftBtnStyle.width = 4;
 
-		mSkin->setStyle("ScrollLeftBtn", scrollLeftBtnStyle);
+		skin->setStyle("ScrollLeftBtn", scrollLeftBtnStyle);
 
 		// Right button
 		GUIElementStyle scrollRightBtnStyle;
@@ -343,7 +415,7 @@ namespace BansheeEngine
 		scrollRightBtnStyle.height = 8;
 		scrollRightBtnStyle.width = 4;
 
-		mSkin->setStyle("ScrollRightBtn", scrollRightBtnStyle);
+		skin->setStyle("ScrollRightBtn", scrollRightBtnStyle);
 
 		// Horizontal handle
 		GUIElementStyle scrollBarHorzBtnStyle;
@@ -355,7 +427,7 @@ namespace BansheeEngine
 		scrollBarHorzBtnStyle.height = 6;
 		scrollBarHorzBtnStyle.width = 4;
 
-		mSkin->setStyle("ScrollBarHorzBtn", scrollBarHorzBtnStyle);
+		skin->setStyle("ScrollBarHorzBtn", scrollBarHorzBtnStyle);
 
 		// Vertical handle
 		GUIElementStyle scrollBarVertBtnStyle;
@@ -367,7 +439,7 @@ namespace BansheeEngine
 		scrollBarVertBtnStyle.height = 4;
 		scrollBarVertBtnStyle.width = 6;
 
-		mSkin->setStyle("ScrollBarVertBtn", scrollBarVertBtnStyle);
+		skin->setStyle("ScrollBarVertBtn", scrollBarVertBtnStyle);
 
 		HSpriteTexture scrollBarBgPtr = getSkinTexture(ScrollBarBgTex);
 
@@ -381,7 +453,7 @@ namespace BansheeEngine
 		vertScrollBarStyle.minHeight = 16;
 		vertScrollBarStyle.width = 8;
 
-		mSkin->setStyle("ScrollBarVert", vertScrollBarStyle);
+		skin->setStyle("ScrollBarVert", vertScrollBarStyle);
 
 		// Horizontal scroll bar
 		GUIElementStyle horzScrollBarStyle;
@@ -393,7 +465,7 @@ namespace BansheeEngine
 		horzScrollBarStyle.minWidth = 16;
 		horzScrollBarStyle.height = 8;
 
-		mSkin->setStyle("ScrollBarHorz", horzScrollBarStyle);
+		skin->setStyle("ScrollBarHorz", horzScrollBarStyle);
 
 		/************************************************************************/
 		/* 								DROP DOWN BOX                      		*/
@@ -424,7 +496,7 @@ namespace BansheeEngine
 		dropDownListStyle.textHorzAlign = THA_Left;
 		dropDownListStyle.textVertAlign = TVA_Top;
 
-		mSkin->setStyle("ListBox", dropDownListStyle);
+		skin->setStyle("ListBox", dropDownListStyle);
 
 		// DropDown scroll up button arrow
 		GUIElementStyle dropDownScrollUpBtnArrowStyle;
@@ -440,9 +512,9 @@ namespace BansheeEngine
 		dropDownScrollUpBtnArrowStyle.border.top = 1;
 		dropDownScrollUpBtnArrowStyle.border.bottom = 1;
 
-		mSkin->setStyle("ListBoxScrollUpBtnArrow", dropDownScrollUpBtnArrowStyle);
-		mSkin->setStyle("MenuBarScrollUpBtnArrow", dropDownScrollUpBtnArrowStyle);
-		mSkin->setStyle("ContextMenuScrollUpBtnArrow", dropDownScrollUpBtnArrowStyle);
+		skin->setStyle("ListBoxScrollUpBtnArrow", dropDownScrollUpBtnArrowStyle);
+		skin->setStyle("MenuBarScrollUpBtnArrow", dropDownScrollUpBtnArrowStyle);
+		skin->setStyle("ContextMenuScrollUpBtnArrow", dropDownScrollUpBtnArrowStyle);
 
 		// DropDown scroll up button
 		GUIElementStyle dropDownScrollUpBtnStyle;
@@ -458,9 +530,9 @@ namespace BansheeEngine
 		dropDownScrollUpBtnStyle.border.top = 1;
 		dropDownScrollUpBtnStyle.border.bottom = 1;
 
-		mSkin->setStyle("ListBoxScrollUpBtn", dropDownScrollUpBtnStyle);
-		mSkin->setStyle("MenuBarScrollUpBtn", dropDownScrollUpBtnStyle);
-		mSkin->setStyle("ContextMenuScrollUpBtn", dropDownScrollUpBtnStyle);
+		skin->setStyle("ListBoxScrollUpBtn", dropDownScrollUpBtnStyle);
+		skin->setStyle("MenuBarScrollUpBtn", dropDownScrollUpBtnStyle);
+		skin->setStyle("ContextMenuScrollUpBtn", dropDownScrollUpBtnStyle);
 
 		// DropDown scroll down button arrow
 		GUIElementStyle dropDownScrollDownBtnArrowStyle;
@@ -475,10 +547,10 @@ namespace BansheeEngine
 		dropDownScrollDownBtnArrowStyle.border.right = 1;
 		dropDownScrollDownBtnArrowStyle.border.top = 1;
 		dropDownScrollDownBtnArrowStyle.border.bottom = 1;
-		
-		mSkin->setStyle("ListBoxScrollDownBtnArrow", dropDownScrollDownBtnArrowStyle);
-		mSkin->setStyle("MenuBarScrollDownBtnArrow", dropDownScrollDownBtnArrowStyle);
-		mSkin->setStyle("ContextMenuScrollDownBtnArrow", dropDownScrollDownBtnArrowStyle);
+
+		skin->setStyle("ListBoxScrollDownBtnArrow", dropDownScrollDownBtnArrowStyle);
+		skin->setStyle("MenuBarScrollDownBtnArrow", dropDownScrollDownBtnArrowStyle);
+		skin->setStyle("ContextMenuScrollDownBtnArrow", dropDownScrollDownBtnArrowStyle);
 
 		// DropDown scroll down button
 		GUIElementStyle dropDownScrollDownBtnStyle;
@@ -494,9 +566,9 @@ namespace BansheeEngine
 		dropDownScrollDownBtnStyle.border.top = 1;
 		dropDownScrollDownBtnStyle.border.bottom = 1;
 
-		mSkin->setStyle("ListBoxScrollDownBtn", dropDownScrollDownBtnStyle);
-		mSkin->setStyle("MenuBarScrollDownBtn", dropDownScrollDownBtnStyle);
-		mSkin->setStyle("ContextMenuScrollDownBtn", dropDownScrollDownBtnStyle);
+		skin->setStyle("ListBoxScrollDownBtn", dropDownScrollDownBtnStyle);
+		skin->setStyle("MenuBarScrollDownBtn", dropDownScrollDownBtnStyle);
+		skin->setStyle("ContextMenuScrollDownBtn", dropDownScrollDownBtnStyle);
 
 		// DropDown entry button
 		GUIElementStyle dropDownEntryBtnStyle;
@@ -519,7 +591,7 @@ namespace BansheeEngine
 		dropDownEntryBtnStyle.textHorzAlign = THA_Left;
 		dropDownEntryBtnStyle.textVertAlign = TVA_Top;
 
-		mSkin->setStyle(GUIDropDownContent::ENTRY_STYLE_TYPE, dropDownEntryBtnStyle);
+		skin->setStyle(GUIDropDownContent::ENTRY_STYLE_TYPE, dropDownEntryBtnStyle);
 
 		// DropDown entry button with expand
 		GUIElementStyle dropDownEntryExpBtnStyle;
@@ -542,7 +614,7 @@ namespace BansheeEngine
 		dropDownEntryExpBtnStyle.textHorzAlign = THA_Left;
 		dropDownEntryExpBtnStyle.textVertAlign = TVA_Top;
 
-		mSkin->setStyle(GUIDropDownContent::ENTRY_EXP_STYLE_TYPE, dropDownEntryExpBtnStyle);
+		skin->setStyle(GUIDropDownContent::ENTRY_EXP_STYLE_TYPE, dropDownEntryExpBtnStyle);
 
 		// Drop down separator
 		GUIElementStyle dropDownSeparatorStyle;
@@ -556,7 +628,7 @@ namespace BansheeEngine
 		dropDownSeparatorStyle.border.top = 1;
 		dropDownSeparatorStyle.border.bottom = 1;
 
-		mSkin->setStyle(GUIDropDownContent::SEPARATOR_STYLE_TYPE, dropDownSeparatorStyle);
+		skin->setStyle(GUIDropDownContent::SEPARATOR_STYLE_TYPE, dropDownSeparatorStyle);
 
 		// Drop down content
 		GUIElementStyle dropDownContentStyle;
@@ -566,9 +638,9 @@ namespace BansheeEngine
 		dropDownContentStyle.subStyles[GUIDropDownContent::ENTRY_EXP_STYLE_TYPE] = GUIDropDownContent::ENTRY_EXP_STYLE_TYPE;
 		dropDownContentStyle.subStyles[GUIDropDownContent::SEPARATOR_STYLE_TYPE] = GUIDropDownContent::SEPARATOR_STYLE_TYPE;
 
-		mSkin->setStyle("ListBoxContent", dropDownContentStyle);
-		mSkin->setStyle("MenuBarContent", dropDownContentStyle);
-		mSkin->setStyle("ContextMenuContent", dropDownContentStyle);
+		skin->setStyle("ListBoxContent", dropDownContentStyle);
+		skin->setStyle("MenuBarContent", dropDownContentStyle);
+		skin->setStyle("ContextMenuContent", dropDownContentStyle);
 
 		// DropDown box frame
 		GUIElementStyle dropDownBoxStyle;
@@ -586,9 +658,9 @@ namespace BansheeEngine
 		dropDownBoxStyle.margins.top = 1;
 		dropDownBoxStyle.margins.bottom = 1;
 
-		mSkin->setStyle("ListBoxFrame", dropDownBoxStyle);
-		mSkin->setStyle("MenuBarFrame", dropDownBoxStyle);
-		mSkin->setStyle("ContextMenuFrame", dropDownBoxStyle);
+		skin->setStyle("ListBoxFrame", dropDownBoxStyle);
+		skin->setStyle("MenuBarFrame", dropDownBoxStyle);
+		skin->setStyle("ContextMenuFrame", dropDownBoxStyle);
 
 		/************************************************************************/
 		/* 									OTHER                      			*/
@@ -604,134 +676,15 @@ namespace BansheeEngine
 		rightAlignedLabelStyle.minWidth = 10;
 		rightAlignedLabelStyle.textHorzAlign = THA_Right;
 
-		mSkin->setStyle("RightAlignedLabel", rightAlignedLabelStyle);
-	}
-
-	void BuiltinResources::preprocess()
-	{
-		static const WString GUI_TEXTURES[] = { WhiteTex, ButtonNormalTex, ButtonHoverTex, ButtonActiveTex, ToggleNormalTex,
-			ToggleHoverTex, ToggleActiveTex, ToggleNormalOnTex, ToggleHoverOnTex, ToggleActiveOnTex, InputBoxNormalTex,
-			InputBoxHoverTex, InputBoxFocusedTex, ScrollBarUpNormalTex, ScrollBarUpHoverTex, ScrollBarUpActiveTex,
-			ScrollBarDownNormalTex, ScrollBarDownHoverTex, ScrollBarDownActiveTex, ScrollBarLeftNormalTex,
-			ScrollBarLeftHoverTex, ScrollBarLeftActiveTex, ScrollBarRightNormalTex, ScrollBarRightHoverTex,
-			ScrollBarRightActiveTex, ScrollBarHandleHorzNormalTex, ScrollBarHandleHorzHoverTex, ScrollBarHandleHorzActiveTex,
-			ScrollBarHandleVertNormalTex, ScrollBarHandleVertHoverTex, ScrollBarHandleVertActiveTex, DropDownBtnNormalTex,
-			DropDownBtnHoverTex, DropDownBoxBgTex, DropDownBoxEntryNormalTex, DropDownBoxEntryHoverTex, DropDownBoxBtnUpNormalTex,
-			DropDownBoxBtnUpHoverTex, DropDownBoxBtnDownNormalTex, DropDownBoxBtnDownHoverTex, DropDownBoxEntryExpNormalTex, DropDownBoxEntryExpHoverTex,
-			DropDownSeparatorTex, DropDownBoxBtnUpArrowTex, DropDownBoxBtnDownArrowTex };
-
-		static const WString CURSOR_TEXTURES[] = { CursorArrowTex, CursorArrowDragTex, CursorArrowLeftRightTex, CursorIBeamTex,
-			CursorDenyTex, CursorWaitTex, CursorSizeNESWTex, CursorSizeNSTex, CursorSizeNWSETex, CursorSizeWETex };
-
-		if (FileSystem::exists(DefaultCursorFolderRaw))
-		{
-			FileSystem::remove(DefaultCursorFolder);
-
-			for (auto& tex : CURSOR_TEXTURES)
-				importCursorTexture(tex);
-		}
-
-		if (FileSystem::exists(DefaultSkinFolderRaw))
-		{
-			FileSystem::remove(DefaultSkinFolder);
-
-			for (auto& tex : GUI_TEXTURES)
-				importSkinTexture(tex);
-
-			{
-				Path fontPath = FileSystem::getWorkingDirectoryPath();
-				fontPath.append(DefaultSkinFolderRaw);
-				fontPath.append(DefaultFontFilename);
-
-				ImportOptionsPtr fontImportOptions = Importer::instance().createImportOptions(fontPath);
-				if (rtti_is_of_type<FontImportOptions>(fontImportOptions))
-				{
-					FontImportOptions* importOptions = static_cast<FontImportOptions*>(fontImportOptions.get());
-
-					Vector<UINT32> fontSizes;
-					fontSizes.push_back(DefaultFontSize);
-					importOptions->setFontSizes(fontSizes);
-					importOptions->setAntialiasing(false);
-				}
-
-				HFont font = Importer::instance().import<Font>(fontPath, fontImportOptions);
-
-				Path outputPath = FileSystem::getWorkingDirectoryPath();
-				outputPath.append(DefaultSkinFolder);
-				outputPath.append(DefaultFontFilename + L".asset");
-
-				Resources::instance().save(font, outputPath, true);
-
-				// Save font texture pages as well. TODO - Later maybe figure out a more automatic way to do this
-				const FontData* fontData = font->getFontDataForSize(DefaultFontSize);
-
-				Path texPageOutputPath = FileSystem::getWorkingDirectoryPath();
-				texPageOutputPath.append(DefaultSkinFolder);
-
-				UINT32 pageIdx = 0;
-				for (auto tex : fontData->texturePages)
-				{
-					texPageOutputPath.setFilename(DefaultFontFilename + L"_texpage_" + toWString(pageIdx) + L".asset");
-					Resources::instance().save(tex, texPageOutputPath, true);
-				}
-			}
-		}
-
-		if (FileSystem::exists(DefaultShaderFolderRaw))
-		{
-			FileSystem::remove(DefaultShaderFolder);
-
-			Vector<Path> directories;
-			Vector<Path> files;
-			FileSystem::getChildren(DefaultShaderFolderRaw, files, directories);
-
-			// Process includes first since shaders reference them
-			for (auto& shaderFile : files)
-			{
-				if (shaderFile.getExtension() != ".bslinc")
-					continue;
-
-				HResource resource = Importer::instance().import(shaderFile);
-
-				if (resource != nullptr)
-				{
-					if (rtti_is_of_type<ShaderInclude>(resource.getInternalPtr()))
-					{
-						Path outputLoc = DefaultShaderFolder;
-						outputLoc.append(shaderFile.getWFilename() + L".asset");
-
-						Resources::instance().save(resource, outputLoc, true);
-					}
-				}
-			}
-
-			for (auto& shaderFile : files)
-			{
-				if (shaderFile.getExtension() != ".bsl")
-					continue;
-
-				HResource resource = Importer::instance().import(shaderFile);
-
-				if (resource != nullptr)
-				{
-					if (rtti_is_of_type<Shader>(resource.getInternalPtr()))
-					{
-						Path outputLoc = DefaultShaderFolder;
-						outputLoc.append(shaderFile.getWFilename() + L".asset");
-
-						Resources::instance().save(resource, outputLoc, true);
-					}
-				}
-			}
-		}
+		skin->setStyle("RightAlignedLabel", rightAlignedLabelStyle);
 
-		Resources::instance().unloadAllUnused();
+		return skin;
 	}
 
 	HSpriteTexture BuiltinResources::getSkinTexture(const WString& name)
 	{
 		Path texturePath = FileSystem::getWorkingDirectoryPath();
-		texturePath.append(DefaultSkinFolder);
+		texturePath.append(EngineSkinFolder);
 		texturePath.append(L"sprite_" + name + L".asset");
 
 		return Resources::instance().load<SpriteTexture>(texturePath);
@@ -739,7 +692,7 @@ namespace BansheeEngine
 
 	HShader BuiltinResources::getShader(const WString& name)
 	{
-		Path programPath = DefaultShaderFolder;
+		Path programPath = EngineShaderFolder;
 		programPath.append(name + L".asset");
 
 		return gResources().load<Shader>(programPath);
@@ -748,45 +701,12 @@ namespace BansheeEngine
 	HTexture BuiltinResources::getCursorTexture(const WString& name)
 	{
 		Path cursorPath = FileSystem::getWorkingDirectoryPath();
-		cursorPath.append(DefaultCursorFolder);
+		cursorPath.append(EngineCursorFolder);
 		cursorPath.append(name + L".asset");
 
 		return Resources::instance().load<Texture>(cursorPath);
 	}
 
-	void BuiltinResources::importSkinTexture(const WString& name)
-	{
-		Path texturePath = FileSystem::getWorkingDirectoryPath();
-		texturePath.append(DefaultSkinFolderRaw);
-		texturePath.append(name);
-
-		Path texOutputPath = FileSystem::getWorkingDirectoryPath();
-		texOutputPath.append(DefaultSkinFolder);
-		Path spriteTexOutputPath = texOutputPath;
-		texOutputPath.append(name + L".asset");
-		spriteTexOutputPath.append(L"sprite_" + name + L".asset");
-
-		HTexture tex = Importer::instance().import<Texture>(texturePath);
-		Resources::instance().save(tex, texOutputPath, true);
-
-		HSpriteTexture spriteTex = SpriteTexture::create(tex);
-		Resources::instance().save(spriteTex, spriteTexOutputPath, true);
-	}
-
-	void BuiltinResources::importCursorTexture(const WString& name)
-	{
-		Path inputPath = FileSystem::getWorkingDirectoryPath();
-		inputPath.append(DefaultCursorFolderRaw);
-		inputPath.append(name);
-
-		Path ouputPath = FileSystem::getWorkingDirectoryPath();
-		ouputPath.append(DefaultCursorFolder);
-		ouputPath.append(name + L".asset");
-
-		HTexture tex = Importer::instance().import<Texture>(inputPath);
-		Resources::instance().save(tex, ouputPath, true);
-	}
-	
 	const PixelData& BuiltinResources::getCursorArrow(Vector2I& hotSpot)
 	{
 		hotSpot = CursorArrowHotspot;
@@ -893,4 +813,136 @@ namespace BansheeEngine
 	{
 		return Material::create(mShaderDummy);
 	}
+
+	void BuiltinResourcesHelper::importAssets(const Path& inputFolder, const Path& outputFolder, const ResourceManifestPtr& manifest)
+	{
+		if (!FileSystem::exists(inputFolder))
+			return;
+
+		auto importResource = [&](const Path& filePath)
+		{
+			Path relativePath = filePath.getRelative(inputFolder);
+			Path outputPath = FileSystem::getWorkingDirectoryPath() + outputFolder + relativePath;
+			outputPath.setFilename(outputPath.getWFilename() + L".asset");
+
+			HResource resource = Importer::instance().import(filePath);
+			if (resource != nullptr)
+			{
+				Resources::instance().save(resource, outputPath, true);
+				manifest->registerResource(resource.getUUID(), outputPath);
+			}
+
+			return true;
+		};
+
+		FileSystem::iterate(inputFolder, importResource);
+	}
+
+	void BuiltinResourcesHelper::importFont(const Path& inputFile, const Path& outputFolder, 
+		UINT32 size, bool antialiasing, const ResourceManifestPtr& manifest)
+	{
+		ImportOptionsPtr fontImportOptions = Importer::instance().createImportOptions(inputFile);
+		if (rtti_is_of_type<FontImportOptions>(fontImportOptions))
+		{
+			FontImportOptions* importOptions = static_cast<FontImportOptions*>(fontImportOptions.get());
+
+			Vector<UINT32> fontSizes;
+			fontSizes.push_back(size);
+			importOptions->setFontSizes(fontSizes);
+			importOptions->setAntialiasing(antialiasing);
+		}
+		else
+			return;
+
+		HFont font = Importer::instance().import<Font>(inputFile, fontImportOptions);
+
+		WString fontName = inputFile.getWFilename();
+		Path outputPath = FileSystem::getWorkingDirectoryPath() + outputFolder + fontName;
+		outputPath.setFilename(outputPath.getWFilename() + L".asset");
+
+		Resources::instance().save(font, outputPath, true);
+		manifest->registerResource(font.getUUID(), outputPath);
+
+		// Save font texture pages as well. TODO - Later maybe figure out a more automatic way to do this
+		const FontData* fontData = font->getFontDataForSize(size);
+
+		Path texPageOutputPath = FileSystem::getWorkingDirectoryPath() + outputFolder;
+
+		UINT32 pageIdx = 0;
+		for (auto tex : fontData->texturePages)
+		{
+			texPageOutputPath.setFilename(fontName + L"_texpage_" + toWString(pageIdx) + L".asset");
+			Resources::instance().save(tex, texPageOutputPath, true);
+			manifest->registerResource(tex.getUUID(), texPageOutputPath);
+		}
+	}
+
+	void BuiltinResourcesHelper::generateSpriteTextures(const Path& folder, const ResourceManifestPtr& manifest)
+	{
+		if (!FileSystem::exists(folder))
+			return;
+
+		Vector<Path> filesToProcess;
+		auto gather = [&](const Path& filePath)
+		{
+			filesToProcess.push_back(filePath);
+
+			return true;
+		};
+
+		FileSystem::iterate(folder, gather);
+
+		for (auto& filePath : filesToProcess)
+		{
+			Path outputPath = FileSystem::getWorkingDirectoryPath() + filePath;
+			outputPath.setFilename(L"sprite_" + outputPath.getWFilename());
+
+			HTexture source = gResources().load<Texture>(filePath);
+
+			if (source != nullptr)
+			{
+				HSpriteTexture spriteTex = SpriteTexture::create(source);
+				Resources::instance().save(spriteTex, outputPath, true);
+				manifest->registerResource(spriteTex.getUUID(), outputPath);
+			}
+		}
+	}
+
+	void BuiltinResourcesHelper::writeTimestamp(const Path& file)
+	{
+		DataStreamPtr fileStream = FileSystem::createAndOpenFile(file);
+
+		time_t currentTime = std::time(nullptr);
+		fileStream->write(&currentTime, sizeof(currentTime));
+		fileStream->close();
+	}
+
+	bool BuiltinResourcesHelper::checkForModifications(const Path& folder, const Path& timeStampFile)
+	{
+		if (!FileSystem::exists(timeStampFile))
+			return true;
+
+		DataStreamPtr fileStream = FileSystem::openFile(timeStampFile);
+		time_t lastUpdateTime = 0;
+		fileStream->read(&lastUpdateTime, sizeof(lastUpdateTime));
+		fileStream->close();
+
+		bool upToDate = true;
+		auto checkUpToDate = [&](const Path& filePath)
+		{
+			time_t fileLastModified = FileSystem::getLastModifiedTime(filePath);
+
+			if (fileLastModified > lastUpdateTime)
+			{
+				upToDate = false;
+				return false;
+			}
+
+			return true;
+		};
+
+		FileSystem::iterate(folder, checkUpToDate);
+
+		return !upToDate;
+	}
 }

+ 17 - 0
BansheeUtility/Include/BsFileSystem.h

@@ -101,6 +101,23 @@ namespace BansheeEngine
 		 */
 		static void getChildren(const Path& dirPath, Vector<Path>& files, Vector<Path>& directories);
 
+		/**
+		 * @brief	Iterates over all files and directories in the specified folder and calls the provided callback
+		 *			when a file/folder is iterated over.
+		 *
+		 * @param	dirPath			Directory over which to iterate
+		 * @param	fileCallback	Callback to call whenever a file is found. If callback returns false iteration stops. Can be null.
+		 * @param	dirCallback		Callback to call whenever a directory is found. If callback returns false iteration stops. Can be null.
+		 * @param	recursive		If false then only the direct children of the provided folder
+		 *							will be iterated over, and if true then child directories will
+		 *							be recursively visited as well.
+		 *
+		 * @returns	True if iteration finished iterating over all files/folders, or false if it was interrupted
+		 *			by a callback returning false.
+		 */
+		static bool iterate(const Path& dirPath, std::function<bool(const Path&)> fileCallback,
+			std::function<bool(const Path&)> dirCallback = nullptr, bool recursive = true);
+
 		/**
 		 * @brief	Returns the last modified time of a file or a folder at the specified path.
 		 *

+ 32 - 17
BansheeUtility/Include/BsPath.h

@@ -341,8 +341,8 @@ namespace BansheeEngine
 		const WString& getWDirectory(UINT32 idx) const;
 
 		/**
-		* @brief	Gets a directory name with the specified index from the path.
-		*/
+		 * @brief	Gets a directory name with the specified index from the path.
+		 */
 		String getDirectory(UINT32 idx) const;
 
 		/**
@@ -351,28 +351,28 @@ namespace BansheeEngine
 		const WString& getWDevice() const { return mDevice; }
 
 		/**
-		* @brief	Returns path device (e.g. drive, volume, etc.) if one exists in the path.
-		*/
+		 * @brief	Returns path device (e.g. drive, volume, etc.) if one exists in the path.
+		 */
 		String getDevice() const { return BansheeEngine::toString(mDevice); }
 
 		/**
-		* @brief	Returns path node (e.g. network name) if one exists in the path.
-		*/
+		 * @brief	Returns path node (e.g. network name) if one exists in the path.
+		 */
 		const WString& getWNode() const { return mNode; }
 
 		/**
-		* @brief	Returns path node (e.g. network name) if one exists in the path.
-		*/
+		 * @brief	Returns path node (e.g. network name) if one exists in the path.
+		 */
 		String getNode() const { return BansheeEngine::toString(mNode); }
 
 		/**
-		* @brief	Gets last element in the path, filename if it exists, otherwise the last directory.
-		*			If no directories exist returns device or node.
-		*
-		* @param	type	Determines format of node or device, in case they are returned. When default,
-		*					format for the active platform will be used, otherwise the format defined
-		*					by the parameter will be used.
-		*/
+		 * @brief	Gets last element in the path, filename if it exists, otherwise the last directory.
+		 *			If no directories exist returns device or node.
+		 *
+		 * @param	type	Determines format of node or device, in case they are returned. When default,
+		 *					format for the active platform will be used, otherwise the format defined
+		 *					by the parameter will be used.
+		 */
 		WString getWTail(PathType type = PathType::Default) const;
 
 		/**
@@ -396,10 +396,25 @@ namespace BansheeEngine
 		bool isEmpty() const { return mDirectories.empty() && mFilename.empty() && mDevice.empty() && mNode.empty(); }
 
 		/**
-		* @brief	Compares two path elements (i.e. filenames, directory names, etc.)
-		*/
+		 * @brief	Concatenates two paths.
+		 */
+		Path operator+ (const Path& rhs) const;
+
+		/**
+		 * @brief	Concatenates two paths.
+		 */
+		Path& operator+= (const Path& rhs);
+
+		/**
+		 * @brief	Compares two path elements (i.e. filenames, directory names, etc.)
+		 */
 		static bool comparePathElem(const WString& left, const WString& right);
 
+		/**
+		 * @brief	Combines two paths and returns the result. Right path should be relative.
+		 */
+		static Path combine(const Path& left, const Path& right);
+
 		static const Path BLANK;
 	private:
 		/**

+ 17 - 0
BansheeUtility/Source/BsPath.cpp

@@ -255,6 +255,7 @@ namespace BansheeEngine
 		for (auto& dir : mDirectories)
 			absDir.pushDirectory(dir);
 
+		absDir.setFilename(mFilename);
 		*this = absDir;
 
 		return *this;
@@ -512,6 +513,16 @@ namespace BansheeEngine
 		return result.str();
 	}
 
+	Path Path::operator+ (const Path& rhs) const
+	{
+		return Path::combine(*this, rhs);
+	}
+
+	Path& Path::operator+= (const Path& rhs)
+	{
+		return append(rhs);
+	}
+
 	bool Path::comparePathElem(const WString& left, const WString& right)
 	{
 		if (left.size() != right.size())
@@ -527,6 +538,12 @@ namespace BansheeEngine
 		return true;
 	}
 
+	Path Path::combine(const Path& left, const Path& right)
+	{
+		Path output = left;
+		return output.append(right);
+	}
+
 	void Path::pushDirectory(const WString& dir)
 	{
 		if (!dir.empty() && dir != L".")

+ 73 - 0
BansheeUtility/Source/Win32/BsFileSystem.cpp

@@ -483,6 +483,79 @@ namespace BansheeEngine
 		FindClose(fileHandle);
 	}
 
+	bool FileSystem::iterate(const Path& dirPath, std::function<bool(const Path&)> fileCallback,
+		std::function<bool(const Path&)> dirCallback, bool recursive)
+	{
+		if (dirPath.isFile())
+			return true;
+
+		WString findPath = dirPath.toWString();
+		findPath.append(L"*");
+
+		WIN32_FIND_DATAW findData;
+		HANDLE fileHandle = FindFirstFileW(findPath.c_str(), &findData);
+
+		bool lastFailed = false;
+		WString tempName;
+		do
+		{
+			if (lastFailed || fileHandle == INVALID_HANDLE_VALUE)
+			{
+				if (GetLastError() == ERROR_NO_MORE_FILES)
+					break;
+				else
+					win32_handleError(GetLastError(), findPath);
+			}
+			else
+			{
+				tempName = findData.cFileName;
+
+				if (tempName != L"." && tempName != L"..")
+				{
+					Path fullPath = dirPath;
+					if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
+					{
+						Path childDir = fullPath.append(tempName + L"/");
+						if (dirCallback != nullptr)
+						{
+							if (!dirCallback(childDir))
+							{
+								FindClose(fileHandle);
+								return false;
+							}
+						}
+
+						if (recursive)
+						{
+							if (!iterate(childDir, fileCallback, dirCallback, recursive))
+							{
+								FindClose(fileHandle);
+								return false;
+							}
+						}
+					}
+					else
+					{
+						Path filePath = fullPath.append(tempName);
+						if (fileCallback != nullptr)
+						{
+							if (!fileCallback(filePath))
+							{
+								FindClose(fileHandle);
+								return false;
+							}
+						}
+					}
+				}
+			}
+
+			lastFailed = FindNextFileW(fileHandle, &findData) == FALSE;
+		} while (true);
+
+		FindClose(fileHandle);
+		return true;
+	}
+
 	std::time_t FileSystem::getLastModifiedTime(const Path& fullPath)
 	{
 		return win32_getLastModifiedTime(fullPath.toWString().c_str());

+ 1 - 0
MBansheeEditor/MBansheeEditor.csproj

@@ -55,6 +55,7 @@
     <Compile Include="DialogBox.cs" />
     <Compile Include="DragDrop.cs" />
     <Compile Include="EditorApplication.cs" />
+    <Compile Include="EditorBuiltin.cs" />
     <Compile Include="EditorSettings.cs" />
     <Compile Include="EditorStyles.cs" />
     <Compile Include="EditorUtility.cs" />

+ 15 - 0
MBansheeEngine/Builtin.cs

@@ -0,0 +1,15 @@
+using System.Runtime.CompilerServices;
+
+namespace BansheeEngine
+{
+    public static class Builtin
+    {
+        public static SpriteTexture WhiteTexture
+        {
+            get { return Internal_GetWhiteTexture(); }
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern SpriteTexture Internal_GetWhiteTexture();
+    }
+}

+ 0 - 16
MBansheeEngine/BuiltinResources.cs

@@ -1,16 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace BansheeEngine
-{
-    class BuiltinResources
-    {
-        public Resource Load<T>(string path) where T : Resource, new()
-        {
-            // TODO -Dummy only
-            return new T();
-        }
-    }
-}

+ 1 - 1
MBansheeEngine/MBansheeEngine.csproj

@@ -43,7 +43,7 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="AsyncOp.cs" />
-    <Compile Include="BuiltinResources.cs" />
+    <Compile Include="Builtin.cs" />
     <Compile Include="Camera.cs" />
     <Compile Include="CameraHandler.cs" />
     <Compile Include="Cursor.cs" />

+ 21 - 0
SBansheeEditor/Include/BsScriptEditorBuiltin.h

@@ -0,0 +1,21 @@
+#pragma once
+
+#include "BsScriptEditorPrerequisites.h"
+#include "BsScriptObject.h"
+
+namespace BansheeEngine
+{
+	class BS_SCR_BED_EXPORT ScriptEditorBuiltin : public ScriptObject <ScriptEditorBuiltin>
+	{
+	public:
+		SCRIPT_OBJ(EDITOR_ASSEMBLY, "BansheeEditor", "EditorBuiltin")
+
+	private:
+		static MonoObject* internal_getFolderIcon();
+		static MonoObject* internal_getMeshIcon();
+		static MonoObject* internal_getFontIcon();
+		static MonoObject* internal_getTextureIcon();
+
+		ScriptEditorBuiltin(MonoObject* instance);
+	};
+}

+ 2 - 0
SBansheeEditor/SBansheeEditor.vcxproj

@@ -242,6 +242,7 @@
     <ClInclude Include="Include\BsScriptCodeEditor.h" />
     <ClInclude Include="Include\BsScriptDragDropManager.h" />
     <ClInclude Include="Include\BsScriptEditorApplication.h" />
+    <ClInclude Include="Include\BsScriptEditorBuiltin.h" />
     <ClInclude Include="Include\BsScriptEditorPrerequisites.h" />
     <ClInclude Include="Include\BsScriptEditorSettings.h" />
     <ClInclude Include="Include\BsScriptEditorUtility.h" />
@@ -286,6 +287,7 @@
     <ClCompile Include="Source\BsGUIResourceField.cpp" />
     <ClCompile Include="Source\BsScriptBrowseDialog.cpp" />
     <ClCompile Include="Source\BsScriptEditorApplication.cpp" />
+    <ClCompile Include="Source\BsScriptEditorBuiltin.cpp" />
     <ClCompile Include="Source\BsScriptEditorPlugin.cpp" />
     <ClCompile Include="Source\BsScriptEditorSettings.cpp" />
     <ClCompile Include="Source\BsScriptEditorUtility.cpp" />

+ 6 - 0
SBansheeEditor/SBansheeEditor.vcxproj.filters

@@ -141,6 +141,9 @@
     <ClInclude Include="Include\BsMenuItemManager.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsScriptEditorBuiltin.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsScriptEditorPlugin.cpp">
@@ -269,5 +272,8 @@
     <ClCompile Include="Source\BsMenuItemManager.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsScriptEditorBuiltin.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 51 - 0
SBansheeEditor/Source/BsScriptEditorBuiltin.cpp

@@ -0,0 +1,51 @@
+#include "BsScriptEditorBuiltin.h"
+#include "BsMonoManager.h"
+#include "BsMonoClass.h"
+#include "BsMonoMethod.h"
+#include "BsMonoUtil.h"
+#include "BsBuiltinEditorResources.h"
+#include "BsScriptSpriteTexture.h"
+#include "BsScriptResourceManager.h"
+
+namespace BansheeEngine
+{
+	ScriptEditorBuiltin::ScriptEditorBuiltin(MonoObject* instance)
+		:ScriptObject(instance)
+	{ }
+
+	void ScriptEditorBuiltin::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_GetFolderIcon", &ScriptEditorBuiltin::internal_getFolderIcon);
+		metaData.scriptClass->addInternalCall("Internal_GetMeshIcon", &ScriptEditorBuiltin::internal_getMeshIcon);
+		metaData.scriptClass->addInternalCall("Internal_GetFontIcon", &ScriptEditorBuiltin::internal_getFontIcon);
+		metaData.scriptClass->addInternalCall("Internal_GetTextureIcon", &ScriptEditorBuiltin::internal_getTextureIcon);
+	}
+
+	MonoObject* ScriptEditorBuiltin::internal_getFolderIcon()
+	{
+		HSpriteTexture tex = HSpriteTexture(); // TODO - Get actual texture
+
+		return ScriptSpriteTexture::toManaged(tex);
+	}
+
+	MonoObject* ScriptEditorBuiltin::internal_getMeshIcon()
+	{
+		HSpriteTexture tex = HSpriteTexture(); // TODO - Get actual texture
+
+		return ScriptSpriteTexture::toManaged(tex);
+	}
+
+	MonoObject* ScriptEditorBuiltin::internal_getFontIcon()
+	{
+		HSpriteTexture tex = HSpriteTexture(); // TODO - Get actual texture
+
+		return ScriptSpriteTexture::toManaged(tex);
+	}
+
+	MonoObject* ScriptEditorBuiltin::internal_getTextureIcon()
+	{
+		HSpriteTexture tex = HSpriteTexture(); // TODO - Get actual texture
+
+		return ScriptSpriteTexture::toManaged(tex);
+	}
+}

+ 18 - 0
SBansheeEngine/Include/BsScriptBuiltin.h

@@ -0,0 +1,18 @@
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "BsScriptObject.h"
+
+namespace BansheeEngine
+{
+	class BS_SCR_BE_EXPORT ScriptBuiltin : public ScriptObject <ScriptBuiltin>
+	{
+	public:
+		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "Builtin")
+
+	private:
+		static MonoObject* internal_getWhiteTexture();
+		
+		ScriptBuiltin(MonoObject* instance);
+	};
+}

+ 2 - 0
SBansheeEngine/Include/BsScriptSpriteTexture.h

@@ -16,6 +16,8 @@ namespace BansheeEngine
 		HResource getNativeHandle() const { return mTexture; }
 		void setNativeHandle(const HResource& resource);
 
+		static MonoObject* toManaged(const HSpriteTexture& texture);
+
 	private:
 		friend class ScriptResourceManager;
 

+ 2 - 0
SBansheeEngine/SBansheeEngine.vcxproj

@@ -252,6 +252,7 @@
     <ClInclude Include="Include\BsManagedSerializableObjectDataRTTI.h" />
     <ClInclude Include="Include\BsScriptAssemblyManager.h" />
     <ClInclude Include="Include\BsScriptAsyncOp.h" />
+    <ClInclude Include="Include\BsScriptBuiltin.h" />
     <ClInclude Include="Include\BsScriptCameraHandler.h" />
     <ClInclude Include="Include\BsScriptColor.h" />
     <ClInclude Include="Include\BsScriptComponent.h" />
@@ -328,6 +329,7 @@
     <ClCompile Include="Source\BsManagedSerializableObjectData.cpp" />
     <ClCompile Include="Source\BsScriptAssemblyManager.cpp" />
     <ClCompile Include="Source\BsScriptAsyncOp.cpp" />
+    <ClCompile Include="Source\BsScriptBuiltin.cpp" />
     <ClCompile Include="Source\BsScriptCameraHandler.cpp" />
     <ClCompile Include="Source\BsScriptColor.cpp" />
     <ClCompile Include="Source\BsScriptComponent.cpp" />

+ 6 - 0
SBansheeEngine/SBansheeEngine.vcxproj.filters

@@ -294,6 +294,9 @@
     <ClInclude Include="Include\BsScriptScriptCode.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsScriptBuiltin.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsScriptTexture2D.cpp">
@@ -524,5 +527,8 @@
     <ClCompile Include="Source\BsScriptScriptCode.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsScriptBuiltin.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 31 - 0
SBansheeEngine/Source/BsScriptBuiltin.cpp

@@ -0,0 +1,31 @@
+#include "BsScriptBuiltin.h"
+#include "BsMonoManager.h"
+#include "BsMonoClass.h"
+#include "BsMonoMethod.h"
+#include "BsMonoUtil.h"
+#include "BsBuiltinResources.h"
+#include "BsScriptSpriteTexture.h"
+#include "BsScriptResourceManager.h"
+
+namespace BansheeEngine
+{
+	ScriptBuiltin::ScriptBuiltin(MonoObject* instance)
+		:ScriptObject(instance)
+	{ }
+
+	void ScriptBuiltin::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_GetWhiteTexture", &ScriptBuiltin::internal_getWhiteTexture);
+	}
+
+	MonoObject* ScriptBuiltin::internal_getWhiteTexture()
+	{
+		HSpriteTexture whiteTexture = BuiltinResources::instance().getWhiteSpriteTexture();
+
+		ScriptSpriteTexture* scriptSpriteTex = ScriptResourceManager::instance().getScriptSpriteTexture(whiteTexture);
+		if (scriptSpriteTex == nullptr)
+			scriptSpriteTex = ScriptResourceManager::instance().createScriptSpriteTexture(whiteTexture);
+
+		return scriptSpriteTex->getManagedInstance();
+	}
+}

+ 12 - 0
SBansheeEngine/Source/BsScriptSpriteTexture.cpp

@@ -48,4 +48,16 @@ namespace BansheeEngine
 	{ 
 		mTexture = static_resource_cast<SpriteTexture>(resource);
 	}
+
+	MonoObject* ScriptSpriteTexture::toManaged(const HSpriteTexture& texture)
+	{
+		if (texture == nullptr)
+			return nullptr;
+
+		ScriptSpriteTexture* scriptSpriteTex = ScriptResourceManager::instance().getScriptSpriteTexture(texture);
+		if (scriptSpriteTex == nullptr)
+			scriptSpriteTex = ScriptResourceManager::instance().createScriptSpriteTexture(texture);
+
+		return scriptSpriteTex->getManagedInstance();
+	}
 }

+ 0 - 27
TODO.txt

@@ -11,35 +11,9 @@ Project library
 
 Almost all of PRojectLibrary functionality is completely untested
 
-Figure out how to create a C# BuiltinResources class. It should be able to load arbitrary resources from a non-project folder
- - I should move all the GUI element style creation out of code and make it just pure data (once I have an editor for it)
- - Will also need a debug button to reimport all the built-in resources
-
 My GUID generation is screwed up. If multiple GUIDs are generated in succession then the timestamp will remain
 the same and the only variable will be the 4byte random number, which can sometimes end up identical to the previous number.
 
-----------------------------------------------------------------------
-BuiltinResources
- - All data in ..\..\BuiltinData (if we start in /bin/Release/BansheeEd.exe)
- - Need BuiltinEngine and BuiltinEditor (separate classes) that internally do pretty much the same thing
-   - Derive them from common base since most of the functionality will be reused
-   - Make sure that commonly used resources are available directly and aren't required to call Load
- - Also have ..\..\RawBuiltinData where all the non-processed assets are
- - When compiled as debug, define Preprocess command which goes over all assets in ..\..\RawBuiltinData, imports them and outputs them to ..\..\BuiltinData
-   - Preprocess can be done fully in C++
-
-I need to make a GUISkin a resource so I can save it
- - It should be editable from the Editor (only when in debug mode) and not generated in code
- - Then in Preprocess it can just get copied from RawBuiltinData subfolder to the actual folder
- - Before I have editing capability it can just be generated in Preprocess step
-
-Preprocess will also need to generate any Shaders or SpriteTextures
- - POSSIBLY wait until I get generate these assets directly in Editor, then just copy them over to Builtin
- - This way I can fully avoid writing any preprocess code
-
-I still need to be able to access most of these assets from C++ (e.g. GUI element styles)
- - I need to add BuiltinResources.Load which should allow me to load all needed resources, from C++ or C#
-
 ----------------------------------------------------------------------
 Resources
  - Load/Unload/UnloadUnused
@@ -74,7 +48,6 @@ Other simple stuff:
  - Call stack from C# to use in Debug.Log calls
  - Get rid of event callback from HString and figure out a better way
  - GUI TextureField similar to ResourceField but it displays the texture it has assigned
- - Getting rid of import on start would be a pretty big deal. Just adding a button in Editor "Reimport" should be good instead
  - Better handle and gizmo shaders
 
 ----------------------------------------------------------------------