Browse Source

Docs: Various documentation improvements

BearishSun 7 years ago
parent
commit
19b849f084

+ 10 - 8
Documentation/Manuals/Native/codeStyle.md

@@ -59,18 +59,24 @@ When making changes or additions that you plan on contributing to bs::f, you mus
  - Reference/pointer parameters that won't be modified by a function should always be `const` (e.g. `bool processData(const SomeStruct& input, SomeStruct& output)`)
  
 **Implementation**
- - Avoid the use of `auto` for variable types, with the exception of very long type names (like iterators)
-  - If `auto` is used try to name the variable so its type can be easily deduced
+ - Avoid the use of `auto` except for:
+  - Very long type names (like iterators), in which case include indication of the type in variable name (e.g. `auto iter = ...;`)
+  - Variables where type can be otherwise deduced (e.g. casts, `auto var = (UINT32)otherVar;`)
  - Use built-in typedefs for standard library containers (e.g. `Vector`) and shared pointers (`SPtr`).
  - Don't allocate memory using `new/delete` or `malloc/free`, instead use bs::f allocators
  - No code warnings under default compiler warning settings are allowed. Fix all your warnings or if absolutely not possible isolate that bit of code and disable that specific warning (but only in that bit of code).
  - Never use `using namespace` in a header
  
 **Documentation**
+ - Documentation must be in JavaDoc format
+ - Write **meaningful** documentation
+  - Avoid writing documentation that provides information that can be deduced from class/method name and instead try to provide the reader with deeper understanding. For example `/** Gets value */ getValue(); ` is pointless documentation
+  - Avoid giving away implementation details in documentation. Implementation should be allowed to change, and as long as the interface remains the same, the documentation should remain the same
  - Document every class/structure/enum with a short description on what their purpose is
-  - Optionally provide an use-case example
+  - Optionally provide a use-case example
   - Document every enum member
   - Document struct fields unless they have getter/setter methods that are already documented
+  - Getter/Setter methods should have the same documentation (e.g. document the setter, then use \@copydoc on getter)
   - Documentation for private class fields is optional
  - Document every method, both public and private
   - The only exceptions being very trivial methods whose use can be deduced from their name
@@ -84,13 +90,9 @@ When making changes or additions that you plan on contributing to bs::f, you mus
   - Carefully document complex mathematical expressions
    - Add a comment what the expression does or a hyperlink to expression source
    - If simplified or re-arranged, provide reference expression in comments, as well as explanation on how the current expression was derived (or a link to one)
- - Documentation must be in JavaDoc format 
- - Write **meaningful** documentation
-  - Avoid writing documentation that provides information that can be deduced from class/method name and instead try to provide the reader with deeper understanding. For example `/** Gets value */ getValue(); ` is pointless documentation
-  - Avoid giving away implementation details in documentation. Implementation should be allowed to change, and as long as the interface remains the same, the documentation should remain the same
  - Use \@`addtogroup` to group classes into relevant sections (e.g. a class doing something physics-related should be in the "Physics" group)
   - Classes/structs/functions/enums that aren't meant to be used by normal users should be placed in a separate group to avoid polluting the user-facing documentation (e.g. user-facing physics functionality should be in the "Physics" group, while non-user-facing should be in "Physics_Internal" group)
- - Use \@`name Internal` to mark methods inside a class that they are not meant for normal use (i.e. they might be used for internal communication within a sub-system only)
+ - Use \@`name Internal` to mark public methods inside a class that they are not meant for normal use (i.e. they might be used for internal communication within a sub-system only)
  - Documentation should produce no Doxygen warnings when it is generated
  - If it is not obvious for which thread is a class/method meant to be used on, note it in the documentation
  

+ 3 - 3
Documentation/Manuals/Native/customGui.md

@@ -26,7 +26,7 @@ class GUITexture : public GUIElement
 ## 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.
+ - `dimensions` - 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.
 
@@ -82,7 +82,7 @@ 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.
+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 will be only one element, but you will need multiple elements in case your GUI element uses multiple textures or materials.
 
 ~~~~~~~~~~~~~{.cpp}
 class GUITexture : public GUIElement
@@ -124,7 +124,7 @@ The method receives pointers to the index and vertex memory that must be populat
 
 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`
+ - Vertex size is `sizeof(Vector2) * 2`
 
 ~~~~~~~~~~~~~{.cpp}
 class GUITexture : public GUIElement

+ 50 - 6
Documentation/Manuals/Native/mono.md

@@ -4,19 +4,19 @@ Interacting with the script runtime									{#mono}
 
 In the previous chapter we talked about how to expose a C++ type to the scripting API by using the script binding generator tool. This tool ensures you can generate script bindings easily, but in some cases it is not robust enough and you must interact with the scripting API manually. This manual will explain how to interact with the scripting API and expose C++ code to it manually (without the script binding generator tool). 
 
-You can use manual generation to achieve everything as with the script binding generator tool (in fact this tool uses the same API as described in this manual), plus a lot more. It is preferred you use automatic generation whenever possible, but when working with lower level systems that closely interact with the scripting system (like serialization, script compilation, etc.) you need more direct access.
+You can use manual generation to achieve everything as with the script binding generator tool (in fact the tool uses the same API as we'll describe in this manual), plus a lot more. It is preferred you use automatic generation whenever possible, but when working with lower level systems that closely interact with the scripting system (like serialization, script compilation, etc.) you need more direct access.
 
 All C# script code is executed using the Mono runtime. Mono runtime allows you to communicate with C# code and vice-versa by invoking methods and querying class/method/field information. In this section we'll focus on how to interact with Mono (and therefore the C# runtime).
 
 # MonoManager {#mono_a}
-BansheeMono is a plugin that wraps the functionality of the Mono runtime. The main entry point of the scripting system is the @ref bs::MonoManager "MonoManager" class which allows you to start the runtime and load managed (script) assemblies. The most important method here is @ref bs::MonoManager::loadAssembly "MonoManager::loadAssembly()". It loads all the script code from the managed assembly (.dll) at the provided path, and provides meta-data for the entire assembly through the returned @ref bs::MonoAssembly "MonoAssembly" object. 
+bsfMono is a plugin that wraps the functionality of the Mono runtime. The main entry point of the scripting system is the @ref bs::MonoManager "MonoManager" class which allows you to start the runtime and load managed (script) assemblies. The most important method here is @ref bs::MonoManager::loadAssembly "MonoManager::loadAssembly()". It loads all the script code from the managed assembly (.dll) at the provided path, and provides meta-data for the entire assembly through the returned @ref bs::MonoAssembly "MonoAssembly" object. 
 
 ~~~~~~~~~~~~~{.cpp}
 // Loads the MyManagedAssembly.dll
 MonoAssembly& assembly = MonoManager::instance().loadAssembly("Path/To/Assembly", "MyManagedAssembly");
 ~~~~~~~~~~~~~ 
 
-In most cases Banshee will load all the necessary assemblies for you, in which case you can just retrieve them by calling @ref bs::MonoManager::getAssembly "MonoManager::getAssembly()".
+You can retrieve a previously loaded assembly by calling @ref bs::MonoManager::getAssembly "MonoManager::getAssembly()".
 
 ~~~~~~~~~~~~~{.cpp}
 // Retrieve the MonoAssembly to a previously loaded assembly
@@ -56,7 +56,7 @@ MonoObject* instance3 = klass->createInstance("int,int,bool", params);
 
 When passing arguments to constructors (and methods in general) you need to place the correct number of parameters in a array of *void* pointers, which you then pass to the invoking method. We'll talk more about how to pass arguments to methods later.
 
-To retrieve a method from a class call @ref bs::MonoClass::getMethod() "MonoClass::getMethod()", accepting a name (without parameter types) and a number of parameters. If your method is overloaded you can use @ref bs::MonoClass::getMethodExact "MonoClass:getMethodExact()" which accepts a method name, and a comma separated list of parameter types. You may also use @ref bs::MonoClass::getAllMethods "MonoClass::getAllMethods()" to retrieve all methods in a class. All three of these methods return a @ref bs::MonoMethod "MonoMethod" object.
+To retrieve a method from a class call @ref bs::MonoClass::getMethod() "MonoClass::getMethod()", accepting a name (without parameter types) and a number of parameters. If your method is overloaded you can use @ref bs::MonoClass::getMethodExact "MonoClass::getMethodExact()" which accepts a method name, and a comma separated list of parameter types. You may also use @ref bs::MonoClass::getAllMethods "MonoClass::getAllMethods()" to retrieve all methods in a class. All three of these methods return a @ref bs::MonoMethod "MonoMethod" object.
 
 ~~~~~~~~~~~~~{.cpp}
 // Get method on the class named "MyMethod", accepting zero parameters
@@ -120,7 +120,7 @@ myStaticField->set(nullptr, &newStaticFieldValue)
 Field values are represented by their raw types if they are value types (*int*, *float* or *struct* types in C#), and as **MonoObject** pointer for reference types.
 
 # MonoProperty {#mono_f}
-Properties are very similar to fields, retrieved from a **MonoClass** object by calling @ref bs::MonoClass::getProperty "MonoClass::getProperty()". The returned value is a @ref bs::MonoProperty "MonoProperty" which provides information about the property and allows you to retrieve and set values on it. The main difference is that properties in C# can be indexed (like arrays) and therefore a two set of set/get methods are provided, one accepting an index and other one not. It's up to the user to know which one to call. The methods are @ref bs::MonoProperty::get "MonoProperty::get()" / @ref bs::MonoProperty::set "MonoProperty::set()" and @ref bs::MonoProperty::getIndexed "MonoProperty::getIndexed()" / @ref bs::MonoProperty::setIndexed "MonoProperty::setIndexed()".
+Properties are very similar to fields, retrieved from a **MonoClass** object by calling @ref bs::MonoClass::getProperty "MonoClass::getProperty()". The returned value is a @ref bs::MonoProperty "MonoProperty" which provides information about the property and allows you to retrieve and set values on it. The main difference is that properties in C# can be indexed (like arrays) and therefore two sets of set/get methods are provided, one accepting an index and other one not. It's up to the user to know which one to call. The methods are @ref bs::MonoProperty::get "MonoProperty::get()" / @ref bs::MonoProperty::set "MonoProperty::set()" and @ref bs::MonoProperty::getIndexed "MonoProperty::getIndexed()" / @ref bs::MonoProperty::setIndexed "MonoProperty::setIndexed()".
 
 ~~~~~~~~~~~~~{.cpp}
 // Read property value from a specific object instance
@@ -246,6 +246,50 @@ for(UINT32 i = 0; i < inArray.size(); i++)
 	output[i] = inArray.get<UINT32>(i);
 ~~~~~~~~~~~~~ 
 
+## MonoObject assignment {#mono_i_d}
+As we discussed earlier, **MonoObject** is garbage collected by the Mono's garbage collector. In order for the GC to be able to track **MonoObject**'s in C++, there are some rules that need to be followed when passing these objects around. 
+
+By default **MonoObject** will not be garabage collected if it is stored on the stack or registers (e.g. a local variable in a function). If that is your only use case then no further action is required. But if you copy it to some heap allocated memory you need to inform the GC of that copy, otherwise it might get collected while you are still using it. Often this is the case when outputting a **MonoObject** through a method parameter (marked with `ref` or `out` in C#).
+
+In these cases instead of assignment (`=` operator), use @ref bs::MonoUtil::referenceCopy() "MonoUtil::referenceCopy()";
+
+~~~~~~~~~~~~~{.cpp}
+// One common example for the use of MonoUtil::referenceCopy is outputting a MonoObject by parameter
+// This is an internal method that gets called from managed code
+void getObject(MonoObject** output)
+{
+	MonoObject* newObj = ...; // Create a new MonoObject (or retrieve one from a stored GC handle)
+	
+	*output = newObj; // WRONG - GC isn't aware of this new reference to the MonoObject*
+	MonoUtil::referenceCopy(output, newObj); // CORRECT - GC is properly notified
+}
+~~~~~~~~~~~~~ 
+
+If a **MonoObject** is a member of a struct which you are copying to some heap allocated memory, you need to use @ref bs::MonoUtil::valueCopy() "MonoUtil::valueCopy()" instead of normal assignment. 
+
+~~~~~~~~~~~~~{.cpp}
+struct SomeStruct
+{
+	int a;
+	MonoObject* b;
+};
+
+// This is an internal method that gets called from managed code
+void getObject(SomeStruct* output)
+{
+	SomeStruct obj;
+	obj.a = 5;
+	obj.b = ...; // Create a new MonoObject (or retrieve one from a stored GC handle)
+	
+	*output = obj; // WRONG
+	
+	MonoClass* structClass = ...; // Retrieve the MonoClass of the struct's type
+	MonoUtil::valueCopy(output, &obj, structClass); // CORRECT - GC is properly notified
+}
+~~~~~~~~~~~~~ 
+
+When writing to arrays using **ScriptArray** you do not need to follow these rules as **ScriptArray** will handle this internally.
+
 # Internal methods {#mono_j}
 So far we have talked about calling managed code, and retrieving information about managed types, but we have yet to show how managed code calls C++ code. This is accomplished using internal methods.
 
@@ -255,7 +299,7 @@ The first step is to define a stub method in managed code, like so:
 private static extern float Internal_GetSomeValue(MyObject obj);
 ~~~~~~~~~~~~~
 	
-You then hook up this method with managed code by calling @ref bs::MonoClass::addInternalCall "MonoClass::addInternalCall". In this specific case it would be:
+You then hook up this method with managed code by calling @ref bs::MonoClass::addInternalCall "MonoClass::addInternalCall()". In this specific case it would be:
 ~~~~~~~~~~~~~{.cpp}
 float myNativeFunction(MonoObject* obj)
 {

+ 2 - 0
Documentation/Manuals/Native/quickref.md

@@ -11,3 +11,5 @@ Here are some common conventions used throughout bs::f:
  - Clockwise faces are considered as front facing
  - Matrices are stored in row major format
  - Vectors are interpreted as column vectors
+ - Default unit of length is meters (1 unit = 1 m)
+ - Default unit of mass is kilogram (1 unit = 1 kg)

+ 3 - 9
Documentation/Manuals/Native/scriptObjects.md

@@ -2,7 +2,7 @@ Script objects									{#scriptObjects}
 ===============
 [TOC]
 
-What we have shown in the previous manual is enough to expose an object to C# and communicate with it. However Banshee provides another API built on top of that functionality in the form of script objects. This API handles some of the boilerplate code required for exposing an object to C#, provides a common interface all script objects need to implement, handles assembly refresh (due to script hot-swap) and gracefully handles managed object lifetime and destruction.
+What we have shown in the previous manual is enough to expose an object to C# and communicate with it. However bs::f provides another API built on top of that functionality in the form of script objects. This API handles some of the boilerplate code required for exposing an object to C#, provides a common interface all script objects need to implement, handles assembly refresh (due to script hot-swap) and gracefully handles managed object lifetime and destruction.
 
 To implement the script object interface for a particular type you need two classes:
  - A native interop class (C++)
@@ -83,12 +83,6 @@ void ScriptMyObject::internal_SetSomeObject(MonoObject* obj)
 }
 ~~~~~~~~~~~~~
 
-And vice versa, you can retrieve the **MonoObject** from a **ScriptObject** by calling @ref bs::ScriptObjectBase::getManagedInstance() "ScriptObject::getManagedInstance()".
-~~~~~~~~~~~~~{.cpp}
-ScriptMyObject myObj = ...;
-MonoObject* monoObj = myObj->getManagedInstance();
-~~~~~~~~~~~~~
-
 ## Destroying script object instances ### {#scripting_a_b}
 When the managed object is destroyed (e.g. goes out of scope and gets garbage collected) the system will automatically take care of freeing the related **ScriptObject**. If you need to add onto or replace that functionality you can override @ref bs::ScriptObjectBase::_onManagedInstanceDeleted "ScriptObject::_onManagedInstanceDeleted()" method. This is useful if you need to perform some additional cleanup.
 
@@ -153,7 +147,7 @@ float ScriptMyObject::internal_GetSomeValue(ScriptMyObject* obj)
 ~~~~~~~~~~~~~
 
 # Assembly refresh {#scripting_c}
-Assembly refresh is the process that happens when managed code is recompiled and scripts need to be reloaded. This is primarily used in Banshee editor to hot-reload the scripts while the editor is still running. When assembly refresh happens all managed objects are effectively destroyed.
+Assembly refresh is the process that happens when managed code is recompiled and scripts need to be reloaded. This is primarily used in Banshee 3D editor to hot-reload the scripts while the editor is still running. When assembly refresh happens all managed objects are effectively destroyed.
 
 By default any script objects of such managed objects are destroyed as well. In many cases this is okay, for example GUI elements don't persist refresh, because they're just rebuilt from the managed code every time the refresh happens. However objects like resources, scene objects and components are persistent - we don't wish to reload the entire scene and all resources every time assembly refresh happens.
 
@@ -167,7 +161,7 @@ class MyScriptObject : public ScriptObject<MyScriptObject, PersistentScriptObjec
 ~~~~~~~~~~~~~	
 	
 This ensures that your object is treated properly during assembly refresh. Persistent object then needs to handle four different actions, represented by overrideable methods. These methods are called in order specified, during assembly refresh.
- - @ref bs::ScriptObjectBase::beginRefresh() "ScriptObject::beginRefresh()" - Called just before the refresh starts. The object is still alive here and you can perform needed actions (e.g. saving managed object's contents).
+ - @ref bs::ScriptObjectBase::beginRefresh() "ScriptObject::beginRefresh()" - Called just before the refresh starts. The object is still alive here and you can use this time to save the contents of the managed object before it is destroyed.
  - @ref bs::ScriptObjectBase::_onManagedInstanceDeleted "ScriptObject::_onManagedInstanceDeleted()" - Called after assembly unload happened and the managed object was destroyed. You should override this to prevent the **ScriptObject** itself from being deleted if the assembly refresh is in progress. If assembly refresh is not in progress this method should delete the **ScriptObject** as it likely got called due to standard reasons (managed object went out of scope).
  - @ref bs::ScriptObject::_createManagedInstance "ScriptObject::_createManagedInstance()" - Creates the managed instance after new assemblies are loaded. You should override this if your managed class is constructed using a constructor with parameters. By default this will call **MonoClass::createInstance()** using the parameterless constructor.
  - @ref bs::ScriptObjectBase::endRefresh() "ScriptObject::endRefresh()" - Called after all assemblies are loaded, and after all script interop objects were either destroyed (non-persistent) or had their managed instances re-created (persistent). If you stored any data during **ScriptObject::beginRefresh()**, you should restore it here.

+ 7 - 7
Documentation/Manuals/Native/scriptingAuto.md

@@ -2,9 +2,9 @@ Exposing code to script API (automated)			{#scriptingAuto}
 ===============
 [TOC]
 
-When you've added a new feature, system or just extended existing ones you might want to expose that functionality to the scripting API. Banshee makes this process easier through its automated script binding generator tool. All you need to do is to decorate the C++ types and methods you wish to export and run the tool. The tool is ran automatically whenever you build through CMake.
+When you've added a new feature, system or just extended existing ones you might want to expose that functionality to the scripting API. bs::f makes this process easier through its automated script binding generator tool. All you need to do is to decorate the C++ types and methods you wish to export and run the tool. The tool is ran automatically whenever you build through CMake if *GENERATE_SCRIPT_BINDINGS* option is turned on.
 
-In order to decorate C++ you use the **BS_SCRIPT_EXPORT** macro, which supports a variety of parameters used for customizing how will the type/method be exported.
+@ref **BS_SCRIPT_EXPORT** macro supports a variety of parameters used for customizing how will the type/method be exported.
 
 # Exporting classes {#scriptingAuto_a}
 In order to export a class to script code you need to decorate the class and one or multiple methods with **BS_SCRIPT_EXPORT** macro. 
@@ -71,10 +71,10 @@ public:
 	void setPlainType(UINT32 value);	
 	
 	BS_SCRIPT_EXPORT()
-	std::string getString(); // or std::wstring
+	String getString();
 	
 	BS_SCRIPT_EXPORT()
-	void setString(const std::string& value); // or std::wstring	
+	void setString(const String& value);	
 	
 	BS_SCRIPT_EXPORT()
 	HMesh getResource();
@@ -123,7 +123,7 @@ public partial class MyRenamedClass : ScriptObject
 ~~~~~~~~~~~~~
 
 ## Visibility {#scriptingAuto_a_b}
-You can make a type or a method *public*, *internal* or *private* by specifying the "v" parameter. Accepted values are "public", "internal" and "private. By default all types and methods are public.
+You can make a type or a method *public*, *internal* or *private* by specifying the "v" parameter. Accepted values are "public", "internal" and "private". By default all types and methods are public.
 
 ~~~~~~~~~~~~~{.cpp}
 class BS_SCRIPT_EXPORT() MyClass
@@ -144,7 +144,7 @@ public partial class MyRenamedClass : ScriptObject
 ~~~~~~~~~~~~~
 
 ## Exporting as properties  {#scriptingAuto_a_c}
-Parameter named "pr" allows you to specify that a method should be exported as a property. The supported values for the parameter are "getter" or "setter". When exposing a method as a property the name ("n") parameter is required and ii should be the name of the property.
+Parameter named "pr" allows you to specify that a method should be exported as a property. The supported values for the parameter are "getter" or "setter". When exposing a method as a property the name ("n") parameter is required and should be the name of the property.
 
 ~~~~~~~~~~~~~{.cpp}
 // Decorate the class and the methods with BS_SCRIPT_EXPORT modifier
@@ -397,4 +397,4 @@ External methods must follow these rules:
  - External methods must accept the type they're external to as the first parameter 
  
 # Running the code generator {#scriptingAuto_f}
-Once you have decorated the C++ classes with necessary export parameters you can run the code generator simply by regenerating the CMake build. The generator will run automatically over all Banshee code and generate relevant script code.
+Once you have decorated the C++ classes with necessary export parameters you can run the code generator simply by enabling *GENERATE_SCRIPT_BINDINGS* and regenerating the CMake build. The generator will run automatically over all bs::f code and generate relevant script code.