Browse Source

Bulk of work on the build system
Allow application to be started without importers
Add debug option to platform info

BearishSun 10 years ago
parent
commit
06e03f1239
34 changed files with 772 additions and 68 deletions
  1. 1 1
      BansheeCore/Include/BsCoreApplication.h
  2. 3 4
      BansheeCore/Include/BsCoreThread.h
  3. 6 1
      BansheeCore/Include/BsCoreThreadAccessor.h
  4. 9 0
      BansheeCore/Include/BsPrefab.h
  5. 1 1
      BansheeCore/Include/BsResourceManifest.h
  6. 10 0
      BansheeCore/Include/BsResources.h
  7. 1 1
      BansheeCore/Source/BsCoreApplication.cpp
  8. 11 6
      BansheeCore/Source/BsPrefab.cpp
  9. 12 0
      BansheeCore/Source/BsResources.cpp
  10. 27 3
      BansheeEditor/Include/BsBuildManager.h
  11. 1 0
      BansheeEditor/Include/BsPlatformInfo.h
  12. 4 0
      BansheeEditor/Include/BsPlatformInfoRTTI.h
  13. 7 0
      BansheeEditor/Include/BsProjectLibrary.h
  14. 68 2
      BansheeEditor/Source/BsBuildManager.cpp
  15. 13 1
      BansheeEditor/Source/BsEditorApplication.cpp
  16. 1 1
      BansheeEditor/Source/BsProjectLibrary.cpp
  17. 4 9
      BansheeEngine/Include/BsApplication.h
  18. 1 3
      BansheeEngine/Include/BsBuiltinResources.h
  19. 6 2
      BansheeEngine/Include/BsPrerequisites.h
  20. 10 16
      BansheeEngine/Source/BsApplication.cpp
  21. 3 3
      BansheeEngine/Source/BsBuiltinResources.cpp
  22. 8 1
      BansheeMono/Include/BsMonoManager.h
  23. 5 3
      BansheeMono/Source/BsMonoManager.cpp
  24. 6 0
      Dependencies.txt
  25. 8 1
      ExampleProject/Main/Main.cpp
  26. 2 3
      Game/Source/Main.cpp
  27. 211 5
      MBansheeEditor/BuildManager.cs
  28. 19 0
      SBansheeEditor/Include/BsScriptBuildManager.h
  29. 1 0
      SBansheeEditor/Include/BsScriptEditorPrerequisites.h
  30. 2 0
      SBansheeEditor/Include/BsScriptPlatformInfo.h
  31. 296 0
      SBansheeEditor/Source/BsScriptBuildManager.cpp
  32. 2 0
      SBansheeEditor/Source/BsScriptEditorApplication.cpp
  33. 12 0
      SBansheeEditor/Source/BsScriptPlatformInfo.cpp
  34. 1 1
      TODO.txt

+ 1 - 1
BansheeCore/Include/BsCoreApplication.h

@@ -33,7 +33,7 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT CoreApplication : public Module<CoreApplication>
 	{
 		public:
-			CoreApplication(START_UP_DESC& desc);
+			CoreApplication(START_UP_DESC desc);
 			virtual ~CoreApplication();
 
 			/**

+ 3 - 4
BansheeCore/Include/BsCoreThread.h

@@ -15,12 +15,11 @@ namespace BansheeEngine
 	 * @note	How threading works:
 	 * 			 - This class contains a queue which is filled by commands from other threads via queueCommand and queueReturnCommand  
 	 * 			 - Commands are executed on the core thread as soon as they are queued (if core thread is not busy with previous commands)  
-	 * 			 - Core thread accessors are helpers for queuing commands. They serve two purposes:  
-	 * 				- They contain helper methods for various common Core thread commands.
-	 * 				- They perform better than queuing each command directly using queueCommand or queueReturnCommand    
+	 * 			 - Core thread accessors are helpers for queuing commands. They perform better than queuing each command directly using 
+	 *			   queueCommand or queueReturnCommand.
 	 * 			 - Accessors contain a command queue of their own, and queuing commands in them will not automatically start executing the commands  
 	 * 			   like with queueCommand or queueReturnCommand. Instead you must manually call "submitAccessors" when you are ready to send their
-	 * 			   commands to the core thread.
+	 * 			   commands to the core thread. Sending commands "in bulk" like this is what makes them faster than directly queuing commands.
 	 * 			 - Synced accessor is a special type of accessor which may be accessed from any thread. Its commands are always executed after all other  
 	 * 			   non-synced accessors. It is primarily useful when multiple threads are managing the same resource and you must ensure proper order of operations.
 	 * 			   You should use normal accessors whenever possible as synced accessors involve potentially slow synchronization operations.

+ 6 - 1
BansheeCore/Include/BsCoreThreadAccessor.h

@@ -21,7 +21,8 @@ namespace BansheeEngine
 		virtual ~CoreThreadAccessorBase();
 
 		/**
-		* @brief	Queues a new generic command that will be added to the command queue.
+		* @brief	Queues a new generic command that will be added to the command queue. Returns an async operation object
+		*			that you may use to check if the operation has finished, and to retrieve the return value once finished.
 		*/
 		AsyncOp queueReturnCommand(std::function<void(AsyncOp&)> commandCallback);
 
@@ -33,6 +34,10 @@ namespace BansheeEngine
 		/**
 		 * @brief	Makes all the currently queued commands available to the core thread. They will be executed
 		 * 			as soon as the core thread is ready. All queued commands are removed from the accessor.
+		 *
+		 * @param	blockUntilComplete	If true, the calling thread will block until the core thread finished executing
+		 *								all currently queued commands. This is usually very expensive and should only be
+		 *								used in performance non-critical code.
 		 */
 		void submitToCoreThread(bool blockUntilComplete = false);
 

+ 9 - 0
BansheeCore/Include/BsPrefab.h

@@ -40,6 +40,13 @@ namespace BansheeEngine
 		 */
 		void update(const HSceneObject& sceneObject);
 
+		/**
+		 * @brief	Updates any prefab child instances by loading their prefabs and making sure they are up to date.
+		 * 
+		 * @note	Internal method.
+		 */
+		void _updateChildInstances();
+
 		/**
 		 * @brief	Returns a reference to the internal prefab hierarchy. Returned hierarchy is not instantiated and cannot
 		 *			be interacted with in a manner you would with normal scene objects.
@@ -52,6 +59,8 @@ namespace BansheeEngine
 		 * @brief	Creates the clone of the prefab's current hierarchy but doesn't instantiate it.
 		 *			
 		 * @returns	Clone of the prefab's scene object hierarchy.
+		 *
+		 * @note	Internal method.
 		 */
 		HSceneObject _clone();
 

+ 1 - 1
BansheeCore/Include/BsResourceManifest.h

@@ -101,6 +101,6 @@ namespace BansheeEngine
 	public:
 		friend class ResourceManifestRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 }

+ 10 - 0
BansheeCore/Include/BsResources.h

@@ -130,6 +130,16 @@ namespace BansheeEngine
 		 */
 		void update(HResource& handle, const ResourcePtr& resource);
 
+		/**
+		 * @brief	Returns a list of dependencies from the resources at the specified path. Resource will not be loaded
+		 *			or parsed, but instead the saved list of dependencies will be read from the file and returned.
+		 *
+		 * @param	filePath	Full path to the resource to get dependencies for.
+		 *
+		 * @returns	List of dependencies represented as UUIDs.
+		 */
+		Vector<String> getDependencies(const Path& filePath);
+
 		/**
 		 * @brief	Checks is the resource with the specified UUID loaded.
 		 *

+ 1 - 1
BansheeCore/Source/BsCoreApplication.cpp

@@ -50,7 +50,7 @@
 
 namespace BansheeEngine
 {
-	CoreApplication::CoreApplication(START_UP_DESC& desc)
+	CoreApplication::CoreApplication(START_UP_DESC desc)
 		:mPrimaryWindow(nullptr), mIsFrameRenderingFinished(true), mRunMainLoop(false), 
 		mRendererPlugin(nullptr), mSimThreadId(BS_THREAD_CURRENT_ID), mStartUpDesc(desc)
 	{ }

+ 11 - 6
BansheeCore/Source/BsPrefab.cpp

@@ -108,13 +108,8 @@ namespace BansheeEngine
 		mHash++;
 	}
 
-	HSceneObject Prefab::instantiate()
+	void Prefab::_updateChildInstances()
 	{
-		if (mRoot == nullptr)
-			return HSceneObject();
-
-#if BS_EDITOR_BUILD
-		// Update any child prefab instances in case their prefabs changed
 		Stack<HSceneObject> todo;
 		todo.push(mRoot);
 
@@ -134,6 +129,16 @@ namespace BansheeEngine
 					todo.push(child);
 			}
 		}
+	}
+
+	HSceneObject Prefab::instantiate()
+	{
+		if (mRoot == nullptr)
+			return HSceneObject();
+
+#if BS_EDITOR_BUILD
+		// Update any child prefab instances in case their prefabs changed
+		_updateChildInstances();
 #endif
 
 		HSceneObject clone = _clone();

+ 12 - 0
BansheeCore/Source/BsResources.cpp

@@ -403,6 +403,18 @@ namespace BansheeEngine
 		onResourceModified(handle);
 	}
 
+	Vector<String> Resources::getDependencies(const Path& filePath)
+	{
+		SPtr<SavedResourceData> savedResourceData;
+		if (!filePath.isEmpty())
+		{
+			FileDecoder fs(filePath);
+			savedResourceData = std::static_pointer_cast<SavedResourceData>(fs.decode());
+		}
+
+		return savedResourceData->getDependencies();
+	}
+
 	void Resources::registerResourceManifest(const ResourceManifestPtr& manifest)
 	{
 		if(manifest->getName() == "Default")

+ 27 - 3
BansheeEditor/Include/BsBuildManager.h

@@ -28,6 +28,18 @@ namespace BansheeEngine
 		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Types of various folders used by the build manager.
+	 */
+	enum class BuildFolder
+	{
+		SourceRoot, /**< Absolute path to the root folder where all the prebuilt binaries and data exist. */
+		DestinationRoot, /**< Absolute path to the root folder for a build for a specific platform. */
+		NativeBinaries, /**< Folder where native binaries are stored. Relative to root. */
+		BansheeAssemblies, /**< Folder where Banshee specific assemblies are stored. Relative to root. */
+		Data /**< Folder where builtin data is stored. Relative to root. */
+	};
+
 	/**
 	 * @brief	Handles building of the game executable and related files.
 	 */
@@ -62,13 +74,23 @@ namespace BansheeEngine
 		SPtr<PlatformInfo> getPlatformInfo(PlatformType type) const;
 
 		/**
-		 * @brief	Returns a list of file names of all .NET assemblies 
-		 *			required for a specific platform.
+		 * @brief	Returns a list of file names (without extension) of all .NET assemblies required for a specific platform.
 		 */
 		Vector<WString> getFrameworkAssemblies(PlatformType type) const;
 
 		/**
-		 * @brief	Returns the location of the pre-built executable for the specified platform.
+		 * @brief	Returns a list names of all native binaries required for a specific platform.
+		 */
+		Vector<Path> getNativeBinaries(PlatformType type) const;
+
+		/**
+		 * @brief	Returns a path to a specific folder used in the build process. See entries of
+		 *			BuildFolder enum for explanations of individual folder types.
+		 */
+		Path getBuildFolder(BuildFolder folder, PlatformType platform) const;
+
+		/**
+		 * @brief	Returns the absolute path of the pre-built executable for the specified platform.
 		 */
 		Path getMainExecutable(PlatformType type) const;
 
@@ -93,6 +115,8 @@ namespace BansheeEngine
 		void clear();
 
 	private:
+		static const WString BUILD_FOLDER_NAME;
+
 		SPtr<BuildData> mBuildData;
 	};
 }

+ 1 - 0
BansheeEditor/Include/BsPlatformInfo.h

@@ -29,6 +29,7 @@ namespace BansheeEngine
 		bool fullscreen; /**< If true the application will be started in fullscreen using user's desktop resolution. */
 		UINT32 windowedWidth; /**< Width of the window if not starting the application in fullscreen. */
 		UINT32 windowedHeight; /**< Height of the window if not starting the application in fullscreen. */
+		bool debug; /**< Determines should the scripts be output in debug mode (worse performance but better error reporting). */
 
 		/************************************************************************/
 		/* 								RTTI		                     		*/

+ 4 - 0
BansheeEditor/Include/BsPlatformInfoRTTI.h

@@ -27,6 +27,9 @@ namespace BansheeEngine
 		UINT32& getWindowedHeight(PlatformInfo* obj) { return obj->windowedHeight; }
 		void setWindowedHeight(PlatformInfo* obj, UINT32& val) { obj->windowedHeight = val; }
 
+		bool& getDebug(PlatformInfo* obj) { return obj->debug; }
+		void setDebug(PlatformInfo* obj, bool& val) { obj->debug = val; }
+
 	public:
 		PlatformInfoRTTI()
 		{
@@ -36,6 +39,7 @@ namespace BansheeEngine
 			addPlainField("fullscreen", 3, &PlatformInfoRTTI::getFullscreen, &PlatformInfoRTTI::setFullscreen);
 			addPlainField("windowedWidth", 4, &PlatformInfoRTTI::getWindowedWidth, &PlatformInfoRTTI::setWindowedWidth);
 			addPlainField("windowedHeight", 5, &PlatformInfoRTTI::getWindowedHeight, &PlatformInfoRTTI::setWindowedHeight);
+			addPlainField("debug", 6, &PlatformInfoRTTI::getDebug, &PlatformInfoRTTI::setDebug);
 		}
 
 		virtual const String& getRTTIName() override

+ 7 - 0
BansheeEditor/Include/BsProjectLibrary.h

@@ -225,6 +225,13 @@ namespace BansheeEngine
 		 */
 		const Path& getResourcesFolder() const { return mResourcesFolder; }
 
+		/**
+		 * @brief	Returns the resource manifest managed by the project library.
+		 *
+		 * @note	Internal method.
+		 */
+		const ResourceManifestPtr& _getManifest() const { return mResourceManifest; }
+
 		/**
 		 * @brief	Saves all the project library data so it may be restored later,
 		 *			at the default save location in the project folder. Project

+ 68 - 2
BansheeEditor/Source/BsBuildManager.cpp

@@ -2,6 +2,7 @@
 #include "BsBuildDataRTTI.h"
 #include "BsFileSerializer.h"
 #include "BsFileSystem.h"
+#include "BsEditorApplication.h"
 
 namespace BansheeEngine
 {
@@ -22,6 +23,8 @@ namespace BansheeEngine
 		return BuildData::getRTTIStatic();
 	}
 
+	const WString BuildManager::BUILD_FOLDER_NAME = L"Builds\\";
+
 	BuildManager::BuildManager()
 	{
 		mBuildData = bs_shared_ptr_new<BuildData>();
@@ -68,15 +71,78 @@ namespace BansheeEngine
 		}
 	}
 
+	Vector<Path> BuildManager::getNativeBinaries(PlatformType type) const
+	{
+		Vector<Path> libs = { L"BansheeEngine", L"BansheeCore", L"BansheeUtility",
+			L"BansheeD3D11RenderAPI", L"BansheeGLRenderAPI", L"BansheeMono", L"BansheeOISInput",
+			L"RenderBeast", L"SBansheeEngine", L"BansheeOIS", L"mono-2.0", L"nvtt" };
+
+		switch (type)
+		{
+		case PlatformType::Windows:
+		{
+			for (auto& lib : libs)
+				lib.setExtension(".dll");
+		}
+		}
+
+		return libs;
+	}
+
+	Path BuildManager::getBuildFolder(BuildFolder folder, PlatformType platform) const
+	{
+		Path sourceRoot = APP_ROOT;
+		sourceRoot.makeAbsolute(FileSystem::getWorkingDirectoryPath());
+
+		switch (folder)
+		{
+		case BuildFolder::SourceRoot:
+			return sourceRoot;
+		case BuildFolder::DestinationRoot:
+		{
+			switch (platform)
+			{
+			case PlatformType::Windows:
+				return gEditorApplication().getProjectPath() + BUILD_FOLDER_NAME + L"Windows";
+			}
+
+			return gEditorApplication().getProjectPath() + BUILD_FOLDER_NAME;
+		}
+		case BuildFolder::NativeBinaries:
+		{
+			Path binariesPath = FileSystem::getWorkingDirectoryPath();
+
+			return binariesPath.makeRelative(sourceRoot);
+		}
+		case BuildFolder::BansheeAssemblies:
+		{
+			Path dataPath = ASSEMBLY_PATH;
+			dataPath.makeAbsolute(FileSystem::getWorkingDirectoryPath());
+
+			return dataPath.makeRelative(sourceRoot);
+		}
+		case BuildFolder::Data:
+		{
+			Path dataPath = ENGINE_DATA_PATH;
+			dataPath.makeAbsolute(FileSystem::getWorkingDirectoryPath());
+
+			return dataPath.makeRelative(sourceRoot);
+		}
+		}
+
+		return Path::BLANK;
+	}
+
 	Path BuildManager::getMainExecutable(PlatformType type) const
 	{
 		switch (type)
 		{
 		case PlatformType::Windows:
 		{
-			SPtr<WinPlatformInfo> winPlatformInfo = std::static_pointer_cast<WinPlatformInfo>(getPlatformInfo(type));
+			Path output = RUNTIME_DATA_PATH + "Binaries\\Win64\\Game.exe";
+			output.makeAbsolute(FileSystem::getWorkingDirectoryPath());
 
-			return "Prebuilt\\Win64\\Game.exe";
+			return output;
 		}
 		}
 

+ 13 - 1
BansheeEditor/Source/BsEditorApplication.cpp

@@ -47,8 +47,20 @@ namespace BansheeEngine
 		return renderWindowDesc;
 	}
 
+	Vector<String> getImporters()
+	{
+		Vector<String> importers;
+
+		importers.push_back("BansheeFreeImgImporter");
+		importers.push_back("BansheeFBXImporter");
+		importers.push_back("BansheeFontImporter");
+		importers.push_back("BansheeSL");
+
+		return importers;
+	}
+
 	EditorApplication::EditorApplication(EditorRenderAPI renderAPIPlugin)
-		:Application(createRenderWindowDesc(), toEngineRenderAPI(renderAPIPlugin), RendererPlugin::Default),
+		:Application(createRenderWindowDesc(), toEngineRenderAPI(renderAPIPlugin), RendererPlugin::Default, getImporters()),
 		mActiveRAPIPlugin(toEngineRenderAPI(renderAPIPlugin)), mSBansheeEditorPlugin(nullptr), mIsProjectLoaded(false)
 	{
 

+ 1 - 1
BansheeEditor/Source/BsProjectLibrary.cpp

@@ -21,7 +21,7 @@ using namespace std::placeholders;
 namespace BansheeEngine
 {
 	const Path ProjectLibrary::RESOURCES_DIR = L"Resources\\";
-	const Path ProjectLibrary::INTERNAL_RESOURCES_DIR = PROJECT_INTERNAL_DIR + L"Resources\\";
+	const Path ProjectLibrary::INTERNAL_RESOURCES_DIR = PROJECT_INTERNAL_DIR + GAME_RESOURCES_FOLDER_NAME;
 	const WString ProjectLibrary::LIBRARY_ENTRIES_FILENAME = L"ProjectLibrary.asset";
 	const WString ProjectLibrary::RESOURCE_MANIFEST_FILENAME = L"ResourceManifest.asset";
 

+ 4 - 9
BansheeEngine/Include/BsApplication.h

@@ -30,7 +30,8 @@ namespace BansheeEngine
 	class BS_EXPORT Application : public CoreApplication
 	{
 	public:
-		Application(RENDER_WINDOW_DESC& primaryWindowDesc, RenderAPIPlugin renderAPI, RendererPlugin renderer);
+		Application(RENDER_WINDOW_DESC primaryWindowDesc, RenderAPIPlugin renderAPI, RendererPlugin renderer, 
+			const Vector<String>& importers);
 		virtual ~Application();
 
 		/**
@@ -40,14 +41,8 @@ namespace BansheeEngine
 		 * @param	renderSystem		Render system to use.
 		 * @param	renderer			Renderer to use.
 		 */
-		static void startUp(RENDER_WINDOW_DESC& primaryWindowDesc, RenderAPIPlugin renderAPI, RendererPlugin renderer = RendererPlugin::Default);
-
-		/**
-		 * @brief	Returns the render target that the main camera in the scene (if any) will render its view to. This
-		 * 			generally means the main game window when running standalone, or the Game viewport when running
-		 * 			in editor.
-		 */
-		RenderTargetPtr getMainRenderTarget() const;
+		static void startUp(RENDER_WINDOW_DESC& primaryWindowDesc, RenderAPIPlugin renderAPI, 
+			RendererPlugin renderer = RendererPlugin::Default, const Vector<String>& importers = Vector<String>());
 
 		/**
 		 * @brief	Returns the absolute path to the builtin managed engine assembly file.

+ 1 - 3
BansheeEngine/Include/BsBuiltinResources.h

@@ -135,7 +135,7 @@ namespace BansheeEngine
 		static const Path EngineShaderFolder;
 		static const Path EngineShaderIncludeFolder;
 		static const Path EngineMeshFolder;
-
+		static const WString IconTextureName;
 	private:
 		/**
 		 * @brief	Imports all necessary resources and converts them to engine-ready format.
@@ -298,8 +298,6 @@ namespace BansheeEngine
 		static const Vector2I CursorSizeNWSEHotspot;
 		static const Vector2I CursorSizeWEHotspot;
 
-		static const WString IconTex;
-
 		static const WString ShaderSpriteTextFile;
 		static const WString ShaderSpriteImageAlphaFile;
 		static const WString ShaderSpriteImageNoAlphaFile;

+ 6 - 2
BansheeEngine/Include/BsPrerequisites.h

@@ -133,9 +133,13 @@ namespace BansheeEngine
 	static const char* ENGINE_ASSEMBLY = "MBansheeEngine";
 	static const char* SCRIPT_GAME_ASSEMBLY = "MScriptGame";
 	static const Path ASSEMBLY_PATH = "..\\..\\Assemblies\\";
-	static const Path GAME_RESOURCES_PATH = "..\\..\\..\\Resources\\";
-	static const Path RUNTIME_DATA_PATH = L"..\\..\\..\\Data\\";
+	static const Path APP_ROOT = "..\\..\\..\\";
+	static const char* GAME_RESOURCES_FOLDER_NAME = "Resources\\";
+	static const Path GAME_RESOURCES_PATH = APP_ROOT + GAME_RESOURCES_FOLDER_NAME;
+	static const Path RUNTIME_DATA_PATH = APP_ROOT + "Data\\";
+	static const Path ENGINE_DATA_PATH = RUNTIME_DATA_PATH + "Engine\\";
 	static const char* GAME_SETTINGS_NAME = "GameSettings.asset";
+	static const Path GAME_SETTINGS_PATH = APP_ROOT + GAME_SETTINGS_NAME;
 	static const char* GAME_RESOURCE_MANIFEST_NAME = "ResourceManifest.asset";
 
 	/**

+ 10 - 16
BansheeEngine/Source/BsApplication.cpp

@@ -21,7 +21,8 @@
 
 namespace BansheeEngine
 {
-	START_UP_DESC createStartUpDesc(RENDER_WINDOW_DESC& primaryWindowDesc, const String& renderAPI, const String& renderer)
+	START_UP_DESC createStartUpDesc(RENDER_WINDOW_DESC& primaryWindowDesc, const String& renderAPI, const String& renderer, 
+		const Vector<String>& importers)
 	{
 		START_UP_DESC desc;
 		desc.renderAPI = renderAPI;
@@ -29,17 +30,15 @@ namespace BansheeEngine
 		desc.primaryWindowDesc = primaryWindowDesc;
 
 		desc.input = "BansheeOISInput";
-		desc.importers.push_back("BansheeFreeImgImporter");
-		desc.importers.push_back("BansheeFBXImporter");
-		desc.importers.push_back("BansheeFontImporter");
-		desc.importers.push_back("BansheeSL");
+		desc.importers = importers;
 
 		return desc;
 	}
 
-	Application::Application(RENDER_WINDOW_DESC& primaryWindowDesc, RenderAPIPlugin renderAPI, RendererPlugin renderer)
-		:CoreApplication(createStartUpDesc(primaryWindowDesc, getLibNameForRenderAPI(renderAPI), getLibNameForRenderer(renderer))),
-		mMonoPlugin(nullptr), mSBansheeEnginePlugin(nullptr)
+	Application::Application(RENDER_WINDOW_DESC primaryWindowDesc, RenderAPIPlugin renderAPI, RendererPlugin renderer, 
+		const Vector<String>& importers)
+		:CoreApplication(createStartUpDesc(primaryWindowDesc, getLibNameForRenderAPI(renderAPI), 
+		getLibNameForRenderer(renderer), importers)), mMonoPlugin(nullptr), mSBansheeEnginePlugin(nullptr)
 	{
 
 	}
@@ -100,9 +99,10 @@ namespace BansheeEngine
 		CoreApplication::onShutDown();
 	}
 
-	void Application::startUp(RENDER_WINDOW_DESC& primaryWindowDesc, RenderAPIPlugin renderAPI, RendererPlugin renderer)
+	void Application::startUp(RENDER_WINDOW_DESC& primaryWindowDesc, RenderAPIPlugin renderAPI, 
+		RendererPlugin renderer, const Vector<String>& importers)
 	{
-		CoreApplication::startUp<Application>(primaryWindowDesc, renderAPI, renderer);
+		CoreApplication::startUp<Application>(primaryWindowDesc, renderAPI, renderer, importers);
 	}
 
 	void Application::preUpdate()
@@ -141,12 +141,6 @@ namespace BansheeEngine
 		// Do nothing, we activate the renderer at a later stage
 	}
 
-	RenderTargetPtr Application::getMainRenderTarget() const
-	{
-		// TODO - Need a way to determine primary viewport!
-		return nullptr;
-	}
-
 	Path Application::getEngineAssemblyPath() const
 	{
 		Path assemblyPath = getBuiltinAssemblyFolder();

+ 3 - 3
BansheeEngine/Source/BsBuiltinResources.cpp

@@ -59,7 +59,7 @@ namespace BansheeEngine
 	const Path BuiltinResources::EngineRawShaderFolder = BuiltinRawDataFolder + ShaderFolder;
 	const Path BuiltinResources::EngineRawShaderIncludeFolder = BuiltinRawDataFolder + ShaderIncludeFolder;
 
-	const Path BuiltinResources::BuiltinDataFolder = RUNTIME_DATA_PATH + L"Engine\\";
+	const Path BuiltinResources::BuiltinDataFolder = ENGINE_DATA_PATH;
 	const Path BuiltinResources::EngineSkinFolder = BuiltinDataFolder + SkinFolder;
 	const Path BuiltinResources::EngineCursorFolder = BuiltinDataFolder + CursorFolder;
 	const Path BuiltinResources::EngineIconFolder = BuiltinDataFolder + IconFolder;
@@ -168,7 +168,7 @@ namespace BansheeEngine
 	/* 							ICON TEXTURES					    		*/
 	/************************************************************************/
 
-	const WString BuiltinResources::IconTex = L"BansheeIcon.png";
+	const WString BuiltinResources::IconTextureName = L"BansheeIcon.png";
 
 	/************************************************************************/
 	/* 									SHADERS                      		*/
@@ -290,7 +290,7 @@ namespace BansheeEngine
 
 		Path iconPath = FileSystem::getWorkingDirectoryPath();
 		iconPath.append(EngineIconFolder);
-		iconPath.append(IconTex + L".asset");
+		iconPath.append(IconTextureName + L".asset");
 
 		HTexture iconTex = gResources().load<Texture>(iconPath);
 

+ 8 - 1
BansheeMono/Include/BsMonoManager.h

@@ -67,10 +67,17 @@ namespace BansheeEngine
 		void loadScriptDomain();
 
 		/**
-		 * @brief	Returns the absolute location of the folder where Mono framework assemblies are located.
+		 * @brief	Returns the path of the folder where Mono framework assemblies are located. Path is relative
+		 * 			to the application executable.
 		 */
 		Path getFrameworkAssembliesFolder() const;
 
+		/**
+		 * @brief	Returns the path to the Mono /etc folder that is required for initializing Mono. Path is relative
+		 * 			to the application executable.
+		 */
+		Path getMonoEtcFolder() const;
+
 		/**
 		 * @brief	Returns the absolute path to the Mono compiler.
 		 */

+ 5 - 3
BansheeMono/Source/BsMonoManager.cpp

@@ -243,10 +243,12 @@ namespace BansheeEngine
 
 	Path MonoManager::getFrameworkAssembliesFolder() const
 	{
-		Path assembliesFolder = FileSystem::getWorkingDirectoryPath();
-		assembliesFolder.append(MONO_VERSION_DATA[(int)MONO_VERSION].path);
+		return MONO_VERSION_DATA[(int)MONO_VERSION].path;
+	}
 
-		return assembliesFolder;
+	Path MonoManager::getMonoEtcFolder() const
+	{
+		return MONO_ETC_DIR;
 	}
 
 	Path MonoManager::getCompilerPath() const

+ 6 - 0
Dependencies.txt

@@ -62,6 +62,12 @@ Place plug-in specific dependency files in:
  - Tools (executables) in (BansheeRootDir)/(PluginDir)/Dependencies/tools
  - Dynamic library files in (BansheeRootDir)/bin/(Platform)/(Configuration)
 
+----------------------------------------------------------------------------------
+Scripts
+
+Various scripts located in /Scripts directory require Python 3.5 installed:
+ - https://www.python.org/downloads/
+
 ----------------------------------------------------------------------------------
 
  Legend:

+ 8 - 1
ExampleProject/Main/Main.cpp

@@ -106,11 +106,18 @@ int CALLBACK WinMain(
 	renderWindowDesc.title = "Banshee Example App";
 	renderWindowDesc.fullscreen = false;
 
+	// List of importer plugins we plan on using for importing various resources
+	Vector<String> importers;
+	importers.push_back("BansheeFreeImgImporter"); // For importing textures
+	importers.push_back("BansheeFBXImporter"); // For importing meshes
+	importers.push_back("BansheeFontImporter"); // For importing fonts
+	importers.push_back("BansheeSL"); // For importing shaders
+
 	// Initializes the application with primary window defined as above and DirectX 11 render system.
 	// You may use other render systems than DirectX 11, however this example for simplicity only uses DirectX 11.
 	// If you wanted other render systems you would need to create separate shaders for them and import them
 	// along with (or replace) the DX11 ones.
-	Application::startUp(renderWindowDesc, RenderAPIPlugin::DX11);
+	Application::startUp(renderWindowDesc, RenderAPIPlugin::DX11, RendererPlugin::Default, importers);
 
 	// Imports all of ours assets and prepares GameObject that handle the example logic.
 	setUpExample();

+ 2 - 3
Game/Source/Main.cpp

@@ -14,8 +14,7 @@ using namespace BansheeEngine;
 
 void runApplication()
 {
-	Path gameSettingsPath = RUNTIME_DATA_PATH + GAME_SETTINGS_NAME;
-	FileDecoder fd(gameSettingsPath);
+	FileDecoder fd(GAME_SETTINGS_PATH);
 	SPtr<GameSettings> gameSettings = std::static_pointer_cast<GameSettings>(fd.decode());
 
 	if (gameSettings == nullptr)
@@ -67,7 +66,7 @@ void runApplication()
 	gameSettings->resolutionWidth = resolutionWidth;
 	gameSettings->resolutionHeight = resolutionHeight;
 
-	FileEncoder fe(gameSettingsPath);
+	FileEncoder fe(GAME_SETTINGS_PATH);
 	fe.encode(gameSettings.get());
 
 	Path resourceManifestPath = GAME_RESOURCES_PATH + GAME_RESOURCE_MANIFEST_NAME;

+ 211 - 5
MBansheeEditor/BuildManager.cs

@@ -1,5 +1,7 @@
 using System;
+using System.IO;
 using System.Runtime.CompilerServices;
+using System.Threading;
 using BansheeEngine;
 
 namespace BansheeEditor
@@ -91,6 +93,15 @@ namespace BansheeEditor
             set { Internal_SetResolution(mCachedPtr, WindowedWidth, value); }
         }
 
+        /// <summary>
+        /// Determines should the scripts be output in debug mode (worse performance but better error reporting).
+        /// </summary>
+        public bool Debug
+        {
+            get { return Internal_GetDebug(mCachedPtr); }
+            set { Internal_SetDebug(mCachedPtr, value); }
+        }
+
         /// <summary>
         /// A set of semicolon separated defines to use when compiling scripts for this platform.
         /// </summary>
@@ -126,6 +137,12 @@ namespace BansheeEditor
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         static extern void Internal_SetResolution(IntPtr thisPtr, int width, int height);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        static extern bool Internal_GetDebug(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        static extern void Internal_SetDebug(IntPtr thisPtr, bool fullscreen);
     }
 
     /// <summary>
@@ -247,29 +264,182 @@ namespace BansheeEditor
             get { return Internal_GetActivePlatformInfo(); }
         }
 
+        /// <summary>
+        /// Returns a path to a specific folder used in the build process. See entries of BuildFolder enum for explanations 
+        /// of individual folder types.
+        /// </summary>
+        /// <param name="folder">Type of folder to retrieve the path for.</param>
+        /// <param name="platform">Platform to retrieve the path for.</param>
+        /// <returns>Path for the requested folder. This can be absolute or relative, see <see cref="BuildFolder"/> enum
+        ///          for details.</returns>
+        private static string GetBuildFolder(BuildFolder folder, PlatformType platform)
+        {
+            return Internal_GetBuildFolder(folder, platform);
+        }
+
+        /// <summary>
+        /// Returns a list of names of all native binaries required for a specific platform.
+        /// </summary>
+        /// <param name="platform">Platform type for which to get the binaries for.</param>
+        /// <returns>Array of names of native binary files.</returns>
+        private static string[] GetNativeBinaries(PlatformType platform)
+        {
+            return Internal_GetNativeBinaries(platform);
+        }
+
         /// <summary>
         /// Builds the executable and packages the game.
         /// </summary>
         public static void Build()
         {
-            // TODO
+            PlatformType activePlatform = ActivePlatform;
+            PlatformInfo platformInfo = ActivePlatformInfo;
+
+            string srcRoot = GetBuildFolder(BuildFolder.SourceRoot, activePlatform);
+            string destRoot = GetBuildFolder(BuildFolder.DestinationRoot, activePlatform);
+
+            // Prepare clean destination folder
+            Directory.Delete(destRoot, true);
+            Directory.CreateDirectory(destRoot);
+
+            // Compile game assembly
+            string bansheeAssemblyFolder = GetBuildFolder(BuildFolder.BansheeAssemblies, activePlatform);
+            string srcBansheeAssemblyFolder = Path.Combine(srcRoot, bansheeAssemblyFolder);
+            string destBansheeAssemblyFolder = Path.Combine(destRoot, bansheeAssemblyFolder);
+
+            Directory.CreateDirectory(destBansheeAssemblyFolder);
+            CompilerInstance ci = ScriptCompiler.CompileAsync(ScriptAssemblyType.Game, ActivePlatform, platformInfo.Debug, destBansheeAssemblyFolder);
+
+            // Copy engine assembly
+            // TODO - Copy Release version of engine assembly if not in debug mode, and Debug otherwise
+            {
+                string srcFile = Path.Combine(srcBansheeAssemblyFolder, EditorApplication.EngineAssemblyName);
+                string destFile = Path.Combine(destBansheeAssemblyFolder, EditorApplication.EngineAssemblyName);
+
+                File.Copy(srcFile, destFile);
+            }
+
+            // Copy builtin data
+            string dataFolder = GetBuildFolder(BuildFolder.Data, activePlatform);
+            string srcData = Path.Combine(srcRoot, dataFolder);
+            string destData = Path.Combine(destRoot, dataFolder);
+
+            DirectoryEx.Copy(srcData, destData);
+
+            // Copy native binaries
+            string binaryFolder = GetBuildFolder(BuildFolder.NativeBinaries, activePlatform);
+            string srcBin = Path.Combine(srcRoot, binaryFolder);
+            string destBin = Path.Combine(destRoot, binaryFolder);
+
+            Directory.CreateDirectory(destBin);
+
+            string[] nativeBinaries = GetNativeBinaries(activePlatform);
+            foreach (var entry in nativeBinaries)
+            {
+                string srcFile = Path.Combine(srcBin, entry);
+                string destFile = Path.Combine(destBin, entry);
+
+                File.Copy(srcFile, destFile);
+            }
+
+            // Copy .NET framework assemblies
+            string frameworkAssemblyFolder = GetBuildFolder(BuildFolder.FrameworkAssemblies, activePlatform);
+            string srcFrameworkAssemblyFolder = Path.Combine(srcRoot, frameworkAssemblyFolder);
+            string destFrameworkAssemblyFolder = Path.Combine(destRoot, frameworkAssemblyFolder);
+
+            Directory.CreateDirectory(destFrameworkAssemblyFolder);
+
+            string[] frameworkAssemblies = GetFrameworkAssemblies(activePlatform);
+            foreach (var entry in frameworkAssemblies)
+            {
+                string srcFile = Path.Combine(srcFrameworkAssemblyFolder, entry + ".dll");
+                string destFile = Path.Combine(destFrameworkAssemblyFolder, entry + ".dll");
+
+                File.Copy(srcFile, destFile);
+            }
+
+            // Copy Mono
+            string monoFolder = GetBuildFolder(BuildFolder.Mono, activePlatform);
+            string srcMonoFolder = Path.Combine(srcRoot, monoFolder);
+            string destMonoFolder = Path.Combine(destRoot, monoFolder);
+
+            DirectoryEx.Copy(srcMonoFolder, destMonoFolder);
+
+            string srcExecFile = GetMainExecutable(activePlatform);
+            string destExecFile = Path.Combine(destBin, Path.GetFileName(srcExecFile));
+
+            File.Copy(srcExecFile, destExecFile);
+
+            InjectIcons(destExecFile, platformInfo);
+            PackageResources(destRoot, platformInfo);
+            CreateStartupSettings(destRoot, platformInfo);
+
+            // Wait until compile finishes
+            while (!ci.IsDone)
+                Thread.Sleep(200);
+
+            ci.Dispose();
+        }
+
+        /// <summary>
+        /// Injects icons specified in <see cref="PlatformInfo"/> into an executable at the specified path.
+        /// </summary>
+        /// <param name="filePath">Absolute path to the executable to inject icons in.</param>
+        /// <param name="info">Object containing references to icons to inject.</param>
+        private static void InjectIcons(string filePath, PlatformInfo info)
+        {
+            IntPtr infoPtr = IntPtr.Zero;
+            if (info != null)
+                infoPtr = info.GetCachedPtr();
+
+            Internal_InjectIcons(filePath, infoPtr);
+        }
+
+        /// <summary>
+        /// Finds all used resources by the build and packages them into an output folder.
+        /// </summary>
+        /// <param name="buildFolder">Absolute path to the root folder of the build. This is where the packaged resource
+        ///                           folder be placed.</param>
+        /// <param name="info">Platform information about the current build.</param>
+        private static void PackageResources(string buildFolder, PlatformInfo info)
+        {
+            IntPtr infoPtr = IntPtr.Zero;
+            if (info != null)
+                infoPtr = info.GetCachedPtr();
+
+            Internal_PackageResources(buildFolder, infoPtr);
+        }
+
+        /// <summary>
+        /// Creates a game settings asset that contains necessary data for starting up the game (e.g. initial scene).
+        /// </summary>
+        /// <param name="buildFolder">Absolute path to the root folder of the build. This is where the settings assets
+        ///                           will be output.</param>
+        /// <param name="info">Platform information about the current build.</param>
+        private static void CreateStartupSettings(string buildFolder, PlatformInfo info)
+        {
+            IntPtr infoPtr = IntPtr.Zero;
+            if (info != null)
+                infoPtr = info.GetCachedPtr();
+
+            Internal_CreateStartupSettings(buildFolder, infoPtr);
         }
 
         /// <summary>
-        /// Returns a list of .NET framework managed assemblies to be included for the specified platform.
+        /// Returns a list of .NET framework managed assemblies (without extension) to be included for the specified platform.
         /// </summary>
         /// <param name="type">Platform type to retrieve the list of assemblies for.</param>
-        /// <returns>A list of .NET framework managed assemblies that will be included with the build.</returns>
+        /// <returns>A list of .NET framework managed assemblies (without extension) that will be included with the build.</returns>
         internal static string[] GetFrameworkAssemblies(PlatformType type)
         {
             return Internal_GetFrameworkAssemblies(type);
         }
 
         /// <summary>
-        /// Returns the location of the executable for the provided platform.
+        /// Returns the absolute path to the executable for the provided platform.
         /// </summary>
         /// <param name="type">Platform type to retrieve the executable location for.</param>
-        /// <returns>Path to the executable in the editor install folder.</returns>
+        /// <returns>Absolute path to the executable.</returns>
         internal static string GetMainExecutable(PlatformType type)
         {
             return Internal_GetMainExecutable(type);
@@ -296,6 +466,27 @@ namespace BansheeEditor
             return Internal_GetPlatformInfo(type);
         }
 
+        /// <summary>
+        /// Types of various folders used by the build manager.
+        /// </summary>
+        private enum BuildFolder // Note: Must match C++ enum ScriptBuildFolder
+        {
+            /// <summary>Absolute path to the root folder where all the prebuilt binaries and data exist.</summary>
+            SourceRoot,
+            /// <summary>Absolute path to the root folder for a build for a specific platform.</summary>
+            DestinationRoot,
+            /// <summary>Folder where native binaries are stored. Relative to root.</summary>
+            NativeBinaries,
+            /// <summary>Folder where Banshee specific assemblies are stored. Relative to root.</summary>
+            BansheeAssemblies,
+            /// <summary>Folder where .NET framework assemblies are stored. Relative to root.</summary>
+            FrameworkAssemblies,
+            /// <summary>Folder where miscelaneous Mono files are stored. Relative to root.</summary>
+            Mono,
+            /// <summary>Folder where builtin data is stored. Relative to root.</summary>
+            Data
+        }
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern PlatformType[] Internal_GetAvailablePlatforms();
 
@@ -319,5 +510,20 @@ namespace BansheeEditor
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern string Internal_GetDefines(PlatformType type);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern string[] Internal_GetNativeBinaries(PlatformType type);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern string Internal_GetBuildFolder(BuildFolder folder, PlatformType platform);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_InjectIcons(string filePath, IntPtr info);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_PackageResources(string buildFolder, IntPtr info);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateStartupSettings(string buildFolder, IntPtr info);
     }
 }

+ 19 - 0
SBansheeEditor/Include/BsScriptBuildManager.h

@@ -6,6 +6,20 @@
 
 namespace BansheeEngine
 {
+	/**
+	 * @brief	Types of various folders used by the managed build manager.
+	 */
+	enum class ScriptBuildFolder
+	{
+		SourceRoot, /**< Absolute path to the root folder where all the prebuilt binaries and data exist. */
+		DestinationRoot, /**< Absolute path to the root folder for a build for a specific platform. */
+		NativeBinaries, /**< Folder where native binaries are stored. Relative to root. */
+		BansheeAssemblies, /**< Folder where Banshee specific assemblies are stored. Relative to root. */
+		FrameworkAssemblies, /**< Folder where .NET framework assemblies are stored. Relative to root. */
+		Mono, /**< Folder where miscelaneous Mono files are stored. Relative to root. */
+		Data /**< Folder where builtin data is stored. Relative to root. */
+	};
+
 	/**
 	 * @brief	Interop class between C++ & CLR for BuildManager.
 	 */
@@ -28,5 +42,10 @@ namespace BansheeEngine
 		static MonoArray* internal_GetFrameworkAssemblies(PlatformType type);
 		static MonoString* internal_GetMainExecutable(PlatformType type);
 		static MonoString* internal_GetDefines(PlatformType type);
+		static MonoArray* internal_GetNativeBinaries(PlatformType type);
+		static MonoString* internal_GetBuildFolder(ScriptBuildFolder folder, PlatformType platform);
+		static void internal_InjectIcons(MonoString* filePath, ScriptPlatformInfo* info);
+		static void internal_PackageResources(MonoString* buildFolder, ScriptPlatformInfo* info);
+		static void internal_CreateStartupSettings(MonoString* buildFolder, ScriptPlatformInfo* info);
 	};
 }

+ 1 - 0
SBansheeEditor/Include/BsScriptEditorPrerequisites.h

@@ -26,4 +26,5 @@ namespace BansheeEngine
 	class GUIResourceField;
 	class GUITextureField;
 	class ScriptHandleSliderBase;
+	class ScriptPlatformInfo;
 }

+ 2 - 0
SBansheeEditor/Include/BsScriptPlatformInfo.h

@@ -53,6 +53,8 @@ namespace BansheeEngine
 		static void internal_SetFullscreen(ScriptPlatformInfoBase* thisPtr, bool fullscreen);
 		static void internal_GetResolution(ScriptPlatformInfoBase* thisPtr, UINT32* width, UINT32* height);
 		static void internal_SetResolution(ScriptPlatformInfoBase* thisPtr, UINT32 width, UINT32 height);
+		static bool internal_GetDebug(ScriptPlatformInfoBase* thisPtr);
+		static void internal_SetDebug(ScriptPlatformInfoBase* thisPtr, bool debug);
 	};
 
 	/**

+ 296 - 0
SBansheeEditor/Source/BsScriptBuildManager.cpp

@@ -4,6 +4,18 @@
 #include "BsMonoMethod.h"
 #include "BsMonoUtil.h"
 #include "BsScriptPlatformInfo.h"
+#include "BsFileSystem.h"
+#include "BsIconUtility.h"
+#include "BsCoreThread.h"
+#include "BsGameSettings.h"
+#include "BsFileSerializer.h"
+#include "BsProjectLibrary.h"
+#include "BsProjectResourceMeta.h"
+#include "BsResources.h"
+#include "BsPrefab.h"
+#include "BsEditorApplication.h"
+#include "BsResourceManifest.h"
+#include "BsBuiltinResources.h"
 
 namespace BansheeEngine
 {
@@ -21,6 +33,11 @@ namespace BansheeEngine
 		metaData.scriptClass->addInternalCall("Internal_GetFrameworkAssemblies", &ScriptBuildManager::internal_GetFrameworkAssemblies);
 		metaData.scriptClass->addInternalCall("Internal_GetMainExecutable", &ScriptBuildManager::internal_GetMainExecutable);
 		metaData.scriptClass->addInternalCall("Internal_GetDefines", &ScriptBuildManager::internal_GetDefines);
+		metaData.scriptClass->addInternalCall("Internal_GetNativeBinaries", &ScriptBuildManager::internal_GetNativeBinaries);
+		metaData.scriptClass->addInternalCall("Internal_GetBuildFolder", &ScriptBuildManager::internal_GetBuildFolder);
+		metaData.scriptClass->addInternalCall("Internal_InjectIcons", &ScriptBuildManager::internal_InjectIcons);
+		metaData.scriptClass->addInternalCall("Internal_PackageResources", &ScriptBuildManager::internal_PackageResources);
+		metaData.scriptClass->addInternalCall("Internal_CreateStartupSettings", &ScriptBuildManager::internal_CreateStartupSettings);
 	}
 
 	MonoArray* ScriptBuildManager::internal_GetAvailablePlatforms()
@@ -76,4 +93,283 @@ namespace BansheeEngine
 	{
 		return MonoUtil::wstringToMono(MonoManager::instance().getDomain(), BuildManager::instance().getDefines(type));
 	}
+
+	MonoArray* ScriptBuildManager::internal_GetNativeBinaries(PlatformType type)
+	{
+		Vector<Path> paths = BuildManager::instance().getNativeBinaries(type);
+
+		UINT32 numEntries = (UINT32)paths.size();
+		ScriptArray outArray = ScriptArray::create<WString>(numEntries);
+		for (UINT32 i = 0; i < numEntries; i++)
+		{
+			outArray.set(i, MonoUtil::wstringToMono(MonoManager::instance().getDomain(), paths[i].toWString()));
+		}
+
+		return outArray.getInternal();
+	}
+
+	MonoString* ScriptBuildManager::internal_GetBuildFolder(ScriptBuildFolder folder, PlatformType platform)
+	{
+		Path path;
+
+		if (folder == ScriptBuildFolder::FrameworkAssemblies)
+		{
+			Path assemblyFolder = MonoManager::instance().getFrameworkAssembliesFolder();
+			assemblyFolder.makeAbsolute(FileSystem::getWorkingDirectoryPath());
+
+			Path sourceFolder = BuildManager::instance().getBuildFolder(BuildFolder::SourceRoot, platform);
+			path = assemblyFolder.makeRelative(sourceFolder);
+		}
+		else if (folder == ScriptBuildFolder::Mono)
+		{
+			Path monoEtcFolder = MonoManager::instance().getMonoEtcFolder();
+			monoEtcFolder.makeAbsolute(FileSystem::getWorkingDirectoryPath());
+
+			Path sourceFolder = BuildManager::instance().getBuildFolder(BuildFolder::SourceRoot, platform);
+			path = monoEtcFolder.makeRelative(sourceFolder);
+		}
+		else
+		{
+			BuildFolder nativeFolderType = BuildFolder::SourceRoot;
+			switch (folder)
+			{
+			case ScriptBuildFolder::SourceRoot:
+				nativeFolderType = BuildFolder::SourceRoot;
+				break;
+			case ScriptBuildFolder::DestinationRoot:
+				nativeFolderType = BuildFolder::DestinationRoot;
+				break;
+			case ScriptBuildFolder::NativeBinaries:
+				nativeFolderType = BuildFolder::NativeBinaries;
+				break;
+			case ScriptBuildFolder::BansheeAssemblies:
+				nativeFolderType = BuildFolder::BansheeAssemblies;
+				break;
+			case ScriptBuildFolder::Data:
+				nativeFolderType = BuildFolder::Data;
+				break;
+			}
+
+			path = BuildManager::instance().getBuildFolder(nativeFolderType, platform);
+		}
+
+		return MonoUtil::wstringToMono(MonoManager::instance().getDomain(), path.toWString());
+	}
+
+	void ScriptBuildManager::internal_InjectIcons(MonoString* filePath, ScriptPlatformInfo* info)
+	{
+		if (info == nullptr)
+			return;
+
+		Path executablePath = MonoUtil::monoToWString(filePath);
+
+		Map<UINT32, PixelDataPtr> icons;
+		SPtr<PlatformInfo> platformInfo = info->getPlatformInfo();
+		switch (platformInfo->type)
+		{
+		case PlatformType::Windows:
+		{
+			SPtr<WinPlatformInfo> winPlatformInfo = std::static_pointer_cast<WinPlatformInfo>(platformInfo);
+
+			struct IconData
+			{
+				UINT32 size;
+				HTexture texture;
+				PixelDataPtr pixels;
+			};
+
+			IconData textures[] =
+			{ 
+				{ 16, winPlatformInfo->icon16 },
+				{ 32, winPlatformInfo->icon32 },
+				{ 48, winPlatformInfo->icon48 },
+				{ 64, winPlatformInfo->icon64 },
+				{ 96, winPlatformInfo->icon96 },
+				{ 128, winPlatformInfo->icon128 },
+				{ 192, winPlatformInfo->icon192 }, 
+				{ 256, winPlatformInfo->icon256 } 
+			};
+
+			for (auto& entry : textures)
+			{
+				auto& texProps = entry.texture->getProperties();
+
+				entry.pixels = texProps.allocateSubresourceBuffer(0);
+				entry.texture->readSubresource(gCoreAccessor(), 0, entry.pixels);
+
+				icons[entry.size] = entry.pixels;
+			}
+
+			gCoreAccessor().submitToCoreThread(true);
+		}
+			break;
+		}
+
+		IconUtility::updateIconExe(executablePath, icons);
+	}
+
+	void ScriptBuildManager::internal_PackageResources(MonoString* buildFolder, ScriptPlatformInfo* info)
+	{
+		UnorderedSet<Path> usedResources;
+
+		// Get all resources manually included in build
+		Vector<ProjectLibrary::ResourceEntry*> buildResources = gProjectLibrary().getResourcesForBuild();
+		for (auto& entry : buildResources)
+		{
+			if (entry->meta == nullptr)
+			{
+				LOGWRN("Cannot include resource in build, missing meta file for: " + entry->path.toString());
+				continue;
+			}
+
+			Path resourcePath;
+			if (gResources().getFilePathFromUUID(entry->meta->getUUID(), resourcePath))
+				usedResources.insert(resourcePath);
+			else
+				LOGWRN("Cannot include resource in build, missing imported asset for: " + entry->path.toString());
+		}
+
+		// Include main scene
+		SPtr<PlatformInfo> platformInfo;
+
+		if (info != nullptr)
+			platformInfo = info->getPlatformInfo();
+
+		if (platformInfo != nullptr)
+		{
+			Path resourcePath;
+			if (gResources().getFilePathFromUUID(platformInfo->mainScene.getUUID(), resourcePath))
+				usedResources.insert(resourcePath);
+			else
+				LOGWRN("Cannot include main scene in build, missing imported asset.");
+		}
+
+		// Find dependencies of all resources
+		Vector<Path> newResources;
+		for (auto& entry : usedResources)
+			newResources.push_back(entry);
+
+		while (!newResources.empty())
+		{
+			Vector<Path> allDependencies;
+			for (auto& entry : newResources)
+			{
+				Vector<String> curDependencies = gResources().getDependencies(entry);
+				for (auto& entry : curDependencies)
+				{
+					Path resourcePath;
+					if (gResources().getFilePathFromUUID(entry, resourcePath))
+					{
+						if (usedResources.find(resourcePath) == usedResources.end())
+						{
+							allDependencies.push_back(resourcePath);
+							newResources.push_back(resourcePath);
+						}
+					}
+				}
+			}
+
+			newResources = allDependencies;
+		} 
+
+		// Copy resources
+		Path outputPath = MonoUtil::monoToWString(buildFolder);
+		outputPath.append(GAME_RESOURCES_FOLDER_NAME);
+
+		FileSystem::createDir(outputPath);
+
+		for (auto& entry : usedResources)
+		{
+			String uuid;
+			BS_ASSERT(gResources().getUUIDFromFilePath(entry, uuid));
+
+			Path sourcePath = gProjectLibrary().uuidToPath(uuid);
+			ProjectLibrary::LibraryEntry* libEntry = gProjectLibrary().findEntry(sourcePath);
+			assert(libEntry != nullptr && libEntry->type == ProjectLibrary::LibraryEntryType::File);
+
+			ProjectLibrary::ResourceEntry* resEntry = static_cast<ProjectLibrary::ResourceEntry*>(libEntry);
+
+			// If resource is prefab make sure to update it in case any of the prefabs it is referencing changed
+			if (resEntry->meta->getTypeID() == TID_Prefab)
+			{
+				HPrefab prefab = static_resource_cast<Prefab>(gProjectLibrary().load(sourcePath));
+				prefab->_updateChildInstances();
+
+				// TODO - I should also clear prefab diffs
+				gProjectLibrary().saveEntry(prefab);
+			}
+			else
+			{
+				Path destPath = outputPath;
+				destPath.setFilename(entry.getFilename());
+
+				FileSystem::copy(entry, destPath);
+			}
+		}
+
+		// Save icon
+		Path iconFolder = FileSystem::getWorkingDirectoryPath();
+		iconFolder.append(BuiltinResources::EngineIconFolder);
+
+		Path sourceRoot = BuildManager::instance().getBuildFolder(BuildFolder::SourceRoot, platformInfo->type);
+		iconFolder.makeRelative(sourceRoot);
+
+		Path destRoot = BuildManager::instance().getBuildFolder(BuildFolder::DestinationRoot, platformInfo->type);
+		Path destIconFile = destRoot;
+		destIconFile.append(iconFolder);
+		destIconFile.setFilename(BuiltinResources::IconTextureName + L".asset");
+
+		switch (platformInfo->type)
+		{
+		case PlatformType::Windows:
+		{
+			SPtr<WinPlatformInfo> winPlatformInfo = std::static_pointer_cast<WinPlatformInfo>(platformInfo);
+
+			gResources().save(winPlatformInfo->taskbarIcon, destIconFile, false);
+		}
+		};
+
+		// Save manifest
+		Path manifestPath = outputPath;
+		manifestPath.append(GAME_RESOURCE_MANIFEST_NAME);
+
+		Path internalResourcesFolder = gEditorApplication().getProjectPath();
+		internalResourcesFolder.append(PROJECT_INTERNAL_DIR);
+
+		ResourceManifestPtr manifest = gProjectLibrary()._getManifest();
+		ResourceManifest::save(manifest, manifestPath, internalResourcesFolder);
+	}
+
+	void ScriptBuildManager::internal_CreateStartupSettings(MonoString* buildFolder, ScriptPlatformInfo* info)
+	{
+		SPtr<PlatformInfo> platformInfo;
+
+		if (info != nullptr)
+			platformInfo = info->getPlatformInfo();
+
+		SPtr<GameSettings> gameSettings;
+		if (platformInfo != nullptr)
+		{
+			gameSettings->mainSceneUUID = platformInfo->mainScene.getUUID();
+			gameSettings->fullscreen = platformInfo->fullscreen;
+			gameSettings->resolutionWidth = platformInfo->windowedWidth;
+			gameSettings->resolutionWidth = platformInfo->windowedHeight;
+
+			switch (platformInfo->type)
+			{
+			case(PlatformType::Windows) :
+			{
+				SPtr<WinPlatformInfo> winPlatformInfo = std::static_pointer_cast<WinPlatformInfo>(platformInfo);
+				gameSettings->titleBarText = winPlatformInfo->titlebarText;
+			}
+				break;
+			}
+		}
+
+		Path outputPath = MonoUtil::monoToWString(buildFolder);
+		outputPath.append(GAME_SETTINGS_NAME);
+
+		FileEncoder fe(outputPath);
+		fe.encode(gameSettings.get());
+	}
 }

+ 2 - 0
SBansheeEditor/Source/BsScriptEditorApplication.cpp

@@ -17,6 +17,7 @@
 #include "BsGUIMenuBar.h"
 #include "BsPlayInEditorManager.h"
 #include "BsScriptRenderTarget.h"
+#include "BsFileSystem.h"
 
 namespace BansheeEngine
 {
@@ -173,6 +174,7 @@ namespace BansheeEngine
 	MonoString* ScriptEditorApplication::internal_GetFrameworkAssemblyPath()
 	{
 		Path assemblyFolder = MonoManager::instance().getFrameworkAssembliesFolder();
+		assemblyFolder.makeAbsolute(FileSystem::getWorkingDirectoryPath());
 
 		return MonoUtil::wstringToMono(MonoManager::instance().getDomain(), assemblyFolder.toWString());
 	}

+ 12 - 0
SBansheeEditor/Source/BsScriptPlatformInfo.cpp

@@ -32,6 +32,8 @@ namespace BansheeEngine
 		metaData.scriptClass->addInternalCall("Internal_SetFullscreen", &ScriptPlatformInfo::internal_SetFullscreen);
 		metaData.scriptClass->addInternalCall("Internal_GetResolution", &ScriptPlatformInfo::internal_GetResolution);
 		metaData.scriptClass->addInternalCall("Internal_SetResolution", &ScriptPlatformInfo::internal_SetResolution);
+		metaData.scriptClass->addInternalCall("Internal_GetDebug", &ScriptPlatformInfo::internal_GetDebug);
+		metaData.scriptClass->addInternalCall("Internal_SetDebug", &ScriptPlatformInfo::internal_SetDebug);
 	}
 
 	MonoObject* ScriptPlatformInfo::create(const SPtr<PlatformInfo>& platformInfo)
@@ -108,6 +110,16 @@ namespace BansheeEngine
 		thisPtr->getPlatformInfo()->windowedHeight = height;
 	}
 
+	bool ScriptPlatformInfo::internal_GetDebug(ScriptPlatformInfoBase* thisPtr)
+	{
+		return thisPtr->getPlatformInfo()->debug;
+	}
+
+	void ScriptPlatformInfo::internal_SetDebug(ScriptPlatformInfoBase* thisPtr, bool debug)
+	{
+		thisPtr->getPlatformInfo()->debug = debug;
+	}
+
 	ScriptWinPlatformInfo::ScriptWinPlatformInfo(MonoObject* instance)
 		:ScriptObject(instance)
 	{

+ 1 - 1
TODO.txt

@@ -26,7 +26,7 @@ Optional:
   - Add commands for breaking or reverting a scene object 
   - Test & finalize undo/redo system
  - Add "focus on object" key (F) - animate it: rotate camera towards then speed towards while zooming in (+ menu entry)
- - Ortographic camera views (+ gizmo in scene view corner that shows camera orientation)
+ - Ortographic camera views (+ gizmo in scene view corner that shows camera orientation) (Use custom handles and implement this?)
  - Cursors should be replaced with better ones, or at least hot-spots fixed
  - Drag and dropping a prefab onto the scene (or hierarchy) should work the same as with meshes
  - Add tooltips to toolbar items and other buttons with icons