Prechádzať zdrojové kódy

More work on documentation

BearishSun 8 rokov pred
rodič
commit
3fd69a4a16

+ 300 - 0
Documentation/Manuals/Native/customGui.md

@@ -0,0 +1,300 @@
+Extending the GUI system						{#customGUI}
+===============
+[TOC]
+
+Even though Banshee provides fully skinnable and very customizable GUI elements, sometimes the built-in ones are just not enough if you need some very specialized functionality or look. Banshee allows you to create brand new elements and fully customize the way how they are rendered and how the user interacts with such elements.
+
+You are expected to have read the user-facing GUI manuals before proceeding, and as such familiarized yourself with the basics.
+
+All GUI elements derive from the base @ref bs::GUIElementBase "GUIElementBase" type. The elements can be categorized into two major groups:
+ - *Layouts* - They derive from @ref bs::GUILayout "GUILayout" and do not have any graphics, but instead they control the placement of all elements attached to them.
+ - *Elements* - They derive from @ref bs::GUIElement "GUIElement", and they're standard GUI elements like buttons, input boxes, sliders and such.
+ 
+It's unlikely you will have the need to create **GUILayout** types, so we will instead focus on creating custom GUI elements. 
+ 
+# GUIElement implementation {#customGUI_a}
+When creating a custom GUI element you will need to override the **GUIElement** class. In this section we'll go over the *minimum* set of functionality every GUI element must implement, split into relevant sections. In later sections we'll focus on optional functionality.
+
+~~~~~~~~~~~~~{.cpp}
+// GUI element that displays a single texture
+class GUITexture : public GUIElement
+{
+	// ... implementation
+};
+~~~~~~~~~~~~~ 
+
+## Construction {#customGUI_a_a}
+In its constructor **GUIElement** expects two parameters:
+ - `styleName` - Name of the style to use for rendering the element. This will be looked up in the currently active **GUISkin** and relevant @ref bs::GUIElementStyle "GUIElementStyle" objects will be used for determining object's textures, fonts, colors, borders, margins and similar. Each GUI element type should have a unique default style name, but you also might want to allow the user to override the default style name if he desires. 
+ - `dimensions` - And initial set of dimensions determining GUI element's position and size, represented by @ref bs::GUIDimensions "GUIDimensions". You can create an empty set of dimensions by calling @ref bs::GUIDimensions::create "GUIDimensions::create()", in which case the system will use whichever dimensions are provided by the **GUIElementStyle**. Other overload of **GUIDimensions::create()** accepts a @ref bs::GUIOptions "GUIOptions" object, in which you can specify an arbitrary sized array of various dimension related options.
+
+As a rule of thumb in order to aid construction GUI elements should provide a set of static `create()` methods (but aren't required to). You usually want to provide a few overloads of `create()` that allow the user to use custom style/dimensions or stick with the default one.
+
+~~~~~~~~~~~~~{.cpp}
+class GUITexture : public GUIElement
+{
+public:
+	static const String& getGUITypeName()
+	{
+		// Returns the name of this GUI element, used for looking up the default style
+		static String name = "Texture";
+		return name;
+	}
+	
+	GUITexture(const String& styleName, const GUIDimensions& dimensions)
+		:GUIElement(styleName, dimensions)
+	{ }
+
+	// create() overload accepting custom dimensions in the form of GUIOptions
+	static GUITexture* create(const GUIOptions& options, const String& styleName = StringUtil::BLANK)
+	{
+		// If user didn't provide a style name, use the default
+		String finalStyleName = styleName;
+		if(styleName == StringUtil::BLANK)
+			finalStyleName = getGUITypeName();
+
+		// Pass style name, and construct dimensions from the provided list of options
+		return bs_new<GUITexture>(finalStyleName, GUIDimensions::create(options));
+	}
+	
+	// create() overload using default dimensions
+	static GUITexture* create(const String& styleName = StringUtil::BLANK)
+	{
+		// Same as above
+		String finalStyleName = styleName;
+		if(styleName == StringUtil::BLANK)
+			finalStyleName = getGUITypeName();
+
+		// Pass style name, and construct default dimensions object
+		return bs_new<GUITexture>(finalStyleName, GUIDimensions::create());
+	}
+
+	// ... remaining GUITexture implementation
+};
+~~~~~~~~~~~~~ 
+
+## Graphics {#customGUI_a_b}
+In order for your GUI element to be visible you need to define its graphics. This involves:
+ - Creating a set of vertices and indices that represent your GUI element
+ - Create the material to render the GUI element with, and bind required textures and other properties to it
+
+This is done by implementing the following methods:
+
+@ref bs::GUIElement::_getNumRenderElements() "GUIElement::_getNumRenderElements()"
+
+Returns the number of separate elements that your GUI element consists of. Each element corresponds to a mesh and a material to render the mesh with. For most GUI elements there is only one element, but you will need multiple elements in case your GUI element uses multiple textures or materials.
+
+~~~~~~~~~~~~~{.cpp}
+class GUITexture : public GUIElement
+{
+	// ... remaining GUITexture implementation
+
+	UINT32 _getNumRenderElements() const override
+	{
+		// Our simple GUI element has just a single render element (a single quad to be exact)
+		return 1;
+	}
+};
+~~~~~~~~~~~~~
+
+@ref bs::GUIElement::_getMeshInfo() "GUIElement::_getMeshInfo()"
+
+Takes a render element index as input and returns the number of vertices and indices for the mesh at the specified index. This allows external systems to know how big of a buffer to allocate for the element's mesh. It also returns the type of the mesh which lets external systems know how to render the provided vertices.
+
+~~~~~~~~~~~~~{.cpp}
+class GUITexture : public GUIElement
+{
+	// ... remaining GUITexture implementation
+
+	void _getMeshInfo(UINT32 renderElementIdx, UINT32& numVertices, UINT32& numIndices, GUIMeshType& type) const override
+	{
+		// Since we're rendering a single quad, we use 4 vertices, rendered as 2 triangles (6 indices)
+		numVertices = 4;
+		numIndices = 6;
+		type = GUIMeshType::Triangle;
+	}
+};
+~~~~~~~~~~~~~
+
+@ref bs::GUIElement::_fillBuffer() "GUIElement::_fillBuffer()"
+
+This is the primary method when it comes to **GUIElement** graphics. It allows you to provide the actual vertex and index data that will be used for rendering the GUI element. Note that number of vertices and indices provided must match the number returned by **GUIElement::_getMeshInfo()**.
+
+The method receives pointers to the index and vertex memory that must be populated by the function, offsets at which memory location should the function output its data at, and external buffer sizes (used for overflow checking if needed).
+
+The vertices are always in a specific format:
+ - Each vertex contains a 2D position, followed by 2D texture coordinates
+ - Vertex size if `sizeof(Vector2) * 2`
+
+~~~~~~~~~~~~~{.cpp}
+class GUITexture : public GUIElement
+{
+	// ... remaining GUITexture implementation
+
+	void _fillBuffer(UINT8* vertices, UINT32* indices, UINT32 vertexOffset, UINT32 indexOffset,
+		UINT32 maxNumVerts, UINT32 maxNumIndices, UINT32 renderElementIdx) const
+	{
+		UINT32 vertexStride = sizeof(Vector2) * 2;
+		UINT32 indexStride = sizeof(UINT32);
+
+		// Get location of this element in the provided buffers
+		vertices += vertexStride * vertexOffset;
+		UINT8* uvs = vertices + sizeof(Vector2);
+		
+		indices += indexStride * indexOffset;
+		
+		// Populate the vertices, uv and indices buffer
+		// ... generate vertices, uvs and indices as you would for any mesh
+	}
+};
+~~~~~~~~~~~~~
+
+Banshee also provides a set of helper classes for generating required geometry in the form of @ref bs::ImageSprite "ImageSprite" and @ref bs::TextSprite "TextSprite" classes. **ImageSprite** can easily generate image geometry of specified size, whether a simple quad or a scale-9-grid image (scalable image with fixed borders). And **TextSprite** will take a text string, font and additional options as input, and output a set of quads required for text rendering.
+
+@ref bs::GUIElement::_getMaterial() "GUIElement::_getMaterial()"
+
+Takes a render element index as input and returns a material to render the element with, as well material parameters. 
+
+GUI materials are represented by the @ref bs::SpriteMaterial "SpriteMaterial" type and you can use @ref bs::SpriteManager "SpriteManager" to retrieve the built-in materials. You can also create your own sprite materials by implementing the **SpriteMaterial** class and registering them with the **SpriteManager** by calling @ref bs::SpriteManager::registerMaterial "SpriteManager::registerMaterial()". 
+
+Material parameters are represented by the @ref bs::SpriteMaterialInfo "SpriteMaterialInfo" structure, which contains the texture and color to render the element with. It also contains a `groupId` identifier which tells the external systems with which other GUI elements is this element allowed to be grouped with. Grouped elements are rendered together (batched) for better performance, but sometimes this is not wanted. Generally you want to provide the memory address of the parent **GUIWidget** for the `groupId` field, and don't need to worry about it further. You can retrieve the element's **GUIWidget** by calling @ref bs::GUIElement::_getParentWidget() "GUIElement::_getParentWidget()".
+
+Textures used by the material parameter can be retrieved from the current **GUIElementStyle**, or provided directly to the GUI element by user-specified means. It is preferred to use the **GUIElementStyle** approach as this allows the user to customize the element look through **GUISkin**%s, or by providing a custom style name. To retrieve the currently active style call @ref bs::GUIElement::_getStyle() "GUIElement::_getStyle()". 
+
+~~~~~~~~~~~~~{.cpp}
+class GUITexture : public GUIElement
+{
+	// ... remaining GUITexture implementation
+
+	const SpriteMaterialInfo& _getMaterial(UINT32 renderElementIdx, SpriteMaterial** material) const
+	{
+		// Get material for rendering opaque images
+		*material = SpriteManager::instance().getImageOpaqueMaterial();
+		
+		// Populate the material parameters (normally you want to populate this when properties change and just return it here)
+		//// Use the normal texture as provided in GUIElementStyle
+		mMatParams.texture = _getStyle().normal.texture;
+		
+		//// No tint
+		mMatParams.tint = Color::White;
+		
+		//// Ensures only the GUI elements sharing the same GUIWidget can be grouped
+		mMatParams.groupId = (UINT64)_getParentWidget();
+		
+		return mMatParams;
+	}
+	
+	SpriteMaterialInfo mMatParams;
+};
+~~~~~~~~~~~~~
+
+@ref bs::GUIElement::updateRenderElementsInternal() "GUIElement::updateRenderElementsInternal()"
+
+Called whenever the element's size or style changes. This is the method where you should rebuild the GUI element's mesh. While you could do it directly in **GUIElement::_fillBuffer()** it is better performance-wise to do it here, and instead just return the cached mesh when **GUIElement::_fillBuffer()** is called. This is because **GUIElement::_fillBuffer()** will get called even when mesh geometry didn't change, if the external systems deem it required.
+
+~~~~~~~~~~~~~{.cpp}
+class GUITexture : public GUIElement
+{
+	// ... remaining GUITexture implementation
+
+	void updateRenderElementsInternal()
+	{		
+		// Move the code for vertex/index generation here, cache the generate data and then just return the cached data when _fillBuffer() is called.
+		
+		GUIElement::updateRenderElementsInternal();
+	}
+};
+~~~~~~~~~~~~~
+
+## Layout {#customGUI_a_c}
+In order for the GUI element to work well with the automatic positioning performed by GUI layouts, you must override the @ref bs::GUIElement::_getOptimalSize "GUIElement::_getOptimalSize()" method. As the name implies the method should return the optimal size of your GUI element. For example if your element was displaying a texture 64x64 in size, then the optimal size should probably return 64x64. If you element is displaying text you can use @ref bs::GUIHelper "GUIHelper" to help you calculate the bounds of the text. If displaying something else then it's up to you to determine what constitutes an optimal size.
+
+~~~~~~~~~~~~~{.cpp}
+class GUITexture : public GUIElement
+{
+	// ... remaining GUITexture implementation
+
+	Vector2I _getOptimalSize() const
+	{
+		Vector2I optimalSize;
+		
+		// Retrieve the size of the main texture, if one is provided
+		HSpriteTexture tex = _getStyle().normal.texture;
+		if(tex != nullptr)
+		{
+			optimalSize.x = tex->getWidth();
+			optimalSize.y = tex->getHeight();
+		}
+		
+		return optimalSize;
+	}
+};
+~~~~~~~~~~~~~
+
+This concludes the minimal set of functionality required for implementing a **GUIElement**. At this point you will have a static GUI element that allows no user interaction. In next sections we expand on this by adding support for user input and dynamic graphics.
+
+# Redrawing {#customGUI_b}
+If your element allows the user to update certain contents of it after creation (i.e. it's not static), you need to notify the GUI system so it knows when to rebuild the element. For example if your GUI element displays a text string you might provide a `setText()` method that allows the user to change what is displayed. When text is changed the GUI system will need to update the batched GUI mesh, update the GUI element's mesh and/or update the layout position/size of the element.
+
+There are three ways to notify the GUI system the element is dirty, each more expensive in performance than the previous:
+ - @ref bs::GUIElement::_markMeshAsDirty() "GUIElement::_markMeshAsDirty()" - Causes the batched GUI mesh to be re-assembled. Will cause a call to **GUIElement::_fillBuffer()**. Call this if element's contents and size didn't change (e.g. when its position, or depth changes). Batched GUI mesh is a mesh managed by the GUI system that consists of multiple GUI elements sharing the same material properties (used to improve rendering performance).
+ - @ref bs::GUIElement::_markContentAsDirty() "GUIElement::_markContentAsDirty()" - Has the same effect as **GUIElement::_markMeshDirty()**, but will also trigger a **GUIElement::updateRenderElementsInternal()** call so the GUI element mesh will be fully rebuilt. Call this when contents of the GUI element change, but not its size (e.g. changing a texture but it is the same dimensions as the old one.)
+ - @ref bs::GUIElement::_markLayoutAsDirty() "GUIElement::_markLayoutAsDirty()" - Has the same effect as **GUIElement::_markContentDirty()**, but will also cause the layout system to recalculate the element's position and size. This can be expensive as this will generally trigger layout updates for all siblings and children, potentially even parent GUI elements. Call this when element changes and no other dirty calls are appropriate. Normally you have to call this whenever the element's size changes.
+ 
+~~~~~~~~~~~~~{.cpp}
+class GUITexture : public GUIElement
+{
+	// ... remaining GUITexture implementation
+
+	// Changes the look of the GUI element by fading it out when enabled
+	void setFadeOut(bool fadeOut)
+	{
+		if(fadeOut)
+			mMatParams.tint = Color(1.0f, 1.0f, 1.0f, 0.5f);
+		else
+			mMatParams.tint = Color::White;
+		
+		// Ensure the system redraws the mesh. Since neither the size or contents changed we can call the cheapest redraw method, '_markMeshAsDirty()'
+		_markMeshAsDirty();
+	}
+	
+	// Updated version of _getMaterial()
+	const SpriteMaterialInfo& _getMaterial(UINT32 renderElementIdx, SpriteMaterial** material) const
+	{
+		// Get material for rendering opaque images
+		*material = SpriteManager::instance().getImageOpaqueMaterial();
+		
+		// Assuming remaining mMatParams contents are populated elsewhere
+		return mMatParams;
+	}
+	
+	SpriteMaterialInfo mMatParams;
+};
+~~~~~~~~~~~~~
+ 
+# Input {#customGUI_c}
+In order for the GUI element to accept input from the user you can implement any or all of the following methods:
+ - @ref bs::GUIElement::_mouseEvent "GUIElement::_mouseEvent()" - Triggered when the mouse moves and/or is clicked. See @ref bs::GUIMouseEventType "GUIMouseEventType" for a list of events. Receives @ref bs::GUIMouseEvent "GUIMouseEvent" structure as input.
+ - @ref bs::GUIElement::_textInputEvent "GUIElement::_textInputEvent()" - Triggered when the user inputs some text on the keyboard, while the GUI element is in focus. Receives @ref bs::GUITextInputEvent "GUITextInputEvent" structure as input.
+ - @ref bs::GUIElement::_virtualButtonEvent "GUIElement::_virtualButtonEvent()" - Triggered when a certain virtual button is pressed, while the GUI element is in focus. Receives @ref bs::GUIVirtualButtonEvent "GUIVirtualButtonEvent" structure as input.
+ - @ref bs::GUIElement::_commandEvent "GUIElement::_commandEvent()" - Triggers when some kind of a specialized event happens, like losing/gaining focus, deleting text, selecting text, forcing redraw and similar. See @ref bs::GUICommandEventType "GUICommandEventType" for an explanation of what each event type does. Receives @ref bs::GUICommandEvent "GUICommandEvent" structure as input.
+ 
+Each of the methods should return false if other GUI elements are allowed to receive the same event. If true is returned the GUI element will consume the event and it wont be visible to others.
+ 
+~~~~~~~~~~~~~{.cpp}
+class GUITexture : public GUIElement
+{
+	// ... remaining GUITexture implementation
+
+	bool _mouseEvent(const GUIMouseEvent& ev)
+	{
+		// Fade out the texture when user mouses over the element
+		if(ev.getType() == GUIMouseEventType::MouseOver)
+			setFadeOut(true);
+		else if(ev.getType() == GUIMouseEventType::MouseOut)
+			setFadeOut(false);
+
+		return false;
+	}
+};
+~~~~~~~~~~~~~

+ 0 - 91
Documentation/Manuals/Native/gui.md

@@ -1,91 +0,0 @@
-Creating custom GUI elements						{#customGUI}
-===============
-[TOC]
-
-Sometimes the built-in GUI elements are just not enough, for example when you need a very specific GUI element for your game (e.g. for displaying graphs, charts), want to use a special material or in general just need some more customization options. While in some cases you could construct such elements from the provided GUI elements, it is often more efficient to create a brand new customized type. New GUI elements can be created relatively easily and allow you to fully customize the look and interaction with your element.
-
-Before starting you should familiarize yourself how Banshee's GUI works from the users perspective. Make sure to read the scripting GUI manual to understand the basics (although the manual is for scripting, the C++ versions of these methods are essentially equivalent and the same concepts apply).
-
-All GUI elements derive from the base @ref bs::GUIElementBase "GUIElementBase" type. The elements can be categorized into two major groups:
- - GUILayout: They derive from @ref bs::GUILayout "GUILayout" and do not have any graphics, but instead they control the placement of all elements attached to them.
- - GUIElement: They derive from @ref bs::GUIElement "GUIElement", and they're standard GUI elements like buttons, input boxes, sliders and such.
- 
-You will almost certainly be interested in `GUIElement`, and are unlikely to need to create custom `GUILayout` types.
-
-# Basic GUI element # {#customGUI_a}
-When creating a custom GUI element you will need to override the @ref bs::GUIElement "GUIElement" type. The minimum set of methods you need to implement for your custom elements are:
- - @ref bs::GUIElement::_getOptimalSize "_getOptimalSize()" - Return the optimal size of your GUI element. This is used for controlling the size of the element in a layout (if it's not fixed). For example if your element was displaying a texture 64x64 in size, then the optimal size should probably return 64x64. If you element is displaying text you can use @ref bs::GUIHelper "GUIHelper" to help you calculate the bounds of the text. If displaying something else then it's up to you to determine what constitutes an optimal size.
- - @ref bs::GUIElement::_getNumRenderElements() "_getNumRenderElements()" - Return the number of separate elements that your GUIElement consists of. Each element has its own mesh, material and texture. In most cases there is only one element.
- - @ref bs::GUIElement::_getMeshInfo() "_getMeshInfo()" - Returns the number of vertices and indices for the mesh of the render element at the specified index (e.g. one quad (4 vertices, 6 indices) if the GUI element displays just one texture). This allows external systems to know how big of a buffer to allocate for the element's mesh. It also returns the type of the mesh which lets external systems know in which format will be vertices be provided (e.g. 2D vertex followed by 2D UV coordinate) when calling @ref bs::GUIElement::_fillBuffer() "_fillBuffer()".
- - @ref bs::GUIElement::_fillBuffer() "_fillBuffer()" - This is the meat of the `GUIElement` override. It allows you to fill a buffer with vertices, uv coordinates and indices for a mesh for the specified render element. This allows you to fully control the look of your GUI element by providing customized geometry.
- - @ref bs::GUIElement::_getMaterial() "_getMaterial()" - Here you should return a material that will be applied to the mesh output in the previous method, as well as an optional texture or color tint. You can choose from a set of pre-built materials or use your own material. 
- - @ref bs::GUIElement::updateRenderElementsInternal() "updateRenderElementsInternal()" - Called whenever the element's size or style changes. In this method you should rebuild the element's mesh. (While you could build the mesh in `_fillBuffer` it is inefficient as `_fillBuffer` will get called much more often than `updateRenderElementsInternal` due to mesh batching).
- 
-In order to help you with creating GUI meshes and materials make sure to take a look at @ref bs::ImageSprite "ImageSprite" and @ref bs::TextSprite "TextSprite" classes. `ImageSprite` can easily generate image geometry of specified size, whether a simple quad or a scale-9-grid image. And `TextSprite` will take a text string, font and additional options as input, and output a set of quads required for text rendering.
-
-To retrieve materials used for rendering GUI use the @ref bs::SpriteManager "SpriteManager", which contains a few built-in materials. You can also create your own materials by implementing the @ref bs::SpriteMaterial "SpriteMaterial" interface and registering it with @ref bs::SpriteManager "SpriteManager" by calling @ref bs::SpriteManager::registerMaterial "SpriteManager::registerMaterial".
-
-When constructing the `GUIElement` you will also need to provide a style-name (see next chapter) and dimensions to the `GUIElement` constructor. The dimensions determine the initial size of the element. To use the default dimensions just provide the constructor with return value from @ref bs::GUIDimensions::create() "GUIDimensions::create()". `GUIElement` will internally use dimensions provided by its style, but providing custom `GUIDimensions` allows you to override the dimensions of the style. For that reason you should provide the user with a constructor that accepts @ref bs::GUIOptions "GUIOptions" object, which will contain optional dimension overrides the user can specify. Then you can create a `GUIDimension` by providing the `GUIOptions` object as a parameter.
-
-It is highly suggested you check out an implementation of @ref bs::GUITexture "GUITexture" (in *BsGUITexture.cpp*) for a simple implementation of everything mentioned.
-
-# Style # {#customGUI_b}
-
-Every `GUIElement` has an access to a specific style (@ref bs::GUIElementStyle "GUIElementStyle"). You can access the style by calling @ref bs::GUIElement::_getStyle() "GUIElement::_getStyle()". The style controls the look of your elements, including its texture, text style and margins. When creating a custom `GUIElement` you normally don't need to worry about style options like margins or padding, but you should take the rest into account when creating your mesh and material. You could also choose to ignore the style at the consequence of not having a skinnable `GUIElement`.
-
-You might also need to override @ref bs::GUIElement::styleUpdated() "GUIElement::styleUpdated()" method that will trigger when the user changes the `GUIElement`'s style, depending on your needs. Although in most cases it will be not necessary as a style change will trigger a call to `updateRenderElementsInternal()`, so you can retrieve the new style information there, as well as rebuild any contents as needed.
-
-You should also provide a style-name for your element. This is a string that will be used for looking up the default style for the element, and you must provide it to the `GUIElement` constructor. This name will be used for looking up the exact `GUIElementStyle` in the currently active `GUISkin` (see later for infomation about GUI skins). You might also allow the user to provide a custom style name if needed (e.g. sometimes its nice to be able to style a `GUIToggle` element so it looks like a `GUIButton`).
-
-# Input # {#customGUI_c}
-
-If you implemented everything so far you should have a functional GUIElement that has a custom look, but it still doesn't accept any input. In order to accept input you must override some or all of the following methods:
- - @ref bs::GUIElement::_mouseEvent "GUIElement::_mouseEvent" - Triggered when the mouse moves and/or is clicked
- - @ref bs::GUIElement::_textInputEvent "GUIElement::_textInputEvent" - Triggered when the user inputs some text on the keyboard
- - @ref bs::GUIElement::_virtualButtonEvent "GUIElement::_virtualButtonEvent" - Triggered when a certain virtual button is pressed.
- - @ref bs::GUIElement::_commandEvent "GUIElement::_commandEvent" - Triggers when some kind of a specialized event happens, like losing/gaining focus, deleting text, selecting text, forcing redraw and similar. See @ref bs::GUICommandEventType "GUICommandEventType" for an explanation of what each event type does.
- 
-Check out `_mouseEvent` implementation in @ref bs::GUIButtonBase "GUIButtonBase" for a simple implementation of a mouse hover on/off and click functionality. Check @ref bs::GUIInputBox "GUIInputBox" for a more complex implementation of input.
-
-If working with text input also take a look at @ref bs::GUIInputCaret "GUIInputCaret" and @ref bs::GUIInputSelection "GUIInputSelection", as they help with input caret movement and text selection. Instances of these classes can be accessed from @ref bs::GUIManager "GUIManager" with @ref bs::GUIManager::getInputCaretTool() "getInputCaretTool()" and @ref bs::GUIManager::getInputSelectionTool() "getInputSelectionTool()". This is completely optional and you may choose to handle these manually. See @ref bs::GUIInputBox "GUIInputBox" for example usage.
-
-# Updating # {#customGUI_d}
-
-If your element allows the user to update certain contents of it after creation (i.e. it's not static), you need to notify the GUI system so it knows when to rebuild the element. For example if your GUI element displays a text string you might provide a `setText` method that allows the user to change what is displayed. When that is done the GUI system will need to update the batched GUI mesh, update the GUI element's mesh and/or update the layout position/size of the element.
-
-There are three ways to notify the GUI system the element is dirty, each more expensive in performance than the previous:
- - @ref bs::GUIElement::_markMeshAsDirty() "_markMeshAsDirty()" - Causes the batched GUI mesh to be re-assembled, will cause a call to `_fillBuffer`. Call this if element's size didn't change (e.g. when its position, or depth changes). Batched GUI mesh is a mesh managed by the GUI system that consists of multiple GUI elements sharing the same material properties (used to improve rendering performance).
- - @ref bs::GUIElement::_markContentAsDirty() "_markContentAsDirty()" - Has the same effect as `_markMeshDirty()`, but will also trigger an `updateRenderElementsInternal` call so the GUI element mesh will be fully rebuilt. Call this when contents of the GUI element change, but not its size (e.g. changing a texture but it is the same dimensions as the old one.)
- - @ref bs::GUIElement::_markLayoutAsDirty() "_markLayoutAsDirty()" - Has the same effect as `_markContentDirty()`, but will also cause the layout system to recalculate the element's position and size. This can be very expensive as this will generally trigger layout updates for all siblings and children, potentially even parent GUI elements. Call this when element changes and no other dirty calls are appropriate. Normally you have to call this whenever the element's size changes.
-
-When updating your GUI element with new contents consider using the provided @ref bs::GUIContent "GUIContent" type, in order to stay consistent with the built-in elements. It allows you to specify an image, text and a tooltip all in one. But this is completely optional.
- 
-# Various # {#customGUI_e}
- 
-## GUIWidget ## {#customGUI_d_a}
- 
-Every `GUIElement` is internally part of a specific `GUIWidget`. A `GUIWidget` is a @ref bs::Component "Component" (@ref bs::CGUIWidget "CGUIWidget") that can be attached to a scene object, and transformed like one. This allows you to perform arbitrary transformations on GUI elements.
-
-You attach elements to a `GUIWidget` by adding them to the widget's @ref bs::GUIPanel "GUIPanel". Each widget has a `GUIPanel` which is a `GUILayout` object that allows you to manually position GUI elements within it. Every GUI element's top level parent must be such a panel or they will not be rendered.
-
-`GUIWidget` also allows you to control to which camera should the GUI elements within it be rendered. The camera provides the dimensions of the widget, and in turn the available area for all child GUI elements.
-
-Every style that a `GUIElement` uses is retrieved from its parent `GUIWidget`. GUIWidget contains a @ref bs::GUISkin "GUISkin" object which has a key-value map where style-names are mapped to particular GUI element styles. Changing the `GUISkin`, or moving a `GUIElement` to a widget with a different style will trigger the GUI element rebuild, so it can apply the new style options.
-
-## GUIManager ## {#customGUI_d_b}
-
-@ref bs::GUIManager "GUIManager" is the top level GUI manager that handles almost everything GUI related. It keeps tracks of all `GUIWidget`s and `GUIElement`s. It updates layout when element properties change, rebuilds the GUI meshes, sets up GUI materials and ultimately renders the GUI. It also dispatches all GUI input events.
-
-If you need to do some very deep changes to the GUI system this is where you do it.
-
-## Text ##  {#customGUI_d_c}
-
-If you ever require to render text completely manually (perhaps even outside of the GUI system), take a look at @ref bs::TextData "TextData". It will take a text string with a font and optional bounds as input, and output (optionally) word wrapped text in the form of words and lines, from which you can easily retrieve a mesh for rendering.
- 
-## Scripting integration ## {#customGUI_d_d}
-
-Once you have a custom GUI element 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 GUI scripting interop object must implement @ref bs::TScriptGUIElement "TScriptGUIElement", but other than that creating GUI interop objects is the same as the general case described in the guide above. See @ref bs::ScriptGUITexture "ScriptGUITexture" in `BsScriptGUITexture.cpp` for an example.
-
-Creating managed GUI objects is again the same as the general case. Take a look at the managed GUITexture implementation in `GUITexture.cs` for an example.

+ 2 - 3
Documentation/Manuals/Native/manuals.md

@@ -110,6 +110,7 @@ A set of manuals covering advanced functionality intented for those wanting to e
  - **Exposing code to script API (manually)**
   - [Interacting with the script runtime](@ref mono)
   - [Script objects](@ref scriptObjects)
+- [Extending the GUI system](@ref customGUI)
 - [Porting to other platforms](@ref porting)
 - [Code style](@ref codeStyle)
 - [Quick reference](@ref quickref)
@@ -117,6 +118,4 @@ A set of manuals covering advanced functionality intented for those wanting to e
 ## General guides
 Name                                      | Description
 ------------------------------------------|-------------
-[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.
-[Meshes](@ref meshes)                     | Shows you how to create, use and manipulate meshes.
+[BSLFX](@ref bsl)    	  		  		  | Provides a reference for the Banshee Shading Language syntax.

+ 0 - 164
Documentation/Manuals/Native/meshes.md

@@ -1,164 +0,0 @@
-Meshes									{#meshes}
-===============
-[TOC]
-
-Mesh is an object represented by a set of points, their properties and a set of primitives formed by those points. In Banshee mesh is represented with the @ref bs::Mesh "Mesh" and @ref bs::ct::Mesh "ct::Mesh" classes. Both of these provide almost equivalent functionality, but the former is for use on the simulation thread, and the latter is for use on the core thread. If you are confused by the dual nature of the objects, read the [core thread](@ref coreThread) manual. 
-
-We're going to focus on the simulation thread implementation in this manual, and then note the differences in the core thread version at the end.
-
-# Creating a mesh {#meshes_a}
-To create a mesh call @ref bs::Mesh::create "Mesh::create" or one if its overloads. You'll need to populate the @ref bs::MESH_DESC "MESH_DESC" structure and pass it as a parameter. At minimum you need to provide a @ref bs::VertexDataDesc "vertex description" that describes in what format are the vertices stored in the vertex buffer and the number of vertices and indices. 
-
-Optionally you can also provide the type of indices, type of primitives, and a set of sub-meshes:
- - Indices can be 32- or 16-bit. This is controlled by the `indexType` parameter. Smaller indices can be used to save bandwidth if your mesh has a small enough number of primitives.
- - `drawOp` parameter determines how are the indices interpreted. By default they're interpreted as a list of triangles (every three indices forming a triangle, one after another) but different @ref bs::DrawOperationType "types" are supported.
- - A mesh can have multiple sub-meshes. Each sub-mesh is described by an offset and a range of indices that belong to it. Sub-meshes can be used for rendering sections of a mesh, instead of all of it (for example if a single mesh uses different materials).
- 
-For example to create a simple mesh:
-~~~~~~~~~~~~~{.cpp}
-// Creates an empty mesh with 36 indices and 8 vertices
-MESH_DESC meshDesc;
-meshDesc.numVertices = 8;
-meshDesc.numIndices = 36;
-
-SPtr<VertexDataDesc> vertexDesc = ...; // Vertex description creation is explained later
-meshDesc.vertexDesc = vertexDesc;
-
-HMesh mesh = Mesh::create(meshDesc);
-~~~~~~~~~~~~~ 
- 
-You can also create a non-empty mesh by creating it with a populated @ref bs::MeshData "MeshData" object. More about @ref bs::MeshData "MeshData" later. 
- 
-# Accessing properties {#meshes_b} 
-You can access various mesh properties by calling @ref bs::Mesh::getProperties() "Mesh::getProperties()" which will return an instance of @ref bs::MeshProperties "MeshProperties" which contains information such as mesh bounds, number of indices/vertices and sub-meshes. 
- 
-# Reading/writing {#meshes_c}
-To read and write from/to the mesh use the @ref bs::Mesh::readData "Mesh::readData" and @ref bs::Mesh::writeData "Mesh::writeData" methods. These expect a @ref bs::MeshData "MeshData" object as input.
-
-@ref bs::MeshData "MeshData" object is just a container for a set of vertices and indices. You can create one manually or use @ref bs::Mesh::allocBuffer "Mesh::allocBuffer" to create the object of valid size and format for the specified mesh. When reading from the mesh the buffer will be filled with vertices/indices from the mesh, and when writing you are expected to populate the object.
-
-Be aware that read and write operations are asynchronous and you must follow the rules for @ref asyncMethod "asynchronous methods".
-
-## MeshData {#meshes_c_a}
-You can create @ref bs::MeshData "MeshData" manually by calling @ref bs::MeshData::create "MeshData::create" and providing it with vertex description, index type and number of vertices and indices. You must ensure that the formats and sizes matches the mesh this will be used on.
-
-### Vertex description {#meshes_c_a_a}
-Creating a vertex description is simple, it requires you to specify a list of vertex properties, each identified by a type and a semantic. The semantic determines to which GPU program input field does the property map to. See the [gpu program](@ref gpuPrograms) manual for more information about semantics. For example:
-~~~~~~~~~~~~~{.cpp}
-// Create a vertex with a position, normal and UV coordinates
-SPtr<VertexDataDesc> vertexDesc = VertexDataDesc::create();
-vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
-vertexDesc->addVertElem(VET_FLOAT3, VES_NORMAL);
-vertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD);
-~~~~~~~~~~~~~ 
-
-See @ref bs::VertexElementType "VertexElementType" for valid types, and @ref bs::VertexElementSemantic "VertexElementSemantic" for a list of valid semantics. Each semantic can also optionally have an index in case multiple values of the same semantic are needed.
-
-Each vertex element can also be placed in a "stream". In the example above all the elements are in the 0th stream, but you can place different elements in different streams by providing a stream index to @ref bs::VertexDataDesc::addVertElem "VertexDataDesc::addVertElem". Different streams will result in multiple vertex buffers created within the mesh. This can be useful if you are rendering the mesh with multiple GPU programs and not every GPU program requires all vertex elements, in which case you could only bind a subset of the vertex buffers and reduce the bandwidth costs by not sending the unnecessary data.
-
-Once the @ref bs::VertexDataDesc "VertexDataDesc" structure has been filled, you can use it for initializing a @ref bs::Mesh "Mesh" or @ref bs::MeshData "MeshData". You can also use it to manually create a vertex declaration by calling @ref bs::VertexDeclaration::create "VertexDeclaration::create". @ref bs::VertexDeclaration "VertexDeclaration" can be manually bound to the @ref bs::RenderAPI "RenderAPI", which can be useful in the case you're manually creating vertex or index buffers.
-
-### Reading/writing MeshData {#meshes_c_a_b}
-@ref bs::MeshData "MeshData" provides multiple methods of reading/writing vertex data. The most trivial is setting the data in-bulk by using @ref bs::MeshData::setVertexData "MeshData::setVertexData" and @ref bs::MeshData::getVertexData "MeshData::getVertexData" which set vertex data for a single vertex element all at once. 
-
-~~~~~~~~~~~~~{.cpp}
-SPtr<MeshData> meshData = ...; // Assume we have 4 vertices, with only a position element
-
-Vector3 myVertices[4];
-// ... Set vertex positions ...
-
-// Write the vertices
-meshData->setVertexData(VES_POSITION, myVertices, sizeof(myVertices));
-~~~~~~~~~~~~~
-
-You can also use @ref bs::MeshData::getElementData "MeshData::getElementData" which will return a pointer to the starting point of the vertex data for a specific element. You can then iterate over the pointer to read/write values. Make sure to use @ref bs::VertexDataDesc::getVertexStride "VertexDataDesc::getVertexStride" to know how many bytes to advance between elements.
-
-~~~~~~~~~~~~~{.cpp}
-SPtr<MeshData> meshData = ...; // Assume we have 4 vertices, with only a position element
-
-UINT8* vertices = meshData->getElementData(VES_POSITION);
-UINT32 stride = meshData->getVertexDesc()->getVertexStride();
-
-for(UINT32 i = 0; i < 4; i++)
-{
-	Vector3 myVertex(i, i, 0);
-	memcpy(vertices, &myVertex, sizeof(myVertex));
-	
-	vertices += stride;
-}
-~~~~~~~~~~~~~
-
-And finally you can use iterators: @ref bs::MeshData::getVec2DataIter "MeshData::getVec2DataIter", @ref bs::MeshData::getVec3DataIter "MeshData::getVec3DataIter", @ref bs::MeshData::getVec4DataIter "MeshData::getVec4DataIter", @ref bs::MeshData::getDWORDDataIter "MeshData::getDWORDDataIter". They are similar to the previous example but you don't need to manually worry about the vertex stride, or going outside of valid bounds.
-
-~~~~~~~~~~~~~{.cpp}
-SPtr<MeshData> meshData = ...; // Assume we have 4 vertices, with only a position element
-
-auto iter = meshData->getVec3DataIter(VES_POSITION);
-
-int i = 0;
-do {
-	vecIter.addValue(myVertex(i, i, 0)); // Automatically advances the iterator
-	i++;
-} while(vecIter.moveNext()); // Iterate until we reach the end
-~~~~~~~~~~~~~
-
-Accessing indices is simpler and is done through @ref bs::MeshData::getIndices32 "MeshData::getIndices32" or @ref bs::MeshData::getIndices16 "MeshData::getIndices16" depending if the indices are 32- or 16-bit. The returned value is a pointer to the index buffer you can use to read/write the indices directly.
-
-~~~~~~~~~~~~~{.cpp}
-SPtr<MeshData> meshData = ...; // Assume we have 6 32-bit indices
-
-UINT32* indices = meshData->getIndices32();
-indices[0] = 0;
-indices[1] = 1;
-indices[2] = 2;
-
-indices[3] = 2;
-indices[4] = 1;
-indices[5] = 3;
-~~~~~~~~~~~~~
-
-## Cached CPU data {#meshes_c_b}
-When you read from a mesh using the @ref bs::Mesh::readData "Mesh::readData" method the read will be performed from the GPU. This is useful if the GPU has in some way modified the mesh, but will also incur a potentially large performance penalty because it will introduce a CPU-GPU synchronization point. In a lot of cases you might just want to read mesh data from a mesh that was imported or created on the CPU in some other way.
-
-For this reason @ref bs::Mesh::readCachedData "Mesh::readCachedData" exists. It will read data quickly with little performance impact. However you must create the mesh using the @ref bs::MU_CPUCACHED "MU_CPUCACHED" usage. This also means that the mesh will keep a copy of its data in system memory, so use it sparingly. If the mesh is modified from the GPU this method will not reflect such changes.
-
-# Rendering using the mesh {#meshes_d}
-To use a mesh for rendering you need to bind its vertex buffer(s), index buffer, vertex declaration and draw operation using the @ref bs::RenderAPI "RenderAPI". Relevant methods are @ref bs::RenderAPI::setVertexBuffers "RenderAPI::setVertexBuffers", @ref bs::RenderAPI::setIndexBuffer "RenderAPI::setIndexBuffer", @ref bs::RenderAPI::setVertexDeclaration "RenderAPI::setVertexDeclaration" and @ref bs::RenderAPI::setDrawOperation "RenderAPI::setDrawOperation". See below for information about how to retrieve this information from a mesh.
-
-See the [render API](@ref renderAPI) manual for more information on how to manually execute rendering commands.
-
-If working on the core thread you can use the helper @ref bs::ct::RendererUtility::draw "ct::RendererUtility::draw" method that performs these operations for you.
-
-# Saving/loading {#meshes_e}
-A mesh is a @ref bs::Resource "Resource" and can be saved/loaded like any other. See the [resource](@ref resources) manual.
-
-# Core thread meshes {#meshes_f}
-So far we have only talked about the simulation thread @ref bs::Mesh "Mesh" but have ignored the core thread @ref bs::ct::Mesh "ct::Mesh". The functionality between the two is mostly the same, with the major difference being that the core thread version doesn't have asychronous write/read methods, and those operations are instead performed immediately.
-
-You can also use the core thread version to access and manipulate vertex and index buffers directly (including binding them to the pipeline as described earlier). Use @ref bs::ct::Mesh::getVertexData "ct::Mesh::getVertexData" to retrieve information about all @ref bs::ct::VertexBuffer "vertex buffers", @ref bs::ct::Mesh::getIndexBuffer "ct::Mesh::getIndexBuffer" to retrieve the @ref bs::ct::IndexBuffer "index buffer" and @ref bs::ct::Mesh::getVertexDesc "ct::Mesh::getVertexDesc" to retrieve the @ref bs::VertexDataDesc "vertex description".
-
-# Advanced meshes {#meshes_g}
-So far we have described the use of standard meshes. And while the described meshes can be used for all purposes, when we have a mesh that is updated often (every frame or every few frames) it can be beneficial for performance to use a different mesh type. This is because updates to a normal mesh can introduce GPU-CPU synchronization points if that mesh is still being used by the GPU while we are updating it (which can happen often).
-
-So instead we use a concept of a @ref bs::MeshHeap "MeshHeap", which allows us to quickly create and allocate new meshes, without having to worry about introducing GPU-CPU synchronization points. This is perfect for systems like GUI or grass rendering, which might have their meshes rebuilt nearly every frame. The only downside is that the heap will allocate more memory than actually required for a mesh, as it keeps the memory for both the newly updated mesh and the one currently being used.
-
-Creation of a @ref bs::MeshHeap::create "MeshHeap::create" is nearly identical to creation of a @ref bs::Mesh "Mesh". It requires a vertex description and an index type, while the index/vertex counts are mostly arbitrary (the heap will grow as needed).
-
-You can allocate meshes from the heap by calling @ref bs::MeshHeap::alloc "MeshHeap::alloc" and providing it with a @ref bs::MeshData "MeshData". When done with the mesh call @ref bs::MeshHeap::dealloc "MeshHeap::dealloc". @ref bs::MeshHeap::alloc "MeshHeap::alloc" returns a @ref bs::TransientMesh "TransientMesh" which shares mostly the same interface as a normal @ref bs::Mesh "Mesh", with a few restrictions. You are not allowed to read/write to it (aside from the initial value), and it doesn't support sub-meshes.
-
-A simple example of a mesh heap:
-~~~~~~~~~~~~~{.cpp}
-SPtr<VertexDataDesc> vertexDesc = VertexDataDesc::create();
-vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
-
-// Create the mesh heap (normally you you create this once and use it throughout the application)
-SPtr<MeshHeap> meshHeap = MeshHeap::create(100, 100, vertexDesc);
-
-SPtr<MeshData> meshData = ...; // Assume we create mesh data like in one of the previous sections
-SPtr<TransientMesh> mesh = meshHeap->alloc(meshData);
-// Draw using the mesh
-meshHeap->dealloc(mesh);
-
-~~~~~~~~~~~~~
-
-See @ref bs::GUIManager "GUIManager" implementation in "BsGUIManager.cpp" for a functional example.