2
0
Эх сурвалжийг харах

More work on documentation

BearishSun 8 жил өмнө
parent
commit
16e3390175

+ 62 - 0
Documentation/Manuals/Native/User/advResources.md

@@ -0,0 +1,62 @@
+Advanced resources					{#advResources}
+===============
+
+We've covered basic resource operations already, and this manual will cover a more advanced topics that allow you to do more with resources.
+
+# Resource lifetime {#advResources_a}
+Whenever you load a resource, that resource will be kept loaded until all references to that resource are lost. Each resource handle (e.g. **HMesh**) that exists represents a single reference. By default an additional "internal" reference is also created and held by the system internally. This ensures the resource stays loaded even when all handles are destroyed.
+
+This internal reference must be released by calling @ref bs::Resources::release() "Resources::release()", as we mentioned when we talk about resources before.
+
+You can also force the system to not create the internal reference by passing a custom @ref bs::ResourceLoadFlag "ResourceLoadFlag" to the @ref bs::Resources::load() "Resources::load()" method. This flag should not include the @ref bs::ResourceLoadFlag::KeepInternalRef "ResourceLoadFlag::KeepInternalRef".
+
+~~~~~~~~~~~~~{.cpp}
+// The default load flag is a combination of ResourceLoadFlag::KeepInternalRef and
+// ResourceLoadFlag::LoadDependencies. We don't include the former to prevent the
+// internal reference from being created.
+HMesh mesh = gResources().load("myMesh.asset", ResourceLoadFlag::LoadDependencies);
+~~~~~~~~~~~~~ 
+
+## Weak handles {#advResources_a_a}
+In case you want to keep a reference to a resource without incrementing the reference count you can use a weak handle instead of a normal one. Weak handles are represented by the @ref bs::WeakResourceHandle<T> "WeakResourceHandle<T>" class and can be retrieved from normal handles by calling @ref bs::ResourceHandle<T>::getWeak "ResourceHandle<T>::getWeak()". Other than that they are accessed the same as normal handles.
+
+~~~~~~~~~~~~~{.cpp}
+// Load a mesh and store a handle as normal
+HMesh mesh = gResources().load("myMesh.asset");
+
+// Create a weak handle
+WeakResourceHandle<Mesh> weakMesh = mesh.getWeak();
+~~~~~~~~~~~~~ 
+
+# Resource dependencies {#advResources_b}
+Whenever you load a resource the system will automatically enumerate all dependencies of that resource and attempt to load them as well. For example when loading a **Material** it will automatically load its **Shader** and any referenced **Texture** resources.
+
+In case you wish to prevent that you can not provide the @ref bs::ResourceLoadFlag::LoadDependencies "ResourceLoadFlag::LoadDependencies" flag when calling **Resources::load()** (provided by default).
+
+~~~~~~~~~~~~~{.cpp}
+// Loads a resource without any dependencies, nor keeps an internal reference
+HMesh mesh = gResources().load("myMesh.asset", ResourceLoadFlag::None);
+~~~~~~~~~~~~~ 
+
+# Asynchronous loading {#advResources_c}
+Resources can be loaded asynchronously (in the background) by calling @ref bs::Resources::loadAsync "Resources::loadAsync()". The interface is identical to **Resources::load()**. The main difference is that the returned handle might will contain a reference to a resource that hasn't been loaded yet. 
+
+You can check if a resource handle is pointing to a loaded resource by calling @ref bs::ResourceHandle::isLoaded "ResourceHandle::isLoaded()".
+
+~~~~~~~~~~~~~{.cpp}
+HMesh mesh = gResources().loadAsync("myMesh.asset");
+
+if(mesh.isLoaded())
+{
+	// Check if loaded before doing something
+}
+~~~~~~~~~~~~~ 
+
+> Note that not-yet-loaded resource handles can be provided to some engine systems, but not all. Generally a system will note in its documentation if it works with such resource handles.
+
+You can block the current thread until a resource is loaded by calling @ref bs::ResourceHandle::blockUntilLoaded "ResourceHandle::blockUntilLoaded()".
+
+~~~~~~~~~~~~~{.cpp}
+mesh.blockUntilLoaded();
+// Makes sure the mesh is loaded at this point
+~~~~~~~~~~~~~ 

+ 1 - 1
Documentation/Manuals/Native/User/resourceBasicsAndImport.md

@@ -21,7 +21,7 @@ Similar to scene objects and components, resources are also represented using ha
 You may treat the handles as pointers, using "->" to access their members, comparing them for equality or with *nullptr* to check their validity. 
 You may treat the handles as pointers, using "->" to access their members, comparing them for equality or with *nullptr* to check their validity. 
 
 
 # Customizing import
 # Customizing import
-Sometimes you need more control over import. In which case you can provide an additional **ImportOptions** object to the @ref bs::Importer::import<T> "Importer::import<T>" method. See the example below on how we change the texture format on import, using **TextureImportOptions**.
+Sometimes you need more control over import. In which case you can provide an additional **ImportOptions** object to the @ref bs::Importer::import<T> "Importer::import<T>()" method. See the example below on how we change the texture format on import, using **TextureImportOptions**.
 
 
 ~~~~~~~~~~~~~{.cpp}
 ~~~~~~~~~~~~~{.cpp}
 // Create an import options object specific to textures
 // Create an import options object specific to textures

+ 5 - 9
Documentation/Manuals/Native/User/resourceSavingAndLoading.md

@@ -6,7 +6,7 @@ All resource save and load operations are managed through the @ref bs::Resources
 # Saving
 # Saving
 Once a resource has been imported you can save it for later use. The advantage of saving a resource (instead of importing it every time) is performance - resource import is usually a costly operation. Saved resources remain in engine-friendly format and can be easily loaded later. 
 Once a resource has been imported you can save it for later use. The advantage of saving a resource (instead of importing it every time) is performance - resource import is usually a costly operation. Saved resources remain in engine-friendly format and can be easily loaded later. 
 
 
-To save a resource call @ref bs::Resources::save "Resources::save". Lets see an example where we import a texture and then save it for later use:
+To save a resource call @ref bs::Resources::save "Resources::save()". Lets see an example where we import a texture and then save it for later use:
 
 
 ~~~~~~~~~~~~~{.cpp}
 ~~~~~~~~~~~~~{.cpp}
 // Import a texture named "myTexture.jpg" from the disk
 // Import a texture named "myTexture.jpg" from the disk
@@ -19,24 +19,20 @@ gResources().save(texture, "myTexture.asset");
 Note that resources can also be created within the engine, and don't necessarily have to be imported. e.g. you can populate texture pixels or mesh vertices manually, and then save the resource in this same manner. We will show later how to manually create resources.
 Note that resources can also be created within the engine, and don't necessarily have to be imported. e.g. you can populate texture pixels or mesh vertices manually, and then save the resource in this same manner. We will show later how to manually create resources.
 
 
 # Loading
 # Loading
-Once a resource has been saved you can load it at any time using @ref bs::Resources::load "Resources::load". Lets load the texture we just saved:
+Once a resource has been saved you can load it at any time using @ref bs::Resources::load "Resources::load()". Lets load the texture we just saved:
 
 
 ~~~~~~~~~~~~~{.cpp}
 ~~~~~~~~~~~~~{.cpp}
 HTexture loadedTexture = gResources().load<Texture>("myTexture.asset");
 HTexture loadedTexture = gResources().load<Texture>("myTexture.asset");
 ~~~~~~~~~~~~~
 ~~~~~~~~~~~~~
 
 
-> Extra: If you attempt to load a resource that has already been loaded, the system will return the existing resource.
-
-> Extra: You can load resources asynchronously (in the background) by calling @ref bs::Resources::loadAsync "Resources::loadAsync"
+> If you attempt to load a resource that has already been loaded, the system will return the existing resource.
 
 
 # Unloading
 # Unloading
-Note that the resource system by default never unloads a loaded resource, unless told explicitly. To unload a resource call @ref bs::Resources::release "Resources::release".
+Note that the resource system by default never unloads a loaded resource, unless told explicitly. To unload a resource call @ref bs::Resources::release "Resources::release()".
 
 
 To unload the texture we loaded previously:
 To unload the texture we loaded previously:
 ~~~~~~~~~~~~~{.cpp}
 ~~~~~~~~~~~~~{.cpp}
 gResources().release(loadedTexture);
 gResources().release(loadedTexture);
 ~~~~~~~~~~~~~
 ~~~~~~~~~~~~~
 
 
-> Note that if you called **Resources::load** multiple times, you must also call **Resources::release** the same amount of times.
-
-> Extra: You can also force the system to automatically unload a resource when it is no longer being referenced. Just make sure you don't set the @ref bs::ResourceLoadFlag::KeepInternalRef "ResourceLoadFlag::KeepInternalRef" flag as the second parameter of @ref bs::Resources::load "Resources::load" (set by default).
+> Note that if you called **Resources::load()** multiple times, you must also call **Resources::release** the same amount of times.

+ 133 - 0
Documentation/Manuals/Native/customImporters.md

@@ -0,0 +1,133 @@
+Creating custom importers						{#customImporters}
+===============
+[TOC]
+
+Importers process raw resources in a third-party format (like FBX mesh or a PNG image) into an engine-ready format (e.g. a **Mesh** or a **Texture**). Banshee has an extensible importer system so you may easily add your own importers, either for existing resource types or for new ones. This way you can add support for new third party file formats.
+
+To implement your own importer you need to implement the @ref bs::SpecificImporter "SpecificImporter" interface.
+
+# Implementing SpecificImporter {#customImporters_a}
+Implementing this interface involves implementation of the following methods:
+ * @ref bs::SpecificImporter::isExtensionSupported "SpecificImporter::isExtensionSupported()" - Receives a file extension and returns true or false depending if the importer can process that file. Used by the importer to find which importer plugin to use for import of a specific file.
+ * @ref bs::SpecificImporter::isMagicNumberSupported "SpecificImporter::isMagicNumberSupported()" - Similar to the method above, but receives a magic number (first few bytes of a file) instead of the extension, as this is the more common way of identifying files on non-Windows systems.
+ * @ref bs::SpecificImporter::import "SpecificImporter::import()" - Receives a path to a file, as well as a set of import options. This is the meat of the importer where you will read the file and convert it into engine ready format. When done the method returns a @ref bs::Resource "Resource" of a valid type, or null if it failed. The method should take into account the import options it was provided (if your importer supports any).
+ 
+~~~~~~~~~~~~~{.cpp}
+//	Simple importer for plain text types.
+class PlainTextImporter : public SpecificImporter
+{
+public:
+	bool isExtensionSupported(const WString& ext) const override
+	{
+		WString lowerCaseExt = ext;
+		StringUtil::toLowerCase(lowerCaseExt);
+
+		return lowerCaseExt == L"txt";
+	}
+
+	bool isMagicNumberSupported(const UINT8* magicNumPtr, UINT32 numBytes) const override
+	{
+		// Magic numbers don't make sense for plain text files, so we rely on extension checking
+		return true;
+	}
+
+	SPtr<Resource> import(const Path& filePath, SPtr<const ImportOptions> importOptions) override
+	{
+		SPtr<DataStream> stream = FileSystem::openFile(filePath);
+		WString textData = stream->getAsWString();
+
+		// ... initialize some resource with the text and return
+	}
+};
+~~~~~~~~~~~~~ 
+ 
+# Registering SpecificImporter {#customImporters_b}
+To register your **SpecificImporter** implementation with the importer system you must call @ref bs::Importer::_registerAssetImporter "_registerAssetImporter()". You can do this after application start-up, or during by implementing your own **Application** class as described in the @ref advancedStartup manual.
+
+~~~~~~~~~~~~~{.cpp}
+Application::startUp(...);
+
+PlainTextImporter* myImporter = bs_new<PlainTextImporter>();
+gImporter()._registerAssetImporter(myImporter);
+~~~~~~~~~~~~~ 
+
+> Your importer must be allocated using a general purpose allocator (**bs_new**) because the importer system automatically frees it on shutdown, and it doesn't expect any special memory types.
+
+Optionally you can do this on the higher level by providing a list of importers to @ref bs::Application::startUp "Application::startUp()" method. This method expects a list of dynamic library file-names, which means you must implement your importer as a plugin, as described in the @ref plugins manual.
+
+# Optional features {#customImporters_c}
+Your importer may also optionally implement any of the following features.
+
+## Import options {#customImporters_c_a}
+If you want to allow the user to control how is a file imported, you need to implement the @ref bs::ImportOptions "ImportOptions" class. The class has no special interface except the requirement to create a RTTI object for it.
+
+~~~~~~~~~~~~~{.cpp}
+// Import options for our PlainTextImporter. Contains a single option
+// that allows the user to choose whether or not to convert all text
+// to lowercase on import.
+class PlainTextImportOptions : public ImportOptions
+{
+public:
+	// Converts all text to lowercase on import
+	bool convertToLowercase = false;
+	
+	friend class PlainTextImportOptionsRTTI;
+	static RTTITypeBase* getRTTIStatic() { return PlainTextImportOptionsRTTI::instance(); }
+	RTTITypeBase* getRTTI() const override { return getRTTIStatic(); }
+};
+~~~~~~~~~~~~~ 
+
+The RTTI is implemented as normal, as described in the @ref serializingObjects manual.
+
+You can then instantiate import options and provide them to the call of @ref bs::Importer::import "Importer::import()" and they will be passed through all the way to your **SpecificImporter** implementation. After that you can read the relevant options and perform the import accordingly.
+
+~~~~~~~~~~~~~{.cpp}
+class PlainTextImporter : public SpecificImporter
+{
+public:
+	// ... other importer code
+
+	SPtr<Resource> import(const Path& filePath, SPtr<const ImportOptions> importOptions) override
+	{
+		const PlainTextImportOptions* myIO = static_cast<const PlainTextImportOptions*>(importOptions.get());
+	
+		if(myIO->convertToLowercase)
+		{
+			// Do something
+		}
+		else
+		{
+			// Do something else
+		}
+		
+		// ... import and return a resource
+	}
+};
+~~~~~~~~~~~~~ 
+
+## Multiple resources {#customImporters_c_b}
+If a single external file can be interpreted as multiple engine resources you should override the @ref bs::SpecificImporter::importAll "SpecificImporter::importAll()" method. For example this is the case with FBX format which can contain a mesh and one or multiple animations.
+
+**SpecificImporter::importAll()** method will return a list of resources, each with a unique identifier which allows external code to know what those resources are. One of the resources must always be considered primary, and that's the resource that should be returned by **SpecificImporter::import()** (others should be ignored). The primary resource must have the "primary" identifier, while you are free to add custom identifiers for every other resource.
+ 
+~~~~~~~~~~~~~{.cpp}
+class PlainTextImporter : public SpecificImporter
+{
+public:
+	// ... other importer code
+
+	Vector<SubResourceRaw> importAll(const Path& filePath, SPtr<const ImportOptions> importOptions) override
+	{
+		Vector<SubResourceRaw> output;
+	
+		// ... read the file and generate resources
+	
+		output.push_back({ "primary", someResourceA });
+		output.push_back({ "otherOne", someResourceB });
+		output.push_back({ "anotherOne", someResourceC });
+		return output;
+	}
+};
+~~~~~~~~~~~~~ 
+
+Then you can call @ref bs::Importer::importAll "Importer::importAll()" to import multiple resources from a file.

+ 142 - 0
Documentation/Manuals/Native/customResources.md

@@ -0,0 +1,142 @@
+Creating new resource types					{#customResources}
+===============
+[TOC]
+
+Throughout the previous manuals we have shown how to import, load and save a variety of resource types. You can also add brand new resource types of your own.
+
+# Custom resource type {#customResources_a}
+To create a custom resource type you need to implement the @ref bs::Resource "Resource" interface. **Resource** derives from both @ref bs::CoreObject "CoreObject" and @ref bs::IReflectable "IReflectable". These two classes make up majority of its interface, and we have already shown how to implement them in the @ref coreThread and @ref serializingObjects manuals.
+
+~~~~~~~~~~~~~{.cpp}
+class MyResource : public Resource
+{
+public:
+	MyResource()
+		:Resource(false)
+	{ }
+	
+	UINT32 someData; // Fields should be referenced by the RTTI code, so they get saved
+	UINT32 moreData; 
+
+	friend class MyResourceRTTI;
+	static RTTITypeBase* getRTTIStatic() { return MyResourceRTTI::instance(); }
+	RTTITypeBase* getRTTI() const override { return getRTTIStatic(); }
+};
+
+// MyResourceRTTI implemented as a standard RTTI object, as discussed previously
+~~~~~~~~~~~~~
+
+The constructor of **Resource** accepts one parameter, signifying whether or not your resource requires a core-thread representation. If you set this to false then you don't need to implement any of the core thread sync functionality (as described in @ref coreThread manual), and @ref bs::CoreObject::getCore() "CoreObject::getCore()" method will simply return null. In general if your resource doesn't need to be used on the core thread set this to false. On the other hand, if it is used by systems like the renderer or the render API, set it to true.
+
+# Custom resource handle {#customResources_b}
+To create a handle for your custom resource, similarly to **HTexture** or **HMesh**, simply create a *typedef* using the @ref bs::ResourceHandle<T> "ResourceHandle<T>" type. Generally you want to define this in some header included by all files, for convenience.
+
+~~~~~~~~~~~~~{.cpp}
+typedef ResourceHandle<MyResource> HMyResource;
+~~~~~~~~~~~~~
+
+# Custom resource creation {#customResources_c}
+When creating a new instance of your resource you need to follow all the rules for **CoreObject** creation. This will yield you a shared pointer to the resource. To create a handle to the resource you must call @ref bs::Resources::_createResourceHandle "Resources::_createResourceHandle()". Because of this complex initialization procedure you are encouraged to write a static **create()** method that handles all of it internally, same as for **CoreObject**%s.
+
+~~~~~~~~~~~~~{.cpp}
+class MyResource : public Resource
+{
+public:
+	// ... other MyResource code
+	
+	static HMyResource create()
+	{
+		// Standard core object initialization
+		SPtr<MyResource> sptr = bs_core_ptr<MyResource>(bs_new<MyResource>());
+		sptr->_setThisPtr(sptr);
+		sptr->initialize();
+	
+		// Create a handle
+		return static_resource_cast<MyResource>(gResources()._createResourceHandle(sptr));
+	}
+};
+~~~~~~~~~~~~~
+
+# Optional features {#customResources_d}
+Implementations above represent the minimal set of features to create your own resource, but there are some optional features we'll cover in this section.
+
+## Dependencies {#customResources_d_a}
+If your custom resource is dependant on some other resource make sure to implement the @ref bs::Resource::getResourceDependencies "Resource::getResourceDependencies()" method which should return a list of all resources it is dependant upon. For example, a **Material** resource is dependant on the **Shader** resource, as well as any **Texture** resources set as its parameters.
+
+~~~~~~~~~~~~~{.cpp}
+// Assuming our MyResource class is dependant on a texture
+class MyResource : public Resource
+{
+public:
+	// ... other MyResource code
+	
+	void getResourceDependencies(FrameVector<HResource>& dependencies) const override
+	{
+		dependencies.push_back(mSomeTexture);
+	}
+	
+private:
+	HTexture mSomeTexture;
+};
+~~~~~~~~~~~~~
+
+Such dependant resources will be checked when @ref bs::ResourceHandleBase::isLoaded "HResource::isLoaded()" or @ref bs::ResourceHandleBase::blockUntilLoaded "HResource::blockUntilLoaded()" is called with `checkDependencies` parameter enabled. This ensures you have an easy to way to check if a resource is truly usable (it is loaded, as well as everything it depends on). 
+
+## Resource listener {#customResources_d_b}
+If an object is interested in learning when a certain resource has been loaded or updated you can implement the @ref bs::IResourceListener "IResourceListener" interface. This interface can be implemented both on resources and on normal objects.
+
+To implement it you must return a list of resource handles you are interested in tracking by implementing the @ref bs::IResourceListener::getListenerResources "IResourceListener::getListenerResources()" method. Whenever the dependant resource list changes you should call @ref bs::IResourceListener::markListenerResourcesDirty "IResourceListener::markListenerResourcesDirty()".
+
+~~~~~~~~~~~~~{.cpp}
+class SomeClass : public IResourceListener
+{
+public:
+	void setTexture(const HTexture& tex)
+	{
+		mSomeTexture = tex;
+		
+		// This lets the listener know the list of listener resources changed and a new list needs to be retrieved from getListenerResources()
+		markListenerResourcesDirty();
+	}
+
+	void getListenerResources(Vector<HResource>& resources)
+	{
+		// Place any resources you are interested in listening for in the "resources" vector
+		if (mSomeTexture != nullptr)
+			resources.push_back(mSomeTexture);
+	}
+	
+private:
+	HTexture mSomeTexture;
+};
+~~~~~~~~~~~~~
+
+Whenever a resource you are listening for is loaded @ref bs::IResourceListener::notifyResourceLoaded "IResourceListener::notifyResourceLoaded()" will be called. Similarly whenever a resource is re-imported @ref bs::IResourceListener::notifyResourceChanged "IResourceListener::notifyResourceChanged()" will be called.
+
+~~~~~~~~~~~~~{.cpp}
+class SomeClass : public IResourceListener
+{
+public:
+	// ... other SomeClass code
+	
+	void notifyResourceLoaded(const HResource& resource)
+	{
+		// "resource" could be an asynchronously loaded resource, and we wait on initialization of this object until it is loaded
+		initialize();
+	}
+
+	void notifyResourceChanged(const HResource& resource)
+	{
+		// User could have triggered a reimport for the resource in which case we might need to do some form of re-initialization.
+		// This is especially useful for resource hot-swap, where user can just reimport a resource with new data and the system
+		// automatically starts using a new resource throughout the application.
+		reinitialize();
+	}
+};
+~~~~~~~~~~~~~
+
+**IResourceListener::notifyResourceLoaded()** triggers when a resource is loaded in response to a @ref bs::Resources::load "Resources::load()" or @ref bs::Resources::loadAsync "Resources::loadAsync()" call.
+
+**IResourceListener::notifyResourceChanged()** triggers whenever user calls @ref bs::Importer::reimport "Importer::reimport()". You may also trigger it manually by calling @ref bs::Resources::update() "Resources::update()". This method will update the contents of a resource handle with new resource data, and trigger any listeners.
+
+**Resources** module also provides @ref bs::Resources::onResourceLoaded "Resources::onResourceLoaded", @ref bs::Resources::onResourceDestroyed "Resources::onResourceDestroyed" and @ref bs::Resources::onResourceModified "Resources::onResourceModified" events which may be used for a similar purpose, but **IResourceListener** is more efficient since it only tracks specific resources, while these events trigger for every resource.

+ 0 - 25
Documentation/Manuals/Native/import.md

@@ -1,25 +0,0 @@
-Creating custom importers						{#customImporters}
-===============
-[TOC]
-
-Importers process a raw resource in a third-party format (like FBX mesh or a PNG image) into an engine-ready format (e.g. a @ref bs::Mesh "Mesh" or a @ref bs::Texture "Texture"). Banshee has an extensible importer system so you may easily add your own, either for existing resource types, or for new ones. If you are also interested in creating new resource types check out [this manual](@ref resources).
-
-On the user-facing level resource import works through the @ref bs::Importer "Importer" module. You call its @ref bs::Importer::import "Importer::import" method which takes a path to the resource you want to import, and the system automatically finds the necessary importer plugin (if one is available) and returns the resource in an engine ready format. Optionally you can also supply the importer with @ref bs::ImportOptions "ImportOptions" to control resource import in more detail.
-
-To implement your own importer you need to implement the @ref bs::SpecificImporter "SpecificImporter" interface.
-
-# Implementing SpecificImporter # {#customImporters_a}
-Implementing this interface involves implementation of the following methods:
- * @ref bs::SpecificImporter::isExtensionSupported "isExtensionSupported" - Receives an extension and returns true or false depending if the importer can process that file. Used by the importer to find which importer plugin to use for import of a specific file.
- * @ref bs::SpecificImporter::isMagicNumberSupported "isMagicNumberSupported" - Similar to the method above, but receives a magic number (first few bytes of a file) instead of the extension, as this is the more common way of identifying files on non-Windows systems.
- * @ref bs::SpecificImporter::import "import" - Receives a path to a file, as well as a set of import options. This is the meat of the importer where you will read the file and convert it into engine ready format. When done the method returns a @ref bs::Resource "Resource" of a valid type, or null if it failed. The method should take into account the import options it was provided (if your importer supports any).
- 
-You may also optionally implement the following methods:
- * @ref bs::SpecificImporter::createImportOptions "createImportOptions" - If your importer supports specific import options this should return a brand new empty instance of such import options. These will eventually be provided to the @ref bs::SpecificImporter::import "import" method. Import options must implement @ref bs::ImportOptions "ImportOptions" and you may include any necessary fields in your implementation. You must also [implement RTTI](@ref rtti) for your custom import options. You should strive to use same type of import options for same resource types (for example all textures use @ref bs::TextureImportOptions "TextureImportOptions").
- * @ref bs::SpecificImporter::importAll "importAll" - Sometimes a single third-party resource can contain multiple engine resources (for a example an .fbx may contain both a mesh and animation). In such cases you will want to implement this method, which allows you to return multiple resources, each with a unique identifier. One of the resources must always be considered primary, and that's the resource that should be returned by @ref bs::SpecificImporter::import "import" (others should be ignored). In this method the primary resource must have the "primary" identifier, while you are free to add custom identifiers for every other resource.
- 
-Once your importer is implemented you must register it with the global importer system. You may do this by calling @ref bs::Importer::_registerAssetImporter "_registerAssetImporter" with an instance of your importer. It should be allocated using the general allocator and will be freed automatically on system shutdown.
-
-Optionally you can do this on the higher level by providing a list of importers to @ref bs::Application::startUp "Application::startUp" method. This methods expects a list of dynamic library file-names, which means you must implement your importer as a [plugin](@ref customPlugins).
-
-See @ref bs::PlainTextImporter "PlainTextImporter" for an implementation of a very simple importer that just imports raw textual files.

+ 7 - 11
Documentation/Manuals/Native/manuals.md

@@ -67,6 +67,7 @@ A complete set of manuals covering all major functionality provided by Banshee,
  - [Creating meshes](@ref creatingMeshes)
  - [Creating meshes](@ref creatingMeshes)
  - [Advanced startup](@ref advancedStartup)
  - [Advanced startup](@ref advancedStartup)
  - [Advanced RTTI](@ref advancedRtti)
  - [Advanced RTTI](@ref advancedRtti)
+ - [Advanced resources](@ref advResources)
  - [Prefabs](@ref prefabs)
  - [Prefabs](@ref prefabs)
  - [Cursors](@ref cursors)
  - [Cursors](@ref cursors)
  - [Profiling](@ref cpuProfiling)
  - [Profiling](@ref cpuProfiling)
@@ -101,23 +102,18 @@ A set of manuals covering advanced functionality intented for those wanting to e
 - **Renderer**
 - **Renderer**
  - [Renderer extensions](@ref rendererExtensions)
  - [Renderer extensions](@ref rendererExtensions)
  - [Creating a renderer plugin](@ref customRenderer)
  - [Creating a renderer plugin](@ref customRenderer)
- 
+- **Resources**
+ - [Creating new resource types](@ref customResources)
+ - [Creating custom importers](@ref customImporters)
  
  
 ## General guides
 ## General guides
 Name                                      | Description
 Name                                      | Description
 ------------------------------------------|-------------
 ------------------------------------------|-------------
-[Resources](@ref resources)  			  | Explains how resources work, including saving, loading and creating brand new resource types.
 [Scripting](@ref scripting)               | Shows you how to interact with the scripting system, and how to expose C++ objects to the scripting API.
 [Scripting](@ref scripting)               | Shows you how to interact with the scripting system, and how to expose C++ objects to the scripting API.
 [BSLFX](@ref bsl)    	  		  		  | Provides a reference for the Banshee Shading Language syntax.
 [BSLFX](@ref bsl)    	  		  		  | Provides a reference for the Banshee Shading Language syntax.
 [Custom GUI elements](@ref customGUI)     | Shows you how to create custom GUI elements, manually render text or modify GUI system in a general way.
 [Custom GUI elements](@ref customGUI)     | Shows you how to create custom GUI elements, manually render text or modify GUI system in a general way.
-[Custom importers](@ref customImporters)  | Shows you how to create importers that handle conversion of third party resources into engine ready formats.
+[Meshes](@ref meshes)                     | Shows you how to create, use and manipulate meshes.
+[Materials](@ref materials)				  | Shows you how to create and use materials and shaders.
 [Quick reference](@ref quickref)          | Provides a few bits of commonly required information, that might be hard to remember otherwise.
 [Quick reference](@ref quickref)          | Provides a few bits of commonly required information, that might be hard to remember otherwise.
 [Porting](@ref porting)                   | Information about how to go on about porting Banshee to a different operating system.
 [Porting](@ref porting)                   | Information about how to go on about porting Banshee to a different operating system.
-[Code style](@ref style)                  | Information about code style used when writing Banshee.
-
-## Low level render API
-
-Name                                      | Description
-------------------------------------------|-------------
-[Meshes](@ref meshes)                     | Shows you how to create, use and manipulate meshes.
-[Materials](@ref materials)				  | Shows you how to create and use materials and shaders.
+[Code style](@ref style)                  | Information about code style used when writing Banshee.

+ 0 - 145
Documentation/Manuals/Native/resources.md

@@ -1,145 +0,0 @@
-Resources						{#resources}
-===============
-[TOC]
-
-Resources are objects that can be saved and loaded to/from a disk, can be referenced in a unique manner, and have their lifetime managed by the resources manager. Objects like @ref bs::Texture "Texture", @ref bs::Mesh "Mesh" or @ref bs::Shader "Shader" are all resources.
-
-A resource in Banshee is represented by the @ref bs::Resource "Resource" class. A @ref bs::Resource "Resource" is a @ref bs::CoreObject "CoreObject" and if you're not familiar with core objects you should read the [core object](@ref coreThread) manual.
-
-All resources in Banshee are managed by the @ref bs::Resources "Resources" manager. Use @ref bs::gResources "gResources()" to access its instance easily.
-
-# Loading {#resources_a}
-To load a resource call @ref bs::Resources::load "Resource::load" with a file path to the resource. If the path is valid a handle to the resource will be returned.
-
-You can also call @ref bs::Resources::loadAsync "Resource::loadAsync". Unlike the previous method this method will not block the current thread and will instead proceed with loading the resource on a separate thread. You will receive an uninitialized resource handle. You must use @ref bs::ResourceHandleBase::isLoaded "HResource::isLoaded" to check if the handle is loaded before using it, or @ref bs::ResourceHandleBase::blockUntilLoaded "HResource::blockUntilLoaded" to force the current thread to wait until it is loaded.
-
-An example of both synchronous and asynchronous loads:
-~~~~~~~~~~~~~{.cpp}
-// Load a texture synchronously
-HTexture textureA = gResources().load<Texture>("textureA.asset");
-
-// Load a texture asynchronously
-HTexture textureB = gResources().loadAsync<Texture>("textureB.asset");
-
-while(!textureB.isLoaded())
-{
-	// Do something else
-}
-~~~~~~~~~~~~~
-
-The system internally keeps track of all resources, so calling load multiple times in a row will return a previously loaded resource if one exists.
-
-## Resource handles {#resources_a_a}
-As we saw in the previous example resources are referenced by @ref bs::ResourceHandleBase "resource handles". Different handles exist for each resource type, and they always being with a prefix "H" followed by the resource name, e.g. @ref bs::ResourceHandleBase "HTexture".
-
-Handles act like pointers, and you can access the resource within the handle by using the pointer member "->" operator. Using this operator is only valid if the handle points to a loaded resource (@ref bs::ResourceHandleBase::isLoaded "HResource::isLoaded" returns true). Using the normal member access "." operator works on the handle data directly and is always safe.
-
-Handles are used instead of pointers because:
- - Lifetime of the resource can be automatically managed
- - User can keep a reference to an unloaded resources
- - Are handled specially when serializing/deserializing objects
- 
-A little more elaboration for the last point. If you have read the [RTTI](@ref rtti) manual you know that objects can reference different field types. And resource handles can be referenced by "Reflectable" field types, allowing you to easily save/load references to resources within your objects with no additional code.
-
-Each handle internally stores an UUID that uniquely identifies the resource. You can access it by calling @ref bs::ResourceHandleBase::getUUID() "HResource::getUUID".
-
-## Resource dependencies {#resource_a_b}
-We mentioned in the last section that objects (including resources) can reference resources. For example a @ref bs::Font "Font" resource will reference @ref bs::Texture "Texture" resources which store its pre-rendered font glyphs.
-
-When loading a resource you have a choice to load only that exact resource, or if you wish to load all of its dependencies as well. This is handled by the `loadDependencies` parameter of both @ref bs::Resources::load "Resource::load" and @ref bs::Resources::loadAsync "Resource::loadAsync". If you load a resource without dependencies, and need them later you can just call @ref bs::Resources::load "Resource::load" or @ref bs::Resources::loadAsync "Resource::loadAsync" on that same resource with `loadDependencies` set to true.
-
-## Resource lifetime {#resource_a_c}
-Once a resource is loaded it will stay loaded until all references (handles) to it go out of scope. Once the last handle goes out of scope the system will unload the resource.
-
-If you wish to keep a handle to a resource that doesn't keep it loaded, you can use @ref bs::TResourceHandle<T, true> "WeakResourceHandle<T>". You retrieve such a handle by calling @ref bs::TResourceHandle<T, WeakHandle>::getWeak "HResource::getWeak" method on a normal handle. You can convert a weak handle into a normal handle by calling @ref bs::TResourceHandle<T, WeakHandle>::lock "HResource::lock". Before doing so you should verify that the resource is still loaded.
-
-Weak handles can also be used for referencing resources for serialization/deserialization, same as normal handles can. However a weak handle will never force the referenced resource to load, even if `loadDependencies` parameter is set to true when loading. You must call @ref bs::Resources::load(const WeakResourceHandle<T>&, ResourceLoadFlags) "Resource::load" to manually load such a resource.
-
-You can also force a resource to stay loaded, even after all the handles go out of scope. You do it by setting `keepInternalReference` of @ref bs::Resources::load "Resource::load" or @ref bs::Resources::loadAsync "Resource::loadAsync" to true. In order to free such a resource you should call @ref bs::Resources::release "Resources::release". Be aware that each call to @ref bs::Resources::load "Resource::load" or @ref bs::Resources::loadAsync "Resource::loadAsync" with this parameter enabled will require a separate @ref bs::Resources::release "Resources::release" call. @ref bs::Resources::release "Resources::release" will not release the resource immediately if there are still active handles to it, it will merely remove the internal reference so the resource can be freed when the handles go out of scope.
-
-You can also use @ref bs::Resources::unloadAllUnused "Resources::unloadAllUnused" which will unload any resource that has no handles referencing it.
-
-# Saving {#resources_b}
-To save a resource to the disk call @ref bs::Resources::save(const HResource&, const Path&, bool) "Resources::save". You need to provide a handle to the resource, and a path to save the resource to.
-
-If a resource already exists on the disk (i.e. it was created by @ref bs::Resources::load "Resource::load" instead of manually), you can instead call @ref bs::Resources::save(const HResource&) "Resources::save" to overwrite the existing file.
-
-An example:
-~~~~~~~~~~~~~{.cpp}
-TEXTURE_DESC desc;
-desc.type = TEX_TYPE_2D;
-desc.width = 1280;
-desc.heigth = 720;
-desc.format = PF_R8G8B8A8;
-
-HTexture texture = Texture::create(desc);
-... fill texture with some data ...
-
-gResources().save(texture, "myTexture.asset");
-~~~~~~~~~~~~~
-
-# Creating your own resource {#resources_c}
-To create your own resource, derive a class from @ref bs::Resource "Resource" and:
- - Implement the @ref bs::CoreObject "CoreObject" interface as described in the [core thread](@ref coreThread) manual
- - Implement a RTTI object as described in the [RTTI](@ref rtti) manual
- 
-Every resource is also a @ref bs::CoreObject "CoreObject", but not every resource actually needs a core thread representation (for example a @ref bs::Font "Font" is not relevant on the core thread). In such a case you can provide false to the `requiresGpuInitialization` parameter of the @ref bs::CoreObject "CoreObject" constructor. This also means you can ignore implementing most of the @ref bs::CoreObject "CoreObject" interface.
-
-When creating resources, aside from the normal @ref bs::CoreObject "CoreObject" creation requirements, you must also call @ref bs::Resources::_createResourceHandle "Resources::_createResourceHandle". This method accepts a resource pointer and returns a resource handle. Similar to @ref bs::CoreObject "CoreObject" initialization, this should probably be wrapped as a part of a static `create` method and hidden from the user.
-
-See @ref bs::Font "Font" implementation in `BsFont.cpp` for an example of a simple resource implementation.
-
-## Exposing resources to scripting {#resources_c_a}
-Once you have a custom resource you might want to expose it to the scripting API. Take a look at the [scripting interop guide](@ref scripting) to learn how to create scripting API objects. 
-
-Every resource scripting interop object must implement @ref bs::TScriptResource "TScriptResource", but other than that creating GUI interop objects is the same as the general case described in the guide above. See @ref bs::ScriptFont "ScriptFont" in `BsScriptFont.cpp` for an example.
-
-Creating managed GUI objects is again the same as the general case. Take a look at the managed `Font` implementation in `Font.cs` for an example.
-
-Resources are unlike most other scripting objects because they can be created in the native code and then used in the managed code, or vice versa. Resources are also serialized by reference, which requires some specialized code for managed serialization to properly recognize the resource. 
-
-### Native <-> managed resource conversion {#resources_c_a_a}
-When a resource is created in native code, but needs to be passed to scripting code, the system creates a script interop object and a managed object, which wrap the native resource. The system also needs to be aware if such managed representation of an object already exists, and return an existing one if so. This is the job of the @ref bs::ScriptResourceManager "ScriptResourceManager".
-
-You will need to update this manager with your custom resource type. Relevant methods are:
- - @ref bs::ScriptResourceManager::createScriptResource "ScriptResourceManager::createScriptResource" - Creates a new managed object instance from a native resource (only valid if one doesn't already exist). This method has two overloads, and is specialized for specific resource types. Make sure to add a specialization for both overloads, with your custom resource type. And also update the specialization that accepts a generic @ref bs::ResourceHandleBase "HResource" with an entry of your own resource. You can use existing resources as an example of how it should be done, only the type names need changing.
- - @ref bs::ScriptResourceManager::getScriptResource<RetType, InType> "ScriptResourceManager::getScriptResource" - Retrieves an existing managed object instance from a native resource handle. Optionally creates the managed object if one doesn't already exist. Add a specialization for your own resource type similar to methods above.
-
-### Managed resource serialization {#resources_c_a_b}
-In order for your new resource type to be properly referenced by serialized managed objects you need to make a few more additions:
- - First of append a new resource type to the @ref bs::ScriptReferenceType "ScriptReferenceType" enum.
- - Append a new entry to @ref bs::ManagedSerializableTypeInfoRef::getMonoClass "ManagedSerializableTypeInfoRef::getMonoClass" which maps the enum entry above to your resource script interop object type
- - Append a new entry to @ref bs::ManagedSerializableTypeInfoRef::isTypeLoaded "ManagedSerializableTypeInfoRef::isTypeLoaded" so it always returns true if your resource is encountered (since it's built-in, it's always loaded)
- - Append a new entry in the @ref bs::ScriptAssemblyManager::getTypeInfo "ScriptAssemblyManager::getTypeInfo" which maps the managed resource object type to the enum above
- - Append a new entry to the `getResourceFieldLookup` method in `BsManagedSerializableField.cpp` which uses the native <-> managed conversion methods to map between a native and a managed instance of a resource during serialization/deserialization
- 
-For all of these you can use examples of existing resources which already exist within the mentioned methods, it is just a matter of changing the type/enum names for your own resource. 
- 
-### Other {#resources_c_a_c}
-In order for your resources to be properly recognized by GUI drop fields, as well as the project library append new entries to @ref bs::ScriptResource::getClassFromTypeId "ScriptResource::getClassFromTypeId" and @ref bs::ScriptResource::getTypeFromTypeId "ScriptResource::getTypeFromTypeId" which map between the enum above and the RTTI type ID of the resource.
-
-# Advanced {#resources_d}
-This section lists some more advanced (and optional) features when dealing with resources.
-
-## Dependencies {#resources_d_a}
-When creating a custom resource that is dependant on some other resource(s), make sure to implement @ref bs::Resource::getResourceDependencies "Resource::getResourceDependencies" which returns a list of all resources it is dependant upon. These resources will be checked when @ref bs::ResourceHandleBase::isLoaded "HResource::isLoaded" or @ref bs::ResourceHandleBase::blockUntilLoaded "HResource::blockUntilLoaded" is called with `checkDependencies` parameter enabled.
-
-This does not impact the dependencies that are loaded with @ref bs::Resources::load "Resources::load". ALL referenced non-weak resource handles will be loaded regardless of @ref bs::Resource::getResourceDependencies "Resource::getResourceDependencies" implementation.
-
-## Resource listener {#resources_d_b}
-If an object is interested in learning when a certain resource has been loaded, or updated you can implement the @ref bs::IResourceListener "IResourceListener" interface. For example this can be used for refreshing a @ref bs::Material "Material" if the @ref bs::Shader "Shader" it is dependant upon changes. This also allows you to wait when initializing an object dependant on other resources, in case those resources are being loaded asynchronously.
-
-To implement it you must return a list of resource handles you are interested in tracking by implementing the @ref bs::IResourceListener::getListenerResources "IResourceListener::getListenerResources" method. Whenever the dependant resource list changes you should call @ref bs::IResourceListener::markListenerResourcesDirty "IResourceListener::markListenerResourcesDirty".
-
-After you have set up the listener resources, whenever such a resource is loaded @ref bs::IResourceListener::notifyResourceLoaded "IResourceListener::notifyResourceLoaded" will be called, and when it is updated (via @ref bs::Resources::update "Resources::update") @ref bs::IResourceListener::notifyResourceChanged "IResourceListener::notifyResourceChanged" will be called.
- 
-@ref bs::Resources "Resources" also provides @ref bs::Resources::onResourceLoaded "Resources::onResourceLoaded", @ref bs::Resources::onResourceDestroyed "Resources::onResourceDestroyed" and @ref bs::Resources::onResourceModified "Resources::onResourceModified" events which may be used for similar purpose, but @ref bs::IResourceListener "IResourceListener" is more efficient since it only tracks specific resources.
-
-## Resource manifest {#resources_d_c}
-Every time a resource is saved via @ref bs::Resources::save "Resources::save", its UUID and file path is stored in a @ref bs::ResourceManifest "ResourceManifest". This manifest is used primarily by the deserialization process, so it knows to find resource file paths from the resource handle UUIDs that were serialized.
-
-Without this manifest every time a user saved an object referencing a resource (like a scene), then restarted the application the system would no longer know where to locate the referenced resources. When using the editor or the scripting API the manifest is managed for you, but if you are building an application on a lower level, you must manage it yourself.
-
-Use @ref bs::Resources::getResourceManifest "Resources::getResourceManifest" to retrieve a manifest. By default only one manifest with the name "Default" is registered. You will need to save this manifest before application shut-down and restore it upon application start-up. To restore a manifest call @ref bs::Resources::registerResourceManifest "Resources::registerResourceManifest".
-
-You can register multiple manifests and the system will scan all of them to find resource paths. If a resource exists in multiple ones, then the latest registered one takes priority. You can unregister a manifest by calling @ref bs::Resources::unregisterResourceManifest "Resources::unregisterResourceManifest"

+ 34 - 0
Documentation/Manuals/Native/scripting.md

@@ -257,3 +257,37 @@ class ScriptGUIButton : public ScriptObject<ScriptGUIButton, ScriptGUIElementBas
 This ensures that all GUI elements can now be accessed through the common `ScriptGUIElementBase` interface. Which is important if `GUIElement` provides some internal method calls shared between all GUI element types, otherwise we wouldn't know what to cast the interop object held by its managed object to.
 This ensures that all GUI elements can now be accessed through the common `ScriptGUIElementBase` interface. Which is important if `GUIElement` provides some internal method calls shared between all GUI element types, otherwise we wouldn't know what to cast the interop object held by its managed object to.
 
 
 See @ref bs::ScriptGUIElement "ScriptGUIElement" and @ref bs::ScriptGUIButton "ScriptGUIButton" for an example.
 See @ref bs::ScriptGUIElement "ScriptGUIElement" and @ref bs::ScriptGUIButton "ScriptGUIButton" for an example.
+
+
+
+
+
+
+## Exposing resources to scripting {#resources_c_a}
+Once you have a custom resource you might want to expose it to the scripting API. Take a look at the [scripting interop guide](@ref scripting) to learn how to create scripting API objects. 
+
+Every resource scripting interop object must implement @ref bs::TScriptResource "TScriptResource", but other than that creating GUI interop objects is the same as the general case described in the guide above. See @ref bs::ScriptFont "ScriptFont" in `BsScriptFont.cpp` for an example.
+
+Creating managed GUI objects is again the same as the general case. Take a look at the managed `Font` implementation in `Font.cs` for an example.
+
+Resources are unlike most other scripting objects because they can be created in the native code and then used in the managed code, or vice versa. Resources are also serialized by reference, which requires some specialized code for managed serialization to properly recognize the resource. 
+
+### Native <-> managed resource conversion {#resources_c_a_a}
+When a resource is created in native code, but needs to be passed to scripting code, the system creates a script interop object and a managed object, which wrap the native resource. The system also needs to be aware if such managed representation of an object already exists, and return an existing one if so. This is the job of the @ref bs::ScriptResourceManager "ScriptResourceManager".
+
+You will need to update this manager with your custom resource type. Relevant methods are:
+ - @ref bs::ScriptResourceManager::createScriptResource "ScriptResourceManager::createScriptResource" - Creates a new managed object instance from a native resource (only valid if one doesn't already exist). This method has two overloads, and is specialized for specific resource types. Make sure to add a specialization for both overloads, with your custom resource type. And also update the specialization that accepts a generic @ref bs::ResourceHandleBase "HResource" with an entry of your own resource. You can use existing resources as an example of how it should be done, only the type names need changing.
+ - @ref bs::ScriptResourceManager::getScriptResource<RetType, InType> "ScriptResourceManager::getScriptResource" - Retrieves an existing managed object instance from a native resource handle. Optionally creates the managed object if one doesn't already exist. Add a specialization for your own resource type similar to methods above.
+
+### Managed resource serialization {#resources_c_a_b}
+In order for your new resource type to be properly referenced by serialized managed objects you need to make a few more additions:
+ - First of append a new resource type to the @ref bs::ScriptReferenceType "ScriptReferenceType" enum.
+ - Append a new entry to @ref bs::ManagedSerializableTypeInfoRef::getMonoClass "ManagedSerializableTypeInfoRef::getMonoClass" which maps the enum entry above to your resource script interop object type
+ - Append a new entry to @ref bs::ManagedSerializableTypeInfoRef::isTypeLoaded "ManagedSerializableTypeInfoRef::isTypeLoaded" so it always returns true if your resource is encountered (since it's built-in, it's always loaded)
+ - Append a new entry in the @ref bs::ScriptAssemblyManager::getTypeInfo "ScriptAssemblyManager::getTypeInfo" which maps the managed resource object type to the enum above
+ - Append a new entry to the `getResourceFieldLookup` method in `BsManagedSerializableField.cpp` which uses the native <-> managed conversion methods to map between a native and a managed instance of a resource during serialization/deserialization
+ 
+For all of these you can use examples of existing resources which already exist within the mentioned methods, it is just a matter of changing the type/enum names for your own resource. 
+ 
+### Other {#resources_c_a_c}
+In order for your resources to be properly recognized by GUI drop fields, as well as the project library append new entries to @ref bs::ScriptResource::getClassFromTypeId "ScriptResource::getClassFromTypeId" and @ref bs::ScriptResource::getTypeFromTypeId "ScriptResource::getTypeFromTypeId" which map between the enum above and the RTTI type ID of the resource.