فهرست منبع

Fixing Vector GUI fields so their events don't cause a crash

BearishSun 9 سال پیش
والد
کامیت
a92a2d6649

+ 236 - 235
Documentation/Manuals/Native/scripting.md

@@ -1,236 +1,237 @@
-Scripting									{#scripting}
-===============
-[TOC]
-
-Often when you extend the native portion of the engine in some way you might want to expose that functionality to the managed (i.e. scripting) code. This guide will show you how to create C++ objects that communicate with C# code and vice versa. 
-
-Before we delve into the specifics of Banshee’s scripting you should understand how the scripting system works in general. All C# script code is ran from the C++ part of the engine using the Mono runtime. Mono runtime allows you to communicate with C# code (and for the C# code to communicate with C++), query class/method/field information and pass data between the two languages.
-
-# Scripting system #	{#scripting_a}
-
-Because using Mono directly is complex because its lack of documentation, Banshee provides a set of easy to use wrappers for almost all of Mono related functionality. 
-
-BansheeMono is a plugin that wraps the functionality of the Mono runtime. Here is where the Mono runtime is started and assemblies are loaded (and unloaded), while also giving you detailed information about all loaded classes and a way to communicate with managed code.
-
-The main entry point is the MonoManager class which allows you to start the runtime and load assemblies. The most important method here is MonoManager::loadAssembly. It takes as assembly path to load and returns a MonoAssembly object. 
-
-## MonoAssembly 	{#scripting_a_a}
-MonoAssembly gives you access to all classes in the assembly. You can retrieve all clases using MonoAssembly::getAllClasses, or retrieve a specific one by calling MonoAssembly::getClass(namespace, typename). Both of these methods return a MonoClass object.
-
-## MonoClass 	{#scripting_a_b}
-MonoClass gives you access to all methods, fields, properties and attributes of a specific class. It also allows you to register “internal” methods. These methods allow the managed code to call C++ code, and we’ll go into them later.
-
-Classes also allow you to create object instances of their type. Use MonoClass::createInstance to create a new object instance. All managed objects are referenced using a MonoObject type (more on that later), which is returned from the MonoClass::createInstance call. When creating an instance you may choose whether to construct it or not, and to provide constructor signature if you need a specific one.
-
-To retrieve a method from a class call MonoClass::getMethod(), accepting a name (without parameter types) and a number of parameters. If your method is overloaded you can use MonoClass::getMethodExact which accepts a method name, and a comma separated list of parameter types. You may also use MonoClass::getAllMethods to retrieve all methods in a class.
-
-All the above methods return a MonoMethod object.
-
-## MonoMethod {#scripting_a_c}
-This class provides information about about a managed method, as well as giving you multiple ways of invoking it.
-
-To invoke a method you may use multiple approaches:
- - MonoMethod::invoke - Calls the exact method on a specific managed object, with the provided parameters. We’ll take about how managed objects are referenced in native code later, as well as how passing data between C++ and managed code works.
- - MonoMethod::invokeVirtual - Calls the method polymorphically. Determines the actual type of the provided managed object instance and calls an overriden method if available.
- - MonoMethod::getThunk - Returns a C++ function pointer accepting a managed object, zero or more parameters and an exception object. You can then call the function pointer like you would a C++ function. This is equivalent to MonoMethod::invoke but is significantly faster. A helper method MonoUtil::invokeThunk is provided - it is suggested you use it instead of calling thunks manually (it handles exceptions without you needing to worry about it).
-
-When calling static methods you should provide a null value for the managed object instance.
-
-## MonoField {#scripting_a_d}
-Similar to methods, field information can be retrieved from MonoClass by calling MonoClass::getField or MonoClass::getAllFields. The returned value is a MonoField which provides information about the field and allows you to retrieve and set values in the field using MonoField::getValue/MonoField::setValue. This works similar to how methods are invoked and is explained in more detail later.
-
-## MonoProperty {#scripting_a_e}
-Properties are very similar to fields, retrieved from MonoClass by calling MonoClass::getProperty or MonoClass::getAllProperties. The returned value is a MonoProperty which provides information about the property and allows you to retrieve and set values in 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 MonoPropety::get/MonoProperty::set and MonoProperty::getIndexed/MonoProperty::setIndexed.
-
-## Attributes {#scripting_a_f}
-Attributes provide data about a class, method or field provided at runtime, and allows them to be customized in more detail. Attributes don’t have their own wrapper, because they are esentially normal managed objects and you can work with them as such.
-
-To retrieve a list of attributes from a class use: MonoClass::getAllAttributes(), which returns a list of MonoClass objects that identify the attribute types. To get the actual object instance of the attribute you may call MonoClass::getAttribute with the wanted attribute MonoClass. After that you can call methods, work with field values and other, same as you would with a normal object.
-
-Attributes can also be retrieved from MonoMethod using MonoMethod::getAttribute, or from MonoField using MonoField::getAttribute.
-
-## Managed objects {#scripting_a_g}
-So far we have talked about invoking methods and retrieving field values, but we haven’t yet explained how to access managed object instances in C++ code. All managed objects in Mono are represented by a MonoObject.
-
-For example, when calling a non-static method the first parameter provided to MonoMethod::invoke is a MonoObject pointer. Same goes for retrieving or setting values on fields, properties. Attributes are also a MonoObject.
-
-Mono also provides two more specialized types: MonoArray for managed arrays, and MonoString for managed strings, but they are both still a MonoObject.
-
-Be aware that all managed objects are garbage collected. This means you should not keep a reference to them unless you are sure they are alive. Just having a pointer to a MonoObject will not keep the object alive and it may go out of scope as soon as the control returns to managed code. A good way to deal with this issue is:
- - Call a native method in the object’s finalizer (~MyObject()) which will notify you when the object is no longer valid. Be aware that finalizer may be called after the object is unusable.
- - Require the user to manually destroy the object by calling a custom Destroy method or similar.
- - Force the garbage collector to keep the object alive by calling “mono_gchandle_new” which will return a handle to the object. The handle will keep the object alive until you release it by calling “mono_gchandle_free”. Be aware if an assembly the object belongs to is unloaded all objects will be destroyed regardless of the kept handles.
- 
-## Marshalling data {#scripting_a_h}
-Mono does not perform automatic marshalling of data when calling managed code from C++ (or vice versa). This is important when calling methods, retrieving/setting field/property values, and responding to calls from managed code, because you need to know in what format to expect the data.
-
-The rules are:
- - All primitive types are passed as in. e.g. an int in C# will be a 4 byte integer in C++, a float will be a float, a bool will be a bool.
- - All reference types (“class” in C#) are passed as a MonoObject*. Strings and arrays are handled specially, where strings are passed as MonoString*, and arrays as MonoArray*.
-   - If a reference type parameter in a method is prefixed with an “out” modifier, then the received parameters are MonoObject**, MonoString**, MonoArray** and your method is expected to populate those values.
- - Structs (non-primitive value types) are provided as raw memory. Make sure that all structs in C# have a ”[StructLayout(LayoutKind.Sequential)]” attribute, which ensures they have the same memory layout as C++ structs. This way you can just accept the raw C++ structure and read it with no additional conversion.
-  - It is suggested you never pass structures by value, it is known to cause problems in Mono. Instead pass all structures by prefixing them with “ref” which will give you a pointer to the structure in managed code (e.g. MyStruct*). If you need to output a struct use the “out” modifier which you will give you a double pointer (e.g. MyStruct**).
-  - In cases where it is not possible to avoid passing structures by value (e.g. when retrieving them from a field, use the MonoField::getValueBoxed method instead MonoField::getValue, which will return a struct in the form of a MonoObject. You can then retrieve the raw struct value by calling mono_object_unbox.
-  
-Banshee provides a helper code to assist with marshalling string:
- - MonoUtil::toWString/MonoUtil::toString - Converts a MonoString* to a native string
- - MonoUtil::fromWString/MonoUtil::fromString - Converts a native string into a MonoString*
-
-ScriptArray allows you to construct new arrays and read managed arrays, easily. 
-
-To create a new arrays call ScriptArray<Type>::create. Type can be a primitive type like int, float, a native string or a Script* object (more about Script* objects later). You can then fill the array by calling ScriptArray::set and retrieve the managed MonoArray* by calling ScriptArray::getInternal.
-
-To more easily read existing arrays create a new ScriptArray by providing it with a MonoArray* as its parameters. Then you can easily retrieve the size of the array using ScriptArray::size(), and the value of its elements by calling ScriptArray::get<Type>. 
-
-## Internal methods {#scripting_a_i}
-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 native methods.
-
-The first step is to define a stub method in managed code, like so:
-	[MethodImpl(MethodImplOptions.InternalCall)]
-	private static extern float Internal_GetSomeValue(MyObject obj);
-
-You then hook up this method with managed code by calling MonoClass:addInternalMethod. In this specific case it would be myClass->ddInternalMethod(“Internal_GetSomeValue”, &myNativeFunction), assuming myClass is a MonoClass of the type that contains the stub method. After this call any call to the managed stub method will call the provide native function myNativeFunction. You should take care to properly handle parameter passing as described above.
-
-Take a look at ScriptGUISkin implementation for a simple example of how exactly does this work. 
-
-# Script objects {#scripting_b}
-As you can see interaction between the two languages can get a bit cumbersome. For that reason Banshee implements a higher level system built on the functionality shown so far. It provides an universal interface all script objects must implement. It primarily ensures that native and managed code is always linked by keeping a pointer to each other's objects, as well as gracefully handling managed object destruction and handling assembly refresh (due to script hot-swap).
-
-When creating a new class available for scripting you need to add two things:
- - A native interop object (C++)
- - Managed wrapper for the class (C#)
-
-## Native interop object ## {#scripting_b_a}
-
-All native interop objects implement the ScriptObject interface. A basic implementation of such an interface is:
-	class ScriptMyObject : public ScriptObject <ScriptMyObject>
-	{
-	public:
-		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "MyObject")
-
-	private:
-		ScriptMyObject(MonoObject* instance);
-		
-		static void internal_CreateInstance(MonoObject* obj);
-		static float internal_GetSomeValue(MonoObject* obj);
-	};
-	
-All ScriptObject must begin with a SCRIPT_OBJ macro. The macro accepts (in order): 
- - the name of the assembly (.dll) the manager script object is in, this is either ENGINE_ASSEMBLY or EDITOR_ASSEMBLY
- - the namespace the type is in
- - the name of the managed type
-
-SCRIPT_OBJ macro also defines a static initRuntimeData() method you need to implement (more on that later).
-
-When constructing a ScriptObject you must also provide a pointer to the managed object that wraps it (note the constructor). If the ScriptObject is used for a class that is static then the constructor is of no consequence as the ScriptObject itself never needs to be instantiated (all of its method will be static). 
- 
-The two last method definitions are called from C# (via an internal call, see the section about internal methods earlier).
-
-### initRuntimeData ### {#scripting_b_a_a}
-initRuntimeData is a static method that every ScriptObject needs to implement. It takes care of hooking up managed internal methods to C++ functions. It gets called automatically whenever the assembly containing the related managed class is loaded. 
-
-Every ScriptObject provides a static "metaData" structure you can use for retrieving the MonoClass of the related managed class. You can use that MonoClass to register internal methods to it (as described earlier). For example a basic initRuntimeData() might look like so:
-	void ScriptMyObject::initRuntimeData()
-	{
-		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptFont::internal_CreateInstance);
-		metaData.scriptClass->addInternalCall("Internal_GetSomeValue", &ScriptFont::internal_GetSomeValue);
-	}
-
-initRuntimeData is also a good spot to retrieve MonoMethod (or thunks) for managed methods that needed to be called by the script interop object, if any.
-
-### Creating script object instances ### {#scripting_b_a_b}	
-If your class is not static you will need to eventually create an instance of the script object. This can be done either from C# or C++, depending on what is needed. For example script interop objects for GUI will be created from managed code because user can add GUI elements himself, but a resource like Font will have its script interop object (and managed instanced) created purely from C++ because such an object cannot be created directly in managed code.
-
-For the first case you should set up an internal method that accepts the managed object instance, and is called in the managed constructor (internal_CreateInstance in above example). This way the method gets called whenever the managed object gets created and you can create the related script interop object. A simple implementation would look like so:
-
-	void ScriptMyObject::internal_createInstance(MonoObject* obj)
-	{
-		bs_new<ScriptMyObject>(obj);
-	}
-	
-Note that you don't actually need to store the created object anywhere. The ScriptObject constructor ensures that the pointer to the script interop object is stored in the managed object.
-
-For the second case where you want to create the interop object from C++ you can create a static create() method like so:
-    MonoObject* ScriptMyObject::create()
-	{
-		MonoObject* managedObj = metaData.scriptClass->createInstance();
-		bs_new<ScriptMyObject>(managedObj);
-		
-		return managedObj;
-	}
-	
-In this case the method calls a parameterless constructor but you may specify parameters as needed.
-
-If you have a MonoObject* but need to retrieve its ScriptObject use toNative(MonoObject*) static method. e.g. ScriptMyObject::toNative(). Within the interop object instance you can use ScriptObject::getManagedInstance() to retrieve the managed object.
-
-### Destroying script object instances ### {#scripting_b_a_c}
-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 ScriptObject::_onManagedInstanceDeleted method.
-
-## Managed wrapper object ## {#scripting_b_b}
-Creating the script interop object is one half of the job done. You also need to create the managed counterpart, however that is significantly simpler.
-
-Every managed script object must implement the ScriptObject interface. For example a C# version of the class we're using in this example would look like:
-	namespace BansheeEngine
-	{
-		public class MyObject : ScriptObject
-		{
-			public MyObject()
-			{
-				Internal_CreateInstance(this)
-			}
-			
-			public float SomeValue
-			{
-				get { return Internal_GetSomeValue(this); }
-			}
-			
-			[MethodImpl(MethodImplOptions.InternalCall)]
-			private static extern void Internal_CreateInstance(MyObject obj);
-			
-			[MethodImpl(MethodImplOptions.InternalCall)]
-			private static extern float Internal_GetSomeValue(MyObject obj);
-		}
-	}
-
-That's all that needs to be done. You can now create the object in C# and use its property to retrieve the value from C++ code. All ScriptObjects provide a GetCachedPtr method which returns an IntPtr which points to the script interop object described in previous sections.
-
-## Assembly refresh ##
-What has been shown so far is enough to create a class exposed to script, however object of such a class will not survive assembly refresh. Assembly refresh happens when scripts are recompiled and managed assemblies are unloaded and reloaded. This is something that generally happens only in the editor.
-
-If you don't care about your object surving the refresh, you do not need to implement what is described here. 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.
-
-A persistent script object need to inherit a variation of ScriptObject like so:
-	class MyScriptObject : public ScriptObject<MyScriptObject, PersistentScriptObjectBase>
-	
-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.
- - 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). You can choose to to override this method.
- - 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 (which is what the default implementation does). If assembly refresh is not in progress this method should delete the ScriptObject normals because it likely got called due to normal reasons (managed object went out of scope).
- - 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.
- - ScriptObject::endRefresh() - Called after all assemblies are loaded, and after all script interop objects were either destroyed (non-persistent) or had their managed instances created (persistent). Allows you to restore data stored in beginRefresh(), but that is optional.
- 
-See ScriptSceneObject and its base class ScriptGameObjectBase for example implementations of these methods.
-
-## Deriving from ScriptObject ##
-Sometimes script objects are polymorphic. For example a GUIElement is derived from ScriptObject in managed code, and GUIButton from GUIElement, however they both have script interop objects of their own.
-
-Due to the nature our script interop objects are defined we cannot follow the same simple chain of inheritance in C++ code. For example class definition script interop object for GUIElement would be:
-	class ScriptGUIElement : public ScriptObject<ScriptGUIElement>
-	{
-	public:
-		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "GUIElement")
-	...
-	}
-	
-But what would it be for GUIButton?	It also needs to implement ScriptObject with its own SCRIPT_OBJ macro so we cannot just inherit from ScriptGUIElement directly as it would clash.
-
-The solution is to create a third class that will serve as a base for both. This third class will be a base class for ScriptObject (it's second template parameter allows us to override its default ScriptObjectBase base class). The third class will need to inherit ScriptObjectBase and can implement any functionality common to all GUI elements (e.g. it might store a pointer to a native GUIElement*).
-
-Then we can define script interop object for GUI element as:
-	class ScriptGUIElement : public ScriptObject<ScriptGUIElement, ScriptGUIElementBase>
-	
-Where ScriptGUIElementBase is our third class. Interop object for GUIButton would then be:
-	class ScriptGUIButton : public ScriptObject<ScriptGUIButton, ScriptGUIElementBase>
-	
-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.
-
+Scripting									{#scripting}
+===============
+[TOC]
+
+Often when you extend the native portion of the engine in some way you might want to expose that functionality to the managed (i.e. scripting) code. This guide will show you how to create C++ objects that communicate with C# code and vice versa. 
+
+Before we delve into the specifics of Banshee’s scripting you should understand how the scripting system works in general. All C# script code is ran from the C++ part of the engine using the Mono runtime. Mono runtime allows you to communicate with C# code (and for the C# code to communicate with C++), query class/method/field information and pass data between the two languages.
+
+# Scripting system #	{#scripting_a}
+
+Because using Mono directly is complex because its lack of documentation, Banshee provides a set of easy to use wrappers for almost all of Mono related functionality. 
+
+BansheeMono is a plugin that wraps the functionality of the Mono runtime. Here is where the Mono runtime is started and assemblies are loaded (and unloaded), while also giving you detailed information about all loaded classes and a way to communicate with managed code.
+
+The main entry point is the MonoManager class which allows you to start the runtime and load assemblies. The most important method here is MonoManager::loadAssembly. It takes as assembly path to load and returns a MonoAssembly object. 
+
+## MonoAssembly 	{#scripting_a_a}
+MonoAssembly gives you access to all classes in the assembly. You can retrieve all clases using MonoAssembly::getAllClasses, or retrieve a specific one by calling MonoAssembly::getClass(namespace, typename). Both of these methods return a MonoClass object.
+
+## MonoClass 	{#scripting_a_b}
+MonoClass gives you access to all methods, fields, properties and attributes of a specific class. It also allows you to register “internal” methods. These methods allow the managed code to call C++ code, and we’ll go into them later.
+
+Classes also allow you to create object instances of their type. Use MonoClass::createInstance to create a new object instance. All managed objects are referenced using a MonoObject type (more on that later), which is returned from the MonoClass::createInstance call. When creating an instance you may choose whether to construct it or not, and to provide constructor signature if you need a specific one.
+
+To retrieve a method from a class call MonoClass::getMethod(), accepting a name (without parameter types) and a number of parameters. If your method is overloaded you can use MonoClass::getMethodExact which accepts a method name, and a comma separated list of parameter types. You may also use MonoClass::getAllMethods to retrieve all methods in a class.
+
+All the above methods return a MonoMethod object.
+
+## MonoMethod {#scripting_a_c}
+This class provides information about about a managed method, as well as giving you multiple ways of invoking it.
+
+To invoke a method you may use multiple approaches:
+ - MonoMethod::invoke - Calls the exact method on a specific managed object, with the provided parameters. We’ll take about how managed objects are referenced in native code later, as well as how passing data between C++ and managed code works.
+ - MonoMethod::invokeVirtual - Calls the method polymorphically. Determines the actual type of the provided managed object instance and calls an overriden method if available.
+ - MonoMethod::getThunk - Returns a C++ function pointer accepting a managed object, zero or more parameters and an exception object. You can then call the function pointer like you would a C++ function. This is equivalent to MonoMethod::invoke but is significantly faster. A helper method MonoUtil::invokeThunk is provided - it is suggested you use it instead of calling thunks manually (it handles exceptions without you needing to worry about it).
+
+When calling static methods you should provide a null value for the managed object instance.
+
+## MonoField {#scripting_a_d}
+Similar to methods, field information can be retrieved from MonoClass by calling MonoClass::getField or MonoClass::getAllFields. The returned value is a MonoField which provides information about the field and allows you to retrieve and set values in the field using MonoField::getValue/MonoField::setValue. This works similar to how methods are invoked and is explained in more detail later.
+
+## MonoProperty {#scripting_a_e}
+Properties are very similar to fields, retrieved from MonoClass by calling MonoClass::getProperty or MonoClass::getAllProperties. The returned value is a MonoProperty which provides information about the property and allows you to retrieve and set values in 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 MonoPropety::get/MonoProperty::set and MonoProperty::getIndexed/MonoProperty::setIndexed.
+
+## Attributes {#scripting_a_f}
+Attributes provide data about a class, method or field provided at runtime, and allows them to be customized in more detail. Attributes don’t have their own wrapper, because they are esentially normal managed objects and you can work with them as such.
+
+To retrieve a list of attributes from a class use: MonoClass::getAllAttributes(), which returns a list of MonoClass objects that identify the attribute types. To get the actual object instance of the attribute you may call MonoClass::getAttribute with the wanted attribute MonoClass. After that you can call methods, work with field values and other, same as you would with a normal object.
+
+Attributes can also be retrieved from MonoMethod using MonoMethod::getAttribute, or from MonoField using MonoField::getAttribute.
+
+## Managed objects {#scripting_a_g}
+So far we have talked about invoking methods and retrieving field values, but we haven’t yet explained how to access managed object instances in C++ code. All managed objects in Mono are represented by a MonoObject.
+
+For example, when calling a non-static method the first parameter provided to MonoMethod::invoke is a MonoObject pointer. Same goes for retrieving or setting values on fields, properties. Attributes are also a MonoObject.
+
+Mono also provides two more specialized types: MonoArray for managed arrays, and MonoString for managed strings, but they are both still a MonoObject.
+
+Be aware that all managed objects are garbage collected. This means you should not keep a reference to them unless you are sure they are alive. Just having a pointer to a MonoObject will not keep the object alive and it may go out of scope as soon as the control returns to managed code. A good way to deal with this issue is:
+ - Call a native method in the object’s finalizer (~MyObject()) which will notify you when the object is no longer valid. Be aware that finalizer may be called after the object is unusable.
+ - Require the user to manually destroy the object by calling a custom Destroy method or similar.
+ - Force the garbage collector to keep the object alive by calling “mono_gchandle_new” which will return a handle to the object. The handle will keep the object alive until you release it by calling “mono_gchandle_free”. Be aware if an assembly the object belongs to is unloaded all objects will be destroyed regardless of the kept handles.
+ 
+## Marshalling data {#scripting_a_h}
+Mono does not perform automatic marshalling of data when calling managed code from C++ (or vice versa). This is important when calling methods, retrieving/setting field/property values, and responding to calls from managed code, because you need to know in what format to expect the data.
+
+The rules are:
+ - All primitive types are passed as is. e.g. an int in C# will be a 4 byte integer in C++, a float will be a float, a bool will be a bool.
+ - All reference types (“class” in C#) are passed as a MonoObject*. Strings and arrays are handled specially, where strings are passed as MonoString*, and arrays as MonoArray*.
+   - If a reference type parameter in a method is prefixed with an “out” modifier, then the received parameters are MonoObject**, MonoString**, MonoArray** and your method is expected to populate those values.
+ - Structs (non-primitive value types) are provided as raw memory. Make sure that all structs in C# have a ”[StructLayout(LayoutKind.Sequential)]” attribute, which ensures they have the same memory layout as C++ structs. This way you can just accept the raw C++ structure and read it with no additional conversion.
+  - It is suggested you never pass structures by value, it is known to cause problems in Mono. Instead pass all structures by prefixing them with “ref” which will give you a pointer to the structure in managed code (e.g. MyStruct*). If you need to output a struct use the “out” modifier which you will give you a double pointer (e.g. MyStruct**).
+  - In cases where it is not possible to avoid passing structures by value (e.g. when retrieving them from a field, use the MonoField::getValueBoxed method instead MonoField::getValue, which will return a struct in the form of a MonoObject. You can then retrieve the raw struct value by calling mono_object_unbox.
+  - Everything above applies only when managed code is calling C++. When calling into managed code from C++, all structs need to be boxed (i.e. converted to MonoObject). Use mono_value_box to convert a C++ struct into a MonoObject*. See ScriptVector3 for an example implementation.
+  
+Banshee provides a helper code to assist with marshalling string:
+ - MonoUtil::toWString/MonoUtil::toString - Converts a MonoString* to a native string
+ - MonoUtil::fromWString/MonoUtil::fromString - Converts a native string into a MonoString*
+
+ScriptArray allows you to construct new arrays and read managed arrays, easily. 
+
+To create a new arrays call ScriptArray<Type>::create. Type can be a primitive type like int, float, a native string or a Script* object (more about Script* objects later). You can then fill the array by calling ScriptArray::set and retrieve the managed MonoArray* by calling ScriptArray::getInternal.
+
+To more easily read existing arrays create a new ScriptArray by providing it with a MonoArray* as its parameters. Then you can easily retrieve the size of the array using ScriptArray::size(), and the value of its elements by calling ScriptArray::get<Type>. 
+
+## Internal methods {#scripting_a_i}
+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 native methods.
+
+The first step is to define a stub method in managed code, like so:
+	[MethodImpl(MethodImplOptions.InternalCall)]
+	private static extern float Internal_GetSomeValue(MyObject obj);
+
+You then hook up this method with managed code by calling MonoClass:addInternalMethod. In this specific case it would be myClass->ddInternalMethod(“Internal_GetSomeValue”, &myNativeFunction), assuming myClass is a MonoClass of the type that contains the stub method. After this call any call to the managed stub method will call the provide native function myNativeFunction. You should take care to properly handle parameter passing as described above.
+
+Take a look at ScriptGUISkin implementation for a simple example of how exactly does this work. 
+
+# Script objects {#scripting_b}
+As you can see interaction between the two languages can get a bit cumbersome. For that reason Banshee implements a higher level system built on the functionality shown so far. It provides an universal interface all script objects must implement. It primarily ensures that native and managed code is always linked by keeping a pointer to each other's objects, as well as gracefully handling managed object destruction and handling assembly refresh (due to script hot-swap).
+
+When creating a new class available for scripting you need to add two things:
+ - A native interop object (C++)
+ - Managed wrapper for the class (C#)
+
+## Native interop object ## {#scripting_b_a}
+
+All native interop objects implement the ScriptObject interface. A basic implementation of such an interface is:
+	class ScriptMyObject : public ScriptObject <ScriptMyObject>
+	{
+	public:
+		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "MyObject")
+
+	private:
+		ScriptMyObject(MonoObject* instance);
+		
+		static void internal_CreateInstance(MonoObject* obj);
+		static float internal_GetSomeValue(MonoObject* obj);
+	};
+	
+All ScriptObject must begin with a SCRIPT_OBJ macro. The macro accepts (in order): 
+ - the name of the assembly (.dll) the manager script object is in, this is either ENGINE_ASSEMBLY or EDITOR_ASSEMBLY
+ - the namespace the type is in
+ - the name of the managed type
+
+SCRIPT_OBJ macro also defines a static initRuntimeData() method you need to implement (more on that later).
+
+When constructing a ScriptObject you must also provide a pointer to the managed object that wraps it (note the constructor). If the ScriptObject is used for a class that is static then the constructor is of no consequence as the ScriptObject itself never needs to be instantiated (all of its method will be static). 
+ 
+The two last method definitions are called from C# (via an internal call, see the section about internal methods earlier).
+
+### initRuntimeData ### {#scripting_b_a_a}
+initRuntimeData is a static method that every ScriptObject needs to implement. It takes care of hooking up managed internal methods to C++ functions. It gets called automatically whenever the assembly containing the related managed class is loaded. 
+
+Every ScriptObject provides a static "metaData" structure you can use for retrieving the MonoClass of the related managed class. You can use that MonoClass to register internal methods to it (as described earlier). For example a basic initRuntimeData() might look like so:
+	void ScriptMyObject::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptFont::internal_CreateInstance);
+		metaData.scriptClass->addInternalCall("Internal_GetSomeValue", &ScriptFont::internal_GetSomeValue);
+	}
+
+initRuntimeData is also a good spot to retrieve MonoMethod (or thunks) for managed methods that needed to be called by the script interop object, if any.
+
+### Creating script object instances ### {#scripting_b_a_b}	
+If your class is not static you will need to eventually create an instance of the script object. This can be done either from C# or C++, depending on what is needed. For example script interop objects for GUI will be created from managed code because user can add GUI elements himself, but a resource like Font will have its script interop object (and managed instanced) created purely from C++ because such an object cannot be created directly in managed code.
+
+For the first case you should set up an internal method that accepts the managed object instance, and is called in the managed constructor (internal_CreateInstance in above example). This way the method gets called whenever the managed object gets created and you can create the related script interop object. A simple implementation would look like so:
+
+	void ScriptMyObject::internal_createInstance(MonoObject* obj)
+	{
+		bs_new<ScriptMyObject>(obj);
+	}
+	
+Note that you don't actually need to store the created object anywhere. The ScriptObject constructor ensures that the pointer to the script interop object is stored in the managed object.
+
+For the second case where you want to create the interop object from C++ you can create a static create() method like so:
+    MonoObject* ScriptMyObject::create()
+	{
+		MonoObject* managedObj = metaData.scriptClass->createInstance();
+		bs_new<ScriptMyObject>(managedObj);
+		
+		return managedObj;
+	}
+	
+In this case the method calls a parameterless constructor but you may specify parameters as needed.
+
+If you have a MonoObject* but need to retrieve its ScriptObject use toNative(MonoObject*) static method. e.g. ScriptMyObject::toNative(). Within the interop object instance you can use ScriptObject::getManagedInstance() to retrieve the managed object.
+
+### Destroying script object instances ### {#scripting_b_a_c}
+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 ScriptObject::_onManagedInstanceDeleted method.
+
+## Managed wrapper object ## {#scripting_b_b}
+Creating the script interop object is one half of the job done. You also need to create the managed counterpart, however that is significantly simpler.
+
+Every managed script object must implement the ScriptObject interface. For example a C# version of the class we're using in this example would look like:
+	namespace BansheeEngine
+	{
+		public class MyObject : ScriptObject
+		{
+			public MyObject()
+			{
+				Internal_CreateInstance(this)
+			}
+			
+			public float SomeValue
+			{
+				get { return Internal_GetSomeValue(this); }
+			}
+			
+			[MethodImpl(MethodImplOptions.InternalCall)]
+			private static extern void Internal_CreateInstance(MyObject obj);
+			
+			[MethodImpl(MethodImplOptions.InternalCall)]
+			private static extern float Internal_GetSomeValue(MyObject obj);
+		}
+	}
+
+That's all that needs to be done. You can now create the object in C# and use its property to retrieve the value from C++ code. All ScriptObjects provide a GetCachedPtr method which returns an IntPtr which points to the script interop object described in previous sections.
+
+## Assembly refresh ##
+What has been shown so far is enough to create a class exposed to script, however object of such a class will not survive assembly refresh. Assembly refresh happens when scripts are recompiled and managed assemblies are unloaded and reloaded. This is something that generally happens only in the editor.
+
+If you don't care about your object surving the refresh, you do not need to implement what is described here. 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.
+
+A persistent script object need to inherit a variation of ScriptObject like so:
+	class MyScriptObject : public ScriptObject<MyScriptObject, PersistentScriptObjectBase>
+	
+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.
+ - 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). You can choose to to override this method.
+ - 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 (which is what the default implementation does). If assembly refresh is not in progress this method should delete the ScriptObject normals because it likely got called due to normal reasons (managed object went out of scope).
+ - 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.
+ - ScriptObject::endRefresh() - Called after all assemblies are loaded, and after all script interop objects were either destroyed (non-persistent) or had their managed instances created (persistent). Allows you to restore data stored in beginRefresh(), but that is optional.
+ 
+See ScriptSceneObject and its base class ScriptGameObjectBase for example implementations of these methods.
+
+## Deriving from ScriptObject ##
+Sometimes script objects are polymorphic. For example a GUIElement is derived from ScriptObject in managed code, and GUIButton from GUIElement, however they both have script interop objects of their own.
+
+Due to the nature our script interop objects are defined we cannot follow the same simple chain of inheritance in C++ code. For example class definition script interop object for GUIElement would be:
+	class ScriptGUIElement : public ScriptObject<ScriptGUIElement>
+	{
+	public:
+		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "GUIElement")
+	...
+	}
+	
+But what would it be for GUIButton?	It also needs to implement ScriptObject with its own SCRIPT_OBJ macro so we cannot just inherit from ScriptGUIElement directly as it would clash.
+
+The solution is to create a third class that will serve as a base for both. This third class will be a base class for ScriptObject (it's second template parameter allows us to override its default ScriptObjectBase base class). The third class will need to inherit ScriptObjectBase and can implement any functionality common to all GUI elements (e.g. it might store a pointer to a native GUIElement*).
+
+Then we can define script interop object for GUI element as:
+	class ScriptGUIElement : public ScriptObject<ScriptGUIElement, ScriptGUIElementBase>
+	
+Where ScriptGUIElementBase is our third class. Interop object for GUIButton would then be:
+	class ScriptGUIButton : public ScriptObject<ScriptGUIButton, ScriptGUIElementBase>
+	
+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 ScriptGUIElement and ScriptGUIButton for an example.
 See ScriptGUIElement and ScriptGUIButton for an example.

+ 100 - 99
Source/BansheeEditor/Source/BsGUIVector2Field.cpp

@@ -1,100 +1,101 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsGUIVector2Field.h"
-#include "BsGUILayoutX.h"
-#include "BsGUILayoutY.h"
-#include "BsGUIFloatField.h"
-#include "BsGUILabel.h"
-
-using namespace std::placeholders;
-
-namespace BansheeEngine
-{
-	const UINT32 GUIVector2Field::ELEMENT_LABEL_WIDTH = 10;
-
-	GUIVector2Field::GUIVector2Field(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
-		UINT32 labelWidth, const String& style, const GUIDimensions& dimensions, bool withLabel)
-		:TGUIField(dummy, labelContent, labelWidth, style, dimensions, withLabel),
-		mFieldX(nullptr), mFieldY(nullptr)
-	{
-		mFieldX = GUIFloatField::create(HString(L"X"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
-		mFieldY = GUIFloatField::create(HString(L"Y"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
-
-		mFieldX->onValueChanged.connect(std::bind(&GUIVector2Field::valueChanged, this, _1));
-		mFieldY->onValueChanged.connect(std::bind(&GUIVector2Field::valueChanged, this, _1));
-		mFieldX->onConfirm.connect(std::bind(&GUIVector2Field::inputConfirmed, this));
-		mFieldY->onConfirm.connect(std::bind(&GUIVector2Field::inputConfirmed, this));
-
-		mLayout->removeElement(mLabel);
-
-		GUILayout* layout = mLayout->addNewElement<GUILayoutY>();
-
-		layout->addElement(mLabel);
-		mLabel->resetDimensions();
-
-		GUILayout* elementLayout = layout->addNewElement<GUILayoutX>();
-
-		elementLayout->addElement(mFieldX);
-		elementLayout->addElement(mFieldY);
-	}
-
-	Vector2 GUIVector2Field::getValue() const
-	{
-		Vector2 value;
-		value.x = mFieldX->getValue();
-		value.y = mFieldY->getValue();
-
-		return value;
-	}
-
-	void GUIVector2Field::setValue(const Vector2& value)
-	{
-		mFieldX->setValue(value.x);
-		mFieldY->setValue(value.y);
-	}
-
-	bool GUIVector2Field::hasInputFocus() const
-	{
-		return mFieldX->hasInputFocus() || mFieldY->hasInputFocus();
-	}
-
-	void GUIVector2Field::setTint(const Color& color)
-	{
-		if (mLabel != nullptr)
-			mLabel->setTint(color);
-
-		mFieldX->setTint(color);
-		mFieldY->setTint(color);
-	}
-
-	void GUIVector2Field::valueChanged(float newValue)
-	{
-		onValueChanged(getValue());
-	}
-
-	void GUIVector2Field::inputConfirmed()
-	{
-		onConfirm();
-	}
-
-	void GUIVector2Field::styleUpdated()
-	{
-		if (mLabel != nullptr)
-			mLabel->setStyle(getSubStyleName(getLabelStyleType()));
-
-		mFieldX->setStyle(getSubStyleName(getFloatFieldStyleType()));
-		mFieldY->setStyle(getSubStyleName(getFloatFieldStyleType()));
-	}
-
-	const String& GUIVector2Field::getGUITypeName()
-	{
-		static String typeName = "GUIVector2Field";
-		return typeName;
-	}
-
-	const String& GUIVector2Field::getFloatFieldStyleType()
-	{
-		static String LABEL_STYLE_TYPE = "EditorFloatField";
-		return LABEL_STYLE_TYPE;
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsGUIVector2Field.h"
+#include "BsGUILayoutX.h"
+#include "BsGUILayoutY.h"
+#include "BsGUIFloatField.h"
+#include "BsGUILabel.h"
+
+using namespace std::placeholders;
+
+namespace BansheeEngine
+{
+	const UINT32 GUIVector2Field::ELEMENT_LABEL_WIDTH = 10;
+
+	GUIVector2Field::GUIVector2Field(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
+		UINT32 labelWidth, const String& style, const GUIDimensions& dimensions, bool withLabel)
+		:TGUIField(dummy, labelContent, labelWidth, style, dimensions, withLabel),
+		mFieldX(nullptr), mFieldY(nullptr)
+	{
+		mFieldX = GUIFloatField::create(HString(L"X"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
+		mFieldY = GUIFloatField::create(HString(L"Y"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
+
+		mFieldX->onValueChanged.connect(std::bind(&GUIVector2Field::valueChanged, this, _1));
+		mFieldY->onValueChanged.connect(std::bind(&GUIVector2Field::valueChanged, this, _1));
+		mFieldX->onConfirm.connect(std::bind(&GUIVector2Field::inputConfirmed, this));
+		mFieldY->onConfirm.connect(std::bind(&GUIVector2Field::inputConfirmed, this));
+
+		mLayout->removeElement(mLabel);
+
+		GUILayout* layout = mLayout->addNewElement<GUILayoutY>();
+
+		layout->addElement(mLabel);
+		mLabel->resetDimensions();
+
+		GUILayout* elementLayout = layout->addNewElement<GUILayoutX>();
+
+		elementLayout->addElement(mFieldX);
+		elementLayout->addElement(mFieldY);
+	}
+
+	Vector2 GUIVector2Field::getValue() const
+	{
+		Vector2 value;
+		value.x = mFieldX->getValue();
+		value.y = mFieldY->getValue();
+
+		return value;
+	}
+
+	void GUIVector2Field::setValue(const Vector2& value)
+	{
+		mFieldX->setValue(value.x);
+		mFieldY->setValue(value.y);
+	}
+
+	bool GUIVector2Field::hasInputFocus() const
+	{
+		return mFieldX->hasInputFocus() || mFieldY->hasInputFocus();
+	}
+
+	void GUIVector2Field::setTint(const Color& color)
+	{
+		if (mLabel != nullptr)
+			mLabel->setTint(color);
+
+		mFieldX->setTint(color);
+		mFieldY->setTint(color);
+	}
+
+	void GUIVector2Field::valueChanged(float newValue)
+	{
+		Vector2 value = getValue();
+		onValueChanged(value);
+	}
+
+	void GUIVector2Field::inputConfirmed()
+	{
+		onConfirm();
+	}
+
+	void GUIVector2Field::styleUpdated()
+	{
+		if (mLabel != nullptr)
+			mLabel->setStyle(getSubStyleName(getLabelStyleType()));
+
+		mFieldX->setStyle(getSubStyleName(getFloatFieldStyleType()));
+		mFieldY->setStyle(getSubStyleName(getFloatFieldStyleType()));
+	}
+
+	const String& GUIVector2Field::getGUITypeName()
+	{
+		static String typeName = "GUIVector2Field";
+		return typeName;
+	}
+
+	const String& GUIVector2Field::getFloatFieldStyleType()
+	{
+		static String LABEL_STYLE_TYPE = "EditorFloatField";
+		return LABEL_STYLE_TYPE;
+	}
 }
 }

+ 108 - 107
Source/BansheeEditor/Source/BsGUIVector3Field.cpp

@@ -1,108 +1,109 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsGUIVector3Field.h"
-#include "BsGUILayoutX.h"
-#include "BsGUILayoutY.h"
-#include "BsGUIFloatField.h"
-#include "BsGUILabel.h"
-
-using namespace std::placeholders;
-
-namespace BansheeEngine
-{
-	const UINT32 GUIVector3Field::ELEMENT_LABEL_WIDTH = 10;
-
-	GUIVector3Field::GUIVector3Field(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
-		UINT32 labelWidth, const String& style, const GUIDimensions& dimensions, bool withLabel)
-		:TGUIField(dummy, labelContent, labelWidth, style, dimensions, withLabel),
-		mFieldX(nullptr), mFieldY(nullptr), mFieldZ(nullptr)
-	{
-		mFieldX = GUIFloatField::create(HString(L"X"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
-		mFieldY = GUIFloatField::create(HString(L"Y"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
-		mFieldZ = GUIFloatField::create(HString(L"Z"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
-
-		mFieldX->onValueChanged.connect(std::bind(&GUIVector3Field::valueChanged, this, _1));
-		mFieldY->onValueChanged.connect(std::bind(&GUIVector3Field::valueChanged, this, _1));
-		mFieldZ->onValueChanged.connect(std::bind(&GUIVector3Field::valueChanged, this, _1));
-
-		mFieldX->onConfirm.connect(std::bind(&GUIVector3Field::inputConfirmed, this));
-		mFieldY->onConfirm.connect(std::bind(&GUIVector3Field::inputConfirmed, this));
-		mFieldZ->onConfirm.connect(std::bind(&GUIVector3Field::inputConfirmed, this));
-
-		mLayout->removeElement(mLabel);
-
-		GUILayout* layout = mLayout->addNewElement<GUILayoutY>();
-		layout->addElement(mLabel);
-		mLabel->resetDimensions();
-
-		GUILayout* elementLayout = layout->addNewElement<GUILayoutX>();
-
-		elementLayout->addElement(mFieldX);
-		elementLayout->addElement(mFieldY);
-		elementLayout->addElement(mFieldZ);
-	}
-
-	Vector3 GUIVector3Field::getValue() const
-	{
-		Vector3 value;
-		value.x = mFieldX->getValue();
-		value.y = mFieldY->getValue();
-		value.z = mFieldZ->getValue();
-
-		return value;
-	}
-
-	void GUIVector3Field::setValue(const Vector3& value)
-	{
-		mFieldX->setValue(value.x);
-		mFieldY->setValue(value.y);
-		mFieldZ->setValue(value.z);
-	}
-
-	bool GUIVector3Field::hasInputFocus() const
-	{
-		return mFieldX->hasInputFocus() || mFieldY->hasInputFocus() || mFieldZ->hasInputFocus();
-	}
-
-	void GUIVector3Field::setTint(const Color& color)
-	{
-		if (mLabel != nullptr)
-			mLabel->setTint(color);
-
-		mFieldX->setTint(color);
-		mFieldY->setTint(color);
-		mFieldZ->setTint(color);
-	}
-
-	void GUIVector3Field::styleUpdated()
-	{
-		if (mLabel != nullptr)
-			mLabel->setStyle(getSubStyleName(getLabelStyleType()));
-
-		mFieldX->setStyle(getSubStyleName(getFloatFieldStyleType()));
-		mFieldY->setStyle(getSubStyleName(getFloatFieldStyleType()));
-		mFieldZ->setStyle(getSubStyleName(getFloatFieldStyleType()));
-	}
-
-	void GUIVector3Field::valueChanged(float newValue)
-	{
-		onValueChanged(getValue());
-	}
-
-	void GUIVector3Field::inputConfirmed()
-	{
-		onConfirm();
-	}
-
-	const String& GUIVector3Field::getGUITypeName()
-	{
-		static String typeName = "GUIVector3Field";
-		return typeName;
-	}
-
-	const String& GUIVector3Field::getFloatFieldStyleType()
-	{
-		static String LABEL_STYLE_TYPE = "EditorFloatField";
-		return LABEL_STYLE_TYPE;
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsGUIVector3Field.h"
+#include "BsGUILayoutX.h"
+#include "BsGUILayoutY.h"
+#include "BsGUIFloatField.h"
+#include "BsGUILabel.h"
+
+using namespace std::placeholders;
+
+namespace BansheeEngine
+{
+	const UINT32 GUIVector3Field::ELEMENT_LABEL_WIDTH = 10;
+
+	GUIVector3Field::GUIVector3Field(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
+		UINT32 labelWidth, const String& style, const GUIDimensions& dimensions, bool withLabel)
+		:TGUIField(dummy, labelContent, labelWidth, style, dimensions, withLabel),
+		mFieldX(nullptr), mFieldY(nullptr), mFieldZ(nullptr)
+	{
+		mFieldX = GUIFloatField::create(HString(L"X"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
+		mFieldY = GUIFloatField::create(HString(L"Y"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
+		mFieldZ = GUIFloatField::create(HString(L"Z"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
+
+		mFieldX->onValueChanged.connect(std::bind(&GUIVector3Field::valueChanged, this, _1));
+		mFieldY->onValueChanged.connect(std::bind(&GUIVector3Field::valueChanged, this, _1));
+		mFieldZ->onValueChanged.connect(std::bind(&GUIVector3Field::valueChanged, this, _1));
+
+		mFieldX->onConfirm.connect(std::bind(&GUIVector3Field::inputConfirmed, this));
+		mFieldY->onConfirm.connect(std::bind(&GUIVector3Field::inputConfirmed, this));
+		mFieldZ->onConfirm.connect(std::bind(&GUIVector3Field::inputConfirmed, this));
+
+		mLayout->removeElement(mLabel);
+
+		GUILayout* layout = mLayout->addNewElement<GUILayoutY>();
+		layout->addElement(mLabel);
+		mLabel->resetDimensions();
+
+		GUILayout* elementLayout = layout->addNewElement<GUILayoutX>();
+
+		elementLayout->addElement(mFieldX);
+		elementLayout->addElement(mFieldY);
+		elementLayout->addElement(mFieldZ);
+	}
+
+	Vector3 GUIVector3Field::getValue() const
+	{
+		Vector3 value;
+		value.x = mFieldX->getValue();
+		value.y = mFieldY->getValue();
+		value.z = mFieldZ->getValue();
+
+		return value;
+	}
+
+	void GUIVector3Field::setValue(const Vector3& value)
+	{
+		mFieldX->setValue(value.x);
+		mFieldY->setValue(value.y);
+		mFieldZ->setValue(value.z);
+	}
+
+	bool GUIVector3Field::hasInputFocus() const
+	{
+		return mFieldX->hasInputFocus() || mFieldY->hasInputFocus() || mFieldZ->hasInputFocus();
+	}
+
+	void GUIVector3Field::setTint(const Color& color)
+	{
+		if (mLabel != nullptr)
+			mLabel->setTint(color);
+
+		mFieldX->setTint(color);
+		mFieldY->setTint(color);
+		mFieldZ->setTint(color);
+	}
+
+	void GUIVector3Field::styleUpdated()
+	{
+		if (mLabel != nullptr)
+			mLabel->setStyle(getSubStyleName(getLabelStyleType()));
+
+		mFieldX->setStyle(getSubStyleName(getFloatFieldStyleType()));
+		mFieldY->setStyle(getSubStyleName(getFloatFieldStyleType()));
+		mFieldZ->setStyle(getSubStyleName(getFloatFieldStyleType()));
+	}
+
+	void GUIVector3Field::valueChanged(float newValue)
+	{
+		Vector3 value = getValue();
+		onValueChanged(value);
+	}
+
+	void GUIVector3Field::inputConfirmed()
+	{
+		onConfirm();
+	}
+
+	const String& GUIVector3Field::getGUITypeName()
+	{
+		static String typeName = "GUIVector3Field";
+		return typeName;
+	}
+
+	const String& GUIVector3Field::getFloatFieldStyleType()
+	{
+		static String LABEL_STYLE_TYPE = "EditorFloatField";
+		return LABEL_STYLE_TYPE;
+	}
 }
 }

+ 115 - 114
Source/BansheeEditor/Source/BsGUIVector4Field.cpp

@@ -1,115 +1,116 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsGUIVector4Field.h"
-#include "BsGUILayoutX.h"
-#include "BsGUILayoutY.h"
-#include "BsGUIFloatField.h"
-#include "BsGUILabel.h"
-
-using namespace std::placeholders;
-
-namespace BansheeEngine
-{
-	const UINT32 GUIVector4Field::ELEMENT_LABEL_WIDTH = 10;
-
-	GUIVector4Field::GUIVector4Field(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
-		UINT32 labelWidth, const String& style, const GUIDimensions& dimensions, bool withLabel)
-		:TGUIField(dummy, labelContent, labelWidth, style, dimensions, withLabel), mFieldX(nullptr), mFieldY(nullptr)
-	{
-		mFieldX = GUIFloatField::create(HString(L"X"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
-		mFieldY = GUIFloatField::create(HString(L"Y"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
-		mFieldZ = GUIFloatField::create(HString(L"Z"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
-		mFieldW = GUIFloatField::create(HString(L"W"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
-
-		mFieldX->onValueChanged.connect(std::bind(&GUIVector4Field::valueChanged, this, _1));
-		mFieldY->onValueChanged.connect(std::bind(&GUIVector4Field::valueChanged, this, _1));
-		mFieldZ->onValueChanged.connect(std::bind(&GUIVector4Field::valueChanged, this, _1));
-		mFieldW->onValueChanged.connect(std::bind(&GUIVector4Field::valueChanged, this, _1));
-
-		mFieldX->onConfirm.connect(std::bind(&GUIVector4Field::inputConfirmed, this));
-		mFieldY->onConfirm.connect(std::bind(&GUIVector4Field::inputConfirmed, this));
-		mFieldZ->onConfirm.connect(std::bind(&GUIVector4Field::inputConfirmed, this));
-		mFieldW->onConfirm.connect(std::bind(&GUIVector4Field::inputConfirmed, this));
-
-		mLayout->removeElement(mLabel);
-
-		GUILayout* layout = mLayout->addNewElement<GUILayoutY>();
-		layout->addElement(mLabel);
-		mLabel->resetDimensions();
-
-		GUILayout* elementLayout = layout->addNewElement<GUILayoutX>();
-
-		elementLayout->addElement(mFieldX);
-		elementLayout->addElement(mFieldY);
-		elementLayout->addElement(mFieldZ);
-		elementLayout->addElement(mFieldW);
-	}
-
-	Vector4 GUIVector4Field::getValue() const
-	{
-		Vector4 value;
-		value.x = mFieldX->getValue();
-		value.y = mFieldY->getValue();
-		value.z = mFieldZ->getValue();
-		value.w = mFieldW->getValue();
-
-		return value;
-	}
-
-	void GUIVector4Field::setValue(const Vector4& value)
-	{
-		mFieldX->setValue(value.x);
-		mFieldY->setValue(value.y);
-		mFieldZ->setValue(value.z);
-		mFieldW->setValue(value.w);
-	}
-
-	bool GUIVector4Field::hasInputFocus() const
-	{
-		return mFieldX->hasInputFocus() || mFieldY->hasInputFocus() || mFieldZ->hasInputFocus() || mFieldW->hasInputFocus();
-	}
-
-	void GUIVector4Field::setTint(const Color& color)
-	{
-		if (mLabel != nullptr)
-			mLabel->setTint(color);
-
-		mFieldX->setTint(color);
-		mFieldY->setTint(color);
-		mFieldZ->setTint(color);
-		mFieldW->setTint(color);
-	}
-
-	void GUIVector4Field::styleUpdated()
-	{
-		if (mLabel != nullptr)
-			mLabel->setStyle(getSubStyleName(getLabelStyleType()));
-
-		mFieldX->setStyle(getSubStyleName(getFloatFieldStyleType()));
-		mFieldY->setStyle(getSubStyleName(getFloatFieldStyleType()));
-		mFieldZ->setStyle(getSubStyleName(getFloatFieldStyleType()));
-		mFieldW->setStyle(getSubStyleName(getFloatFieldStyleType()));
-	}
-
-	void GUIVector4Field::valueChanged(float newValue)
-	{
-		onValueChanged(getValue());
-	}
-
-	void GUIVector4Field::inputConfirmed()
-	{
-		onConfirm();
-	}
-
-	const String& GUIVector4Field::getGUITypeName()
-	{
-		static String typeName = "GUIVector4Field";
-		return typeName;
-	}
-
-	const String& GUIVector4Field::getFloatFieldStyleType()
-	{
-		static String LABEL_STYLE_TYPE = "EditorFloatField";
-		return LABEL_STYLE_TYPE;
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsGUIVector4Field.h"
+#include "BsGUILayoutX.h"
+#include "BsGUILayoutY.h"
+#include "BsGUIFloatField.h"
+#include "BsGUILabel.h"
+
+using namespace std::placeholders;
+
+namespace BansheeEngine
+{
+	const UINT32 GUIVector4Field::ELEMENT_LABEL_WIDTH = 10;
+
+	GUIVector4Field::GUIVector4Field(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
+		UINT32 labelWidth, const String& style, const GUIDimensions& dimensions, bool withLabel)
+		:TGUIField(dummy, labelContent, labelWidth, style, dimensions, withLabel), mFieldX(nullptr), mFieldY(nullptr)
+	{
+		mFieldX = GUIFloatField::create(HString(L"X"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
+		mFieldY = GUIFloatField::create(HString(L"Y"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
+		mFieldZ = GUIFloatField::create(HString(L"Z"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
+		mFieldW = GUIFloatField::create(HString(L"W"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
+
+		mFieldX->onValueChanged.connect(std::bind(&GUIVector4Field::valueChanged, this, _1));
+		mFieldY->onValueChanged.connect(std::bind(&GUIVector4Field::valueChanged, this, _1));
+		mFieldZ->onValueChanged.connect(std::bind(&GUIVector4Field::valueChanged, this, _1));
+		mFieldW->onValueChanged.connect(std::bind(&GUIVector4Field::valueChanged, this, _1));
+
+		mFieldX->onConfirm.connect(std::bind(&GUIVector4Field::inputConfirmed, this));
+		mFieldY->onConfirm.connect(std::bind(&GUIVector4Field::inputConfirmed, this));
+		mFieldZ->onConfirm.connect(std::bind(&GUIVector4Field::inputConfirmed, this));
+		mFieldW->onConfirm.connect(std::bind(&GUIVector4Field::inputConfirmed, this));
+
+		mLayout->removeElement(mLabel);
+
+		GUILayout* layout = mLayout->addNewElement<GUILayoutY>();
+		layout->addElement(mLabel);
+		mLabel->resetDimensions();
+
+		GUILayout* elementLayout = layout->addNewElement<GUILayoutX>();
+
+		elementLayout->addElement(mFieldX);
+		elementLayout->addElement(mFieldY);
+		elementLayout->addElement(mFieldZ);
+		elementLayout->addElement(mFieldW);
+	}
+
+	Vector4 GUIVector4Field::getValue() const
+	{
+		Vector4 value;
+		value.x = mFieldX->getValue();
+		value.y = mFieldY->getValue();
+		value.z = mFieldZ->getValue();
+		value.w = mFieldW->getValue();
+
+		return value;
+	}
+
+	void GUIVector4Field::setValue(const Vector4& value)
+	{
+		mFieldX->setValue(value.x);
+		mFieldY->setValue(value.y);
+		mFieldZ->setValue(value.z);
+		mFieldW->setValue(value.w);
+	}
+
+	bool GUIVector4Field::hasInputFocus() const
+	{
+		return mFieldX->hasInputFocus() || mFieldY->hasInputFocus() || mFieldZ->hasInputFocus() || mFieldW->hasInputFocus();
+	}
+
+	void GUIVector4Field::setTint(const Color& color)
+	{
+		if (mLabel != nullptr)
+			mLabel->setTint(color);
+
+		mFieldX->setTint(color);
+		mFieldY->setTint(color);
+		mFieldZ->setTint(color);
+		mFieldW->setTint(color);
+	}
+
+	void GUIVector4Field::styleUpdated()
+	{
+		if (mLabel != nullptr)
+			mLabel->setStyle(getSubStyleName(getLabelStyleType()));
+
+		mFieldX->setStyle(getSubStyleName(getFloatFieldStyleType()));
+		mFieldY->setStyle(getSubStyleName(getFloatFieldStyleType()));
+		mFieldZ->setStyle(getSubStyleName(getFloatFieldStyleType()));
+		mFieldW->setStyle(getSubStyleName(getFloatFieldStyleType()));
+	}
+
+	void GUIVector4Field::valueChanged(float newValue)
+	{
+		Vector4 value = getValue();
+		onValueChanged(value);
+	}
+
+	void GUIVector4Field::inputConfirmed()
+	{
+		onConfirm();
+	}
+
+	const String& GUIVector4Field::getGUITypeName()
+	{
+		static String typeName = "GUIVector4Field";
+		return typeName;
+	}
+
+	const String& GUIVector4Field::getFloatFieldStyleType()
+	{
+		static String LABEL_STYLE_TYPE = "EditorFloatField";
+		return LABEL_STYLE_TYPE;
+	}
 }
 }

+ 104 - 103
Source/BansheeMono/Include/BsMonoManager.h

@@ -1,104 +1,105 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsMonoPrerequisites.h"
-#include "BsScriptMeta.h"
-#include "BsModule.h"
-#include <mono/jit/jit.h>
-
-namespace BansheeEngine
-{
-	/** @addtogroup Mono
-	 *  @{
-	 */
-
-	/**	Available Mono versions. */
-	enum class MonoVersion
-	{
-		v4_0,
-		v4_5
-	};
-
-	/**	Loads Mono script assemblies and manages script objects. */
-	class BS_MONO_EXPORT MonoManager : public Module<MonoManager>
-	{
-	public:
-		MonoManager();
-		~MonoManager();
-
-		/**
-		 * Loads a new assembly from the provided path.
-		 *
-		 * @param[in]	path	Absolute path to the assembly .dll.
-		 * @param[in]	name	Unique name for the assembly.
-		 */
-		MonoAssembly& loadAssembly(const String& path, const String& name);
-
-		/**	Searches all loaded assemblies for the specified class. */
-		MonoClass* findClass(const String& ns, const String& typeName);
-
-		/**	Searches all loaded assemblies for the specified class. */
-		MonoClass* findClass(::MonoClass* rawMonoClass);
-
-		/**	Returns the current Mono domains. */
-		MonoDomain* getDomain() const { return mScriptDomain; }
-
-		/**
-		 * Attempts to find a previously loaded assembly with the specified name. Returns null if assembly cannot be found.
-		 */
-		MonoAssembly* getAssembly(const String& name) const;
-
-		/**
-		 * Unloads the active domain all script assemblies are loaded in and destroys any managed objects associated with it.
-		 */
-		void unloadScriptDomain();
-
-		/**
-		 * Loads a new script domain. If another domain already exists it will be unloaded. This will also restore any
-		 * previously loaded assemblies.
-		 */
-		void loadScriptDomain();
-
-		/**
-		 * Returns the path of the folder where Mono framework assemblies are located. Path is relative to the application
-		 * executable.
-		 */
-		Path getFrameworkAssembliesFolder() const;
-
-		/**
-		 * Returns the path to the Mono /etc folder that is required for initializing Mono. Path is relative to the
-		 * application executable.
-		 */
-		Path getMonoEtcFolder() const;
-
-		/**	Returns the absolute path to the Mono compiler. */
-		Path getCompilerPath() const;
-
-		/**
-		 * Registers a new script type. This should be done before any assembly loading is done. Upon assembly load these
-		 * script types will be initialized with necessary information about their managed counterparts.
-		 */
-		static void registerScriptType(ScriptMeta* metaData);
-
-		/** Triggered when the assembly domain and all relevant assemblies are about to be unloaded. */
-		Event<void()> onDomainUnload;
-	private:
-		/**	Initializes a previous loaded assembly. */
-		void initializeAssembly(MonoAssembly& assembly);
-
-		/**	Returns a list of all types that will be initializes with their assembly gets loaded. */
-		static UnorderedMap<String, Vector<ScriptMeta*>>& getScriptMetaData()
-		{
-			static UnorderedMap<String, Vector<ScriptMeta*>> mTypesToInitialize;
-			return mTypesToInitialize;
-		}
-
-		UnorderedMap<String, MonoAssembly*> mAssemblies;
-		MonoDomain* mScriptDomain;
-		MonoDomain* mRootDomain;
-		bool mIsCoreLoaded;
-	};
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsMonoPrerequisites.h"
+#include "BsScriptMeta.h"
+#include "BsModule.h"
+#include <mono/jit/jit.h>
+
+namespace BansheeEngine
+{
+	/** @addtogroup Mono
+	 *  @{
+	 */
+
+	/**	Available Mono versions. */
+	enum class MonoVersion
+	{
+		v4_0,
+		v4_5
+	};
+
+	/**	Loads Mono script assemblies and manages script objects. */
+	class BS_MONO_EXPORT MonoManager : public Module<MonoManager>
+	{
+	public:
+		MonoManager();
+		~MonoManager();
+
+		/**
+		 * Loads a new assembly from the provided path.
+		 *
+		 * @param[in]	path	Absolute path to the assembly .dll.
+		 * @param[in]	name	Unique name for the assembly.
+		 */
+		MonoAssembly& loadAssembly(const String& path, const String& name);
+
+		/**	Searches all loaded assemblies for the specified class. */
+		MonoClass* findClass(const String& ns, const String& typeName);
+
+		/**	Searches all loaded assemblies for the specified class. */
+		MonoClass* findClass(::MonoClass* rawMonoClass);
+
+		/**	Returns the current Mono domain. */
+		MonoDomain* getDomain() const { return mScriptDomain; }
+
+		/**
+		 * Attempts to find a previously loaded assembly with the specified name. Returns null if assembly cannot be found.
+		 */
+		MonoAssembly* getAssembly(const String& name) const;
+
+		/**
+		 * Unloads the active domain (in which all script assemblies are loaded) and destroys any managed objects
+		 * associated with it.
+		 */
+		void unloadScriptDomain();
+
+		/**
+		 * Loads a new script domain. If another domain already exists it will be unloaded. This will also restore any
+		 * previously loaded assemblies.
+		 */
+		void loadScriptDomain();
+
+		/**
+		 * Returns the path of the folder where Mono framework assemblies are located. Path is relative to the application
+		 * executable.
+		 */
+		Path getFrameworkAssembliesFolder() const;
+
+		/**
+		 * Returns the path to the Mono /etc folder that is required for initializing Mono. Path is relative to the
+		 * application executable.
+		 */
+		Path getMonoEtcFolder() const;
+
+		/**	Returns the absolute path to the Mono compiler. */
+		Path getCompilerPath() const;
+
+		/**
+		 * Registers a new script type. This should be done before any assembly loading is done. Upon assembly load these
+		 * script types will be initialized with necessary information about their managed counterparts.
+		 */
+		static void registerScriptType(ScriptMeta* metaData);
+
+		/** Triggered when the assembly domain and all relevant assemblies are about to be unloaded. */
+		Event<void()> onDomainUnload;
+	private:
+		/**	Initializes a previous loaded assembly. */
+		void initializeAssembly(MonoAssembly& assembly);
+
+		/**	Returns a list of all types that will be initializes with their assembly gets loaded. */
+		static UnorderedMap<String, Vector<ScriptMeta*>>& getScriptMetaData()
+		{
+			static UnorderedMap<String, Vector<ScriptMeta*>> mTypesToInitialize;
+			return mTypesToInitialize;
+		}
+
+		UnorderedMap<String, MonoAssembly*> mAssemblies;
+		MonoDomain* mScriptDomain;
+		MonoDomain* mRootDomain;
+		bool mIsCoreLoaded;
+	};
+
+	/** @} */
 }
 }

+ 71 - 68
Source/MBansheeEditor/Inspectors/BoxColliderInspector.cs

@@ -1,69 +1,72 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    /// <summary>
-    /// Renders an inspector for the <see cref="BoxCollider"/> component.
-    /// </summary>
-    [CustomInspector(typeof(BoxCollider))]
-    public class BoxColliderInspector : ColliderInspector
-    {
-        private GUIVector3Field centerField = new GUIVector3Field(new LocEdString("Center"));
-        private GUIVector3Field extentsField = new GUIVector3Field(new LocEdString("Extents"));
-
-        /// <inheritdoc/>
-        protected internal override void Initialize()
-        {
-            BoxCollider collider = InspectedObject as BoxCollider;
-
-            if(collider != null)
-                BuildGUI(collider);
-        }
-
-        /// <inheritdoc/>
-        protected internal override InspectableState Refresh()
-        {
-            BoxCollider collider = InspectedObject as BoxCollider;
-            if (collider == null)
-                return InspectableState.NotModified;
-
-            Refresh(collider);
-
-            InspectableState oldState = modifyState;
-            if (modifyState.HasFlag(InspectableState.Modified))
-                modifyState = InspectableState.NotModified;
-
-            return oldState;
-        }
-
-        /// <summary>
-        /// Creates GUI elements for fields specific to the box collider.
-        /// </summary>
-        protected void BuildGUI(BoxCollider collider)
-        {
-            centerField.OnChanged += x => { collider.Center = x; MarkAsModified(); };
-            centerField.OnFocusLost += ConfirmModify;
-            centerField.OnConfirmed += ConfirmModify;
-
-            extentsField.OnChanged += x => { collider.Extents = x; MarkAsModified(); };
-            extentsField.OnFocusLost += ConfirmModify;
-            extentsField.OnConfirmed += ConfirmModify;
-
-            base.BuildGUI(collider);
-        }
-
-        /// <summary>
-        /// Updates all GUI elements from current values in the collider.
-        /// </summary>
-        /// <param name="collider">Collider to update the GUI from.</param>
-        protected void Refresh(BoxCollider collider)
-        {
-            centerField.Value = collider.Center;
-            extentsField.Value = collider.Extents;
-
-            base.Refresh(collider);
-        }
-    }
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Renders an inspector for the <see cref="BoxCollider"/> component.
+    /// </summary>
+    [CustomInspector(typeof(BoxCollider))]
+    public class BoxColliderInspector : ColliderInspector
+    {
+        private GUIVector3Field centerField = new GUIVector3Field(new LocEdString("Center"));
+        private GUIVector3Field extentsField = new GUIVector3Field(new LocEdString("Extents"));
+
+        /// <inheritdoc/>
+        protected internal override void Initialize()
+        {
+            BoxCollider collider = InspectedObject as BoxCollider;
+
+            if(collider != null)
+                BuildGUI(collider);
+        }
+
+        /// <inheritdoc/>
+        protected internal override InspectableState Refresh()
+        {
+            BoxCollider collider = InspectedObject as BoxCollider;
+            if (collider == null)
+                return InspectableState.NotModified;
+
+            Refresh(collider);
+
+            InspectableState oldState = modifyState;
+            if (modifyState.HasFlag(InspectableState.Modified))
+                modifyState = InspectableState.NotModified;
+
+            return oldState;
+        }
+
+        /// <summary>
+        /// Creates GUI elements for fields specific to the box collider.
+        /// </summary>
+        protected void BuildGUI(BoxCollider collider)
+        {
+            centerField.OnChanged += x => { collider.Center = x; MarkAsModified(); };
+            centerField.OnFocusLost += ConfirmModify;
+            centerField.OnConfirmed += ConfirmModify;
+
+            extentsField.OnChanged += x => { collider.Extents = x; MarkAsModified(); };
+            extentsField.OnFocusLost += ConfirmModify;
+            extentsField.OnConfirmed += ConfirmModify;
+
+            Layout.AddElement(centerField);
+            Layout.AddElement(extentsField);
+
+            base.BuildGUI(collider);
+        }
+
+        /// <summary>
+        /// Updates all GUI elements from current values in the collider.
+        /// </summary>
+        /// <param name="collider">Collider to update the GUI from.</param>
+        protected void Refresh(BoxCollider collider)
+        {
+            centerField.Value = collider.Center;
+            extentsField.Value = collider.Extents;
+
+            base.Refresh(collider);
+        }
+    }
 }
 }

+ 85 - 80
Source/MBansheeEditor/Inspectors/CapsuleColliderInspector.cs

@@ -1,81 +1,86 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    /// <summary>
-    /// Renders an inspector for the <see cref="CapsuleCollider"/> component.
-    /// </summary>
-    [CustomInspector(typeof(CapsuleCollider))]
-    public class CapsuleColliderInspector : ColliderInspector
-    {
-        private GUIVector3Field centerField = new GUIVector3Field(new LocEdString("Center"));
-        private GUIVector3Field normalField = new GUIVector3Field(new LocEdString("Normal"));
-        private GUIFloatField radiusField = new GUIFloatField(new LocEdString("Radius"));
-        private GUIFloatField halfHeightField = new GUIFloatField(new LocEdString("Half height"));
-
-        /// <inheritdoc/>
-        protected internal override void Initialize()
-        {
-            CapsuleCollider collider = InspectedObject as CapsuleCollider;
-
-            if (collider != null)
-                BuildGUI(collider);
-        }
-
-        /// <inheritdoc/>
-        protected internal override InspectableState Refresh()
-        {
-            CapsuleCollider collider = InspectedObject as CapsuleCollider;
-            if (collider == null)
-                return InspectableState.NotModified;
-
-            Refresh(collider);
-
-            InspectableState oldState = modifyState;
-            if (modifyState.HasFlag(InspectableState.Modified))
-                modifyState = InspectableState.NotModified;
-
-            return oldState;
-        }
-
-        /// <summary>
-        /// Creates GUI elements for fields specific to the capsule collider.
-        /// </summary>
-        protected void BuildGUI(CapsuleCollider collider)
-        {
-            centerField.OnChanged += x => { collider.Center = x; MarkAsModified(); };
-            centerField.OnFocusLost += ConfirmModify;
-            centerField.OnConfirmed += ConfirmModify;
-
-            normalField.OnChanged += x => { collider.Normal = x; MarkAsModified(); };
-            normalField.OnFocusLost += ConfirmModify;
-            normalField.OnConfirmed += ConfirmModify;
-
-            radiusField.OnChanged += x => { collider.Radius = x; MarkAsModified(); };
-            radiusField.OnFocusLost += ConfirmModify;
-            radiusField.OnConfirmed += ConfirmModify;
-
-            halfHeightField.OnChanged += x => { collider.HalfHeight = x; MarkAsModified(); };
-            halfHeightField.OnFocusLost += ConfirmModify;
-            halfHeightField.OnConfirmed += ConfirmModify;
-
-            base.BuildGUI(collider);
-        }
-
-        /// <summary>
-        /// Updates all GUI elements from current values in the collider.
-        /// </summary>
-        /// <param name="collider">Collider to update the GUI from.</param>
-        protected void Refresh(CapsuleCollider collider)
-        {
-            centerField.Value = collider.Center;
-            normalField.Value = collider.Normal;
-            radiusField.Value = collider.Radius;
-            halfHeightField.Value = collider.HalfHeight;
-
-            base.Refresh(collider);
-        }
-    }
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Renders an inspector for the <see cref="CapsuleCollider"/> component.
+    /// </summary>
+    [CustomInspector(typeof(CapsuleCollider))]
+    public class CapsuleColliderInspector : ColliderInspector
+    {
+        private GUIVector3Field centerField = new GUIVector3Field(new LocEdString("Center"));
+        private GUIVector3Field normalField = new GUIVector3Field(new LocEdString("Normal"));
+        private GUIFloatField radiusField = new GUIFloatField(new LocEdString("Radius"));
+        private GUIFloatField halfHeightField = new GUIFloatField(new LocEdString("Half height"));
+
+        /// <inheritdoc/>
+        protected internal override void Initialize()
+        {
+            CapsuleCollider collider = InspectedObject as CapsuleCollider;
+
+            if (collider != null)
+                BuildGUI(collider);
+        }
+
+        /// <inheritdoc/>
+        protected internal override InspectableState Refresh()
+        {
+            CapsuleCollider collider = InspectedObject as CapsuleCollider;
+            if (collider == null)
+                return InspectableState.NotModified;
+
+            Refresh(collider);
+
+            InspectableState oldState = modifyState;
+            if (modifyState.HasFlag(InspectableState.Modified))
+                modifyState = InspectableState.NotModified;
+
+            return oldState;
+        }
+
+        /// <summary>
+        /// Creates GUI elements for fields specific to the capsule collider.
+        /// </summary>
+        protected void BuildGUI(CapsuleCollider collider)
+        {
+            centerField.OnChanged += x => { collider.Center = x; MarkAsModified(); };
+            centerField.OnFocusLost += ConfirmModify;
+            centerField.OnConfirmed += ConfirmModify;
+
+            normalField.OnChanged += x => { collider.Normal = x; MarkAsModified(); };
+            normalField.OnFocusLost += ConfirmModify;
+            normalField.OnConfirmed += ConfirmModify;
+
+            radiusField.OnChanged += x => { collider.Radius = x; MarkAsModified(); };
+            radiusField.OnFocusLost += ConfirmModify;
+            radiusField.OnConfirmed += ConfirmModify;
+
+            halfHeightField.OnChanged += x => { collider.HalfHeight = x; MarkAsModified(); };
+            halfHeightField.OnFocusLost += ConfirmModify;
+            halfHeightField.OnConfirmed += ConfirmModify;
+
+            Layout.AddElement(centerField);
+            Layout.AddElement(normalField);
+            Layout.AddElement(radiusField);
+            Layout.AddElement(halfHeightField);
+
+            base.BuildGUI(collider);
+        }
+
+        /// <summary>
+        /// Updates all GUI elements from current values in the collider.
+        /// </summary>
+        /// <param name="collider">Collider to update the GUI from.</param>
+        protected void Refresh(CapsuleCollider collider)
+        {
+            centerField.Value = collider.Center;
+            normalField.Value = collider.Normal;
+            radiusField.Value = collider.Radius;
+            halfHeightField.Value = collider.HalfHeight;
+
+            base.Refresh(collider);
+        }
+    }
 }
 }

+ 69 - 67
Source/MBansheeEditor/Inspectors/MeshColliderInspector.cs

@@ -1,68 +1,70 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    /// <summary>
-    /// Renders an inspector for the <see cref="MeshCollider"/> component.
-    /// </summary>
-    [CustomInspector(typeof(MeshCollider))]
-    public class MeshColliderInspector : ColliderInspector
-    {
-        private GUIResourceField meshField = new GUIResourceField(typeof(PhysicsMesh), new LocEdString("Mesh"));
-
-        /// <inheritdoc/>
-        protected internal override void Initialize()
-        {
-            MeshCollider collider = InspectedObject as MeshCollider;
-
-            if (collider != null)
-                BuildGUI(collider);
-        }
-
-        /// <inheritdoc/>
-        protected internal override InspectableState Refresh()
-        {
-            MeshCollider collider = InspectedObject as MeshCollider;
-            if (collider == null)
-                return InspectableState.NotModified;
-
-            Refresh(collider);
-
-            InspectableState oldState = modifyState;
-            if (modifyState.HasFlag(InspectableState.Modified))
-                modifyState = InspectableState.NotModified;
-
-            return oldState;
-        }
-
-        /// <summary>
-        /// Creates GUI elements for fields specific to the mesh collider.
-        /// </summary>
-        protected void BuildGUI(MeshCollider collider)
-        {
-            meshField.OnChanged += x =>
-            {
-                PhysicsMesh mesh = Resources.Load<PhysicsMesh>(x);
-                collider.Mesh = mesh;
-
-                MarkAsModified();
-                ConfirmModify();
-            };
-
-            base.BuildGUI(collider);
-        }
-
-        /// <summary>
-        /// Updates all GUI elements from current values in the collider.
-        /// </summary>
-        /// <param name="collider">Collider to update the GUI from.</param>
-        protected void Refresh(MeshCollider collider)
-        {
-            meshField.Value = collider.Mesh;
-
-            base.Refresh(collider);
-        }
-    }
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Renders an inspector for the <see cref="MeshCollider"/> component.
+    /// </summary>
+    [CustomInspector(typeof(MeshCollider))]
+    public class MeshColliderInspector : ColliderInspector
+    {
+        private GUIResourceField meshField = new GUIResourceField(typeof(PhysicsMesh), new LocEdString("Mesh"));
+
+        /// <inheritdoc/>
+        protected internal override void Initialize()
+        {
+            MeshCollider collider = InspectedObject as MeshCollider;
+
+            if (collider != null)
+                BuildGUI(collider);
+        }
+
+        /// <inheritdoc/>
+        protected internal override InspectableState Refresh()
+        {
+            MeshCollider collider = InspectedObject as MeshCollider;
+            if (collider == null)
+                return InspectableState.NotModified;
+
+            Refresh(collider);
+
+            InspectableState oldState = modifyState;
+            if (modifyState.HasFlag(InspectableState.Modified))
+                modifyState = InspectableState.NotModified;
+
+            return oldState;
+        }
+
+        /// <summary>
+        /// Creates GUI elements for fields specific to the mesh collider.
+        /// </summary>
+        protected void BuildGUI(MeshCollider collider)
+        {
+            meshField.OnChanged += x =>
+            {
+                PhysicsMesh mesh = Resources.Load<PhysicsMesh>(x);
+                collider.Mesh = mesh;
+
+                MarkAsModified();
+                ConfirmModify();
+            };
+
+            Layout.AddElement(meshField);
+
+            base.BuildGUI(collider);
+        }
+
+        /// <summary>
+        /// Updates all GUI elements from current values in the collider.
+        /// </summary>
+        /// <param name="collider">Collider to update the GUI from.</param>
+        protected void Refresh(MeshCollider collider)
+        {
+            meshField.Value = collider.Mesh;
+
+            base.Refresh(collider);
+        }
+    }
 }
 }

+ 71 - 68
Source/MBansheeEditor/Inspectors/PlaneColliderInspector.cs

@@ -1,69 +1,72 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    /// <summary>
-    /// Renders an inspector for the <see cref="PlaneCollider"/> component.
-    /// </summary>
-    [CustomInspector(typeof(PlaneCollider))]
-    public class PlaneColliderInspector : ColliderInspector
-    {
-        private GUIVector3Field normalField = new GUIVector3Field(new LocEdString("Normal"));
-        private GUIFloatField distanceField = new GUIFloatField(new LocEdString("Distance"));
-
-        /// <inheritdoc/>
-        protected internal override void Initialize()
-        {
-            PlaneCollider collider = InspectedObject as PlaneCollider;
-
-            if (collider != null)
-                BuildGUI(collider);
-        }
-
-        /// <inheritdoc/>
-        protected internal override InspectableState Refresh()
-        {
-            PlaneCollider collider = InspectedObject as PlaneCollider;
-            if (collider == null)
-                return InspectableState.NotModified;
-
-            Refresh(collider);
-
-            InspectableState oldState = modifyState;
-            if (modifyState.HasFlag(InspectableState.Modified))
-                modifyState = InspectableState.NotModified;
-
-            return oldState;
-        }
-
-        /// <summary>
-        /// Creates GUI elements for fields specific to the plane collider.
-        /// </summary>
-        protected void BuildGUI(PlaneCollider collider)
-        {
-            normalField.OnChanged += x => { collider.Normal = x; MarkAsModified(); };
-            normalField.OnFocusLost += ConfirmModify;
-            normalField.OnConfirmed += ConfirmModify;
-
-            distanceField.OnChanged += x => { collider.Distance = x; MarkAsModified(); };
-            distanceField.OnFocusLost += ConfirmModify;
-            distanceField.OnConfirmed += ConfirmModify;
-
-            base.BuildGUI(collider);
-        }
-
-        /// <summary>
-        /// Updates all GUI elements from current values in the collider.
-        /// </summary>
-        /// <param name="collider">Collider to update the GUI from.</param>
-        protected void Refresh(PlaneCollider collider)
-        {
-            normalField.Value = collider.Normal;
-            distanceField.Value = collider.Distance;
-
-            base.Refresh(collider);
-        }
-    }
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Renders an inspector for the <see cref="PlaneCollider"/> component.
+    /// </summary>
+    [CustomInspector(typeof(PlaneCollider))]
+    public class PlaneColliderInspector : ColliderInspector
+    {
+        private GUIVector3Field normalField = new GUIVector3Field(new LocEdString("Normal"));
+        private GUIFloatField distanceField = new GUIFloatField(new LocEdString("Distance"));
+
+        /// <inheritdoc/>
+        protected internal override void Initialize()
+        {
+            PlaneCollider collider = InspectedObject as PlaneCollider;
+
+            if (collider != null)
+                BuildGUI(collider);
+        }
+
+        /// <inheritdoc/>
+        protected internal override InspectableState Refresh()
+        {
+            PlaneCollider collider = InspectedObject as PlaneCollider;
+            if (collider == null)
+                return InspectableState.NotModified;
+
+            Refresh(collider);
+
+            InspectableState oldState = modifyState;
+            if (modifyState.HasFlag(InspectableState.Modified))
+                modifyState = InspectableState.NotModified;
+
+            return oldState;
+        }
+
+        /// <summary>
+        /// Creates GUI elements for fields specific to the plane collider.
+        /// </summary>
+        protected void BuildGUI(PlaneCollider collider)
+        {
+            normalField.OnChanged += x => { collider.Normal = x; MarkAsModified(); };
+            normalField.OnFocusLost += ConfirmModify;
+            normalField.OnConfirmed += ConfirmModify;
+
+            distanceField.OnChanged += x => { collider.Distance = x; MarkAsModified(); };
+            distanceField.OnFocusLost += ConfirmModify;
+            distanceField.OnConfirmed += ConfirmModify;
+
+            Layout.AddElement(normalField);
+            Layout.AddElement(distanceField);
+
+            base.BuildGUI(collider);
+        }
+
+        /// <summary>
+        /// Updates all GUI elements from current values in the collider.
+        /// </summary>
+        /// <param name="collider">Collider to update the GUI from.</param>
+        protected void Refresh(PlaneCollider collider)
+        {
+            normalField.Value = collider.Normal;
+            distanceField.Value = collider.Distance;
+
+            base.Refresh(collider);
+        }
+    }
 }
 }

+ 71 - 68
Source/MBansheeEditor/Inspectors/SphereColliderInspector.cs

@@ -1,69 +1,72 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    /// <summary>
-    /// Renders an inspector for the <see cref="SphereCollider"/> component.
-    /// </summary>
-    [CustomInspector(typeof(SphereCollider))]
-    public class SphereColliderInspector : ColliderInspector
-    {
-        private GUIVector3Field centerField = new GUIVector3Field(new LocEdString("Center"));
-        private GUIFloatField radiusField = new GUIFloatField(new LocEdString("Radius"));
-
-        /// <inheritdoc/>
-        protected internal override void Initialize()
-        {
-            SphereCollider collider = InspectedObject as SphereCollider;
-
-            if (collider != null)
-                BuildGUI(collider);
-        }
-
-        /// <inheritdoc/>
-        protected internal override InspectableState Refresh()
-        {
-            SphereCollider collider = InspectedObject as SphereCollider;
-            if (collider == null)
-                return InspectableState.NotModified;
-
-            Refresh(collider);
-
-            InspectableState oldState = modifyState;
-            if (modifyState.HasFlag(InspectableState.Modified))
-                modifyState = InspectableState.NotModified;
-
-            return oldState;
-        }
-
-        /// <summary>
-        /// Creates GUI elements for fields specific to the sphere collider.
-        /// </summary>
-        protected void BuildGUI(SphereCollider collider)
-        {
-            centerField.OnChanged += x => { collider.Center = x; MarkAsModified(); };
-            centerField.OnFocusLost += ConfirmModify;
-            centerField.OnConfirmed += ConfirmModify;
-
-            radiusField.OnChanged += x => { collider.Radius = x; MarkAsModified(); };
-            radiusField.OnFocusLost += ConfirmModify;
-            radiusField.OnConfirmed += ConfirmModify;
-
-            base.BuildGUI(collider);
-        }
-
-        /// <summary>
-        /// Updates all GUI elements from current values in the collider.
-        /// </summary>
-        /// <param name="collider">Collider to update the GUI from.</param>
-        protected void Refresh(SphereCollider collider)
-        {
-            centerField.Value = collider.Center;
-            radiusField.Value = collider.Radius;
-
-            base.Refresh(collider);
-        }
-    }
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Renders an inspector for the <see cref="SphereCollider"/> component.
+    /// </summary>
+    [CustomInspector(typeof(SphereCollider))]
+    public class SphereColliderInspector : ColliderInspector
+    {
+        private GUIVector3Field centerField = new GUIVector3Field(new LocEdString("Center"));
+        private GUIFloatField radiusField = new GUIFloatField(new LocEdString("Radius"));
+
+        /// <inheritdoc/>
+        protected internal override void Initialize()
+        {
+            SphereCollider collider = InspectedObject as SphereCollider;
+
+            if (collider != null)
+                BuildGUI(collider);
+        }
+
+        /// <inheritdoc/>
+        protected internal override InspectableState Refresh()
+        {
+            SphereCollider collider = InspectedObject as SphereCollider;
+            if (collider == null)
+                return InspectableState.NotModified;
+
+            Refresh(collider);
+
+            InspectableState oldState = modifyState;
+            if (modifyState.HasFlag(InspectableState.Modified))
+                modifyState = InspectableState.NotModified;
+
+            return oldState;
+        }
+
+        /// <summary>
+        /// Creates GUI elements for fields specific to the sphere collider.
+        /// </summary>
+        protected void BuildGUI(SphereCollider collider)
+        {
+            centerField.OnChanged += x => { collider.Center = x; MarkAsModified(); };
+            centerField.OnFocusLost += ConfirmModify;
+            centerField.OnConfirmed += ConfirmModify;
+
+            radiusField.OnChanged += x => { collider.Radius = x; MarkAsModified(); };
+            radiusField.OnFocusLost += ConfirmModify;
+            radiusField.OnConfirmed += ConfirmModify;
+
+            Layout.AddElement(centerField);
+            Layout.AddElement(radiusField);
+
+            base.BuildGUI(collider);
+        }
+
+        /// <summary>
+        /// Updates all GUI elements from current values in the collider.
+        /// </summary>
+        /// <param name="collider">Collider to update the GUI from.</param>
+        protected void Refresh(SphereCollider collider)
+        {
+            centerField.Value = collider.Center;
+            radiusField.Value = collider.Radius;
+
+            base.Refresh(collider);
+        }
+    }
 }
 }

+ 52 - 52
Source/SBansheeEditor/Include/BsScriptGUIVector2Field.h

@@ -1,53 +1,53 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsScriptEditorPrerequisites.h"
-#include "BsScriptGUIElement.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Interop class between C++ & CLR for GUIVector2Field.
-	 */
-	class BS_SCR_BED_EXPORT ScriptGUIVector2Field : public TScriptGUIElement<ScriptGUIVector2Field>
-	{
-	public:
-		SCRIPT_OBJ(EDITOR_ASSEMBLY, "BansheeEditor", "GUIVector2Field")
-
-	private:
-		/**
-		 * @brief	Triggered when the value in the native vector field changes.
-		 *
-		 * @param	instance	Managed GUIVector2Field instance.
-		 * @param	newValue	New vector value.
-		 */
-		static void onChanged(MonoObject* instance, Vector2 newValue);
-
-		/**
-		 * @brief	Triggered when the user confirms input in the native vector field.
-		 *
-		 * @param	instance	Managed GUIVector2Field instance.
-		 */
-		static void onConfirmed(MonoObject* instance);
-
-		ScriptGUIVector2Field(MonoObject* instance, GUIVector2Field* vector2Field);
-
-		/************************************************************************/
-		/* 								CLR HOOKS						   		*/
-		/************************************************************************/
-		static void internal_createInstance(MonoObject* instance, MonoObject* title, UINT32 titleWidth,
-			MonoString* style, MonoArray* guiOptions, bool withTitle);
-
-		static void internal_getValue(ScriptGUIVector2Field* nativeInstance, Vector2* output);
-		static void internal_setValue(ScriptGUIVector2Field* nativeInstance, Vector2* value);
-		static void internal_hasInputFocus(ScriptGUIVector2Field* nativeInstance, bool* output);
-		static void internal_setTint(ScriptGUIVector2Field* nativeInstance, Color* color);
-
-		typedef void(__stdcall *OnChangedThunkDef) (MonoObject*, Vector2, MonoException**);
-		typedef void(__stdcall *OnConfirmedThunkDef) (MonoObject*, MonoException**);
-
-		static OnChangedThunkDef onChangedThunk;
-		static OnConfirmedThunkDef onConfirmedThunk;
-	};
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsScriptEditorPrerequisites.h"
+#include "BsScriptGUIElement.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	Interop class between C++ & CLR for GUIVector2Field.
+	 */
+	class BS_SCR_BED_EXPORT ScriptGUIVector2Field : public TScriptGUIElement<ScriptGUIVector2Field>
+	{
+	public:
+		SCRIPT_OBJ(EDITOR_ASSEMBLY, "BansheeEditor", "GUIVector2Field")
+
+	private:
+		/**
+		 * @brief	Triggered when the value in the native vector field changes.
+		 *
+		 * @param	instance	Managed GUIVector2Field instance.
+		 * @param	newValue	New vector value.
+		 */
+		static void onChanged(MonoObject* instance, const Vector2& newValue);
+
+		/**
+		 * @brief	Triggered when the user confirms input in the native vector field.
+		 *
+		 * @param	instance	Managed GUIVector2Field instance.
+		 */
+		static void onConfirmed(MonoObject* instance);
+
+		ScriptGUIVector2Field(MonoObject* instance, GUIVector2Field* vector2Field);
+
+		/************************************************************************/
+		/* 								CLR HOOKS						   		*/
+		/************************************************************************/
+		static void internal_createInstance(MonoObject* instance, MonoObject* title, UINT32 titleWidth,
+			MonoString* style, MonoArray* guiOptions, bool withTitle);
+
+		static void internal_getValue(ScriptGUIVector2Field* nativeInstance, Vector2* output);
+		static void internal_setValue(ScriptGUIVector2Field* nativeInstance, Vector2* value);
+		static void internal_hasInputFocus(ScriptGUIVector2Field* nativeInstance, bool* output);
+		static void internal_setTint(ScriptGUIVector2Field* nativeInstance, Color* color);
+
+		typedef void(__stdcall *OnChangedThunkDef) (MonoObject*, MonoObject*, MonoException**);
+		typedef void(__stdcall *OnConfirmedThunkDef) (MonoObject*, MonoException**);
+
+		static OnChangedThunkDef onChangedThunk;
+		static OnConfirmedThunkDef onConfirmedThunk;
+	};
 }
 }

+ 52 - 52
Source/SBansheeEditor/Include/BsScriptGUIVector3Field.h

@@ -1,53 +1,53 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsScriptEditorPrerequisites.h"
-#include "BsScriptGUIElement.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Interop class between C++ & CLR for GUIVector3Field.
-	 */
-	class BS_SCR_BED_EXPORT ScriptGUIVector3Field : public TScriptGUIElement<ScriptGUIVector3Field>
-	{
-	public:
-		SCRIPT_OBJ(EDITOR_ASSEMBLY, "BansheeEditor", "GUIVector3Field")
-
-	private:
-		/**
-		 * @brief	Triggered when the value in the native vector field changes.
-		 *
-		 * @param	instance	Managed GUIVector3Field instance.
-		 * @param	newValue	New vector value.
-		 */
-		static void onChanged(MonoObject* instance, Vector3 newValue);
-
-		/**
-		 * @brief	Triggered when the user confirms input in the native vector field.
-		 *
-		 * @param	instance	Managed GUIVector3Field instance.
-		 */
-		static void onConfirmed(MonoObject* instance);
-
-		ScriptGUIVector3Field(MonoObject* instance, GUIVector3Field* vector3Field);
-
-		/************************************************************************/
-		/* 								CLR HOOKS						   		*/
-		/************************************************************************/
-		static void internal_createInstance(MonoObject* instance, MonoObject* title, UINT32 titleWidth,
-			MonoString* style, MonoArray* guiOptions, bool withTitle);
-
-		static void internal_getValue(ScriptGUIVector3Field* nativeInstance, Vector3* output);
-		static void internal_setValue(ScriptGUIVector3Field* nativeInstance, Vector3* value);
-		static void internal_hasInputFocus(ScriptGUIVector3Field* nativeInstance, bool* output);
-		static void internal_setTint(ScriptGUIVector3Field* nativeInstance, Color* color);
-
-		typedef void(__stdcall *OnChangedThunkDef) (MonoObject*, Vector3, MonoException**);
-		typedef void(__stdcall *OnConfirmedThunkDef) (MonoObject*, MonoException**);
-
-		static OnChangedThunkDef onChangedThunk;
-		static OnConfirmedThunkDef onConfirmedThunk;
-	};
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsScriptEditorPrerequisites.h"
+#include "BsScriptGUIElement.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	Interop class between C++ & CLR for GUIVector3Field.
+	 */
+	class BS_SCR_BED_EXPORT ScriptGUIVector3Field : public TScriptGUIElement<ScriptGUIVector3Field>
+	{
+	public:
+		SCRIPT_OBJ(EDITOR_ASSEMBLY, "BansheeEditor", "GUIVector3Field")
+
+	private:
+		/**
+		 * @brief	Triggered when the value in the native vector field changes.
+		 *
+		 * @param	instance	Managed GUIVector3Field instance.
+		 * @param	newValue	New vector value.
+		 */
+		static void onChanged(MonoObject* instance, const Vector3& newValue);
+
+		/**
+		 * @brief	Triggered when the user confirms input in the native vector field.
+		 *
+		 * @param	instance	Managed GUIVector3Field instance.
+		 */
+		static void onConfirmed(MonoObject* instance);
+
+		ScriptGUIVector3Field(MonoObject* instance, GUIVector3Field* vector3Field);
+
+		/************************************************************************/
+		/* 								CLR HOOKS						   		*/
+		/************************************************************************/
+		static void internal_createInstance(MonoObject* instance, MonoObject* title, UINT32 titleWidth,
+			MonoString* style, MonoArray* guiOptions, bool withTitle);
+
+		static void internal_getValue(ScriptGUIVector3Field* nativeInstance, Vector3* output);
+		static void internal_setValue(ScriptGUIVector3Field* nativeInstance, Vector3* value);
+		static void internal_hasInputFocus(ScriptGUIVector3Field* nativeInstance, bool* output);
+		static void internal_setTint(ScriptGUIVector3Field* nativeInstance, Color* color);
+
+		typedef void(__stdcall *OnChangedThunkDef) (MonoObject*, MonoObject*, MonoException**);
+		typedef void(__stdcall *OnConfirmedThunkDef) (MonoObject*, MonoException**);
+
+		static OnChangedThunkDef onChangedThunk;
+		static OnConfirmedThunkDef onConfirmedThunk;
+	};
 }
 }

+ 52 - 52
Source/SBansheeEditor/Include/BsScriptGUIVector4Field.h

@@ -1,53 +1,53 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsScriptEditorPrerequisites.h"
-#include "BsScriptGUIElement.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Interop class between C++ & CLR for GUIVector4Field.
-	 */
-	class BS_SCR_BED_EXPORT ScriptGUIVector4Field : public TScriptGUIElement<ScriptGUIVector4Field>
-	{
-	public:
-		SCRIPT_OBJ(EDITOR_ASSEMBLY, "BansheeEditor", "GUIVector4Field")
-
-	private:
-		/**
-		 * @brief	Triggered when the value in the native vector field changes.
-		 *
-		 * @param	instance	Managed GUIVector4Field instance.
-		 * @param	newValue	New vector value.
-		 */
-		static void onChanged(MonoObject* instance, Vector4 newValue);
-
-		/**
-		 * @brief	Triggered when the user confirms input in the native vector field.
-		 *
-		 * @param	instance	Managed GUIVector4Field instance.
-		 */
-		static void onConfirmed(MonoObject* instance);
-
-		ScriptGUIVector4Field(MonoObject* instance, GUIVector4Field* vector4Field);
-
-		/************************************************************************/
-		/* 								CLR HOOKS						   		*/
-		/************************************************************************/
-		static void internal_createInstance(MonoObject* instance, MonoObject* title, UINT32 titleWidth,
-			MonoString* style, MonoArray* guiOptions, bool withTitle);
-
-		static void internal_getValue(ScriptGUIVector4Field* nativeInstance, Vector4* output);
-		static void internal_setValue(ScriptGUIVector4Field* nativeInstance, Vector4* value);
-		static void internal_hasInputFocus(ScriptGUIVector4Field* nativeInstance, bool* output);
-		static void internal_setTint(ScriptGUIVector4Field* nativeInstance, Color* color);
-
-		typedef void(__stdcall *OnChangedThunkDef) (MonoObject*, Vector4, MonoException**);
-		typedef void(__stdcall *OnConfirmedThunkDef) (MonoObject*, MonoException**);
-
-		static OnChangedThunkDef onChangedThunk;
-		static OnConfirmedThunkDef onConfirmedThunk;
-	};
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsScriptEditorPrerequisites.h"
+#include "BsScriptGUIElement.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	Interop class between C++ & CLR for GUIVector4Field.
+	 */
+	class BS_SCR_BED_EXPORT ScriptGUIVector4Field : public TScriptGUIElement<ScriptGUIVector4Field>
+	{
+	public:
+		SCRIPT_OBJ(EDITOR_ASSEMBLY, "BansheeEditor", "GUIVector4Field")
+
+	private:
+		/**
+		 * @brief	Triggered when the value in the native vector field changes.
+		 *
+		 * @param	instance	Managed GUIVector4Field instance.
+		 * @param	newValue	New vector value.
+		 */
+		static void onChanged(MonoObject* instance, const Vector4& newValue);
+
+		/**
+		 * @brief	Triggered when the user confirms input in the native vector field.
+		 *
+		 * @param	instance	Managed GUIVector4Field instance.
+		 */
+		static void onConfirmed(MonoObject* instance);
+
+		ScriptGUIVector4Field(MonoObject* instance, GUIVector4Field* vector4Field);
+
+		/************************************************************************/
+		/* 								CLR HOOKS						   		*/
+		/************************************************************************/
+		static void internal_createInstance(MonoObject* instance, MonoObject* title, UINT32 titleWidth,
+			MonoString* style, MonoArray* guiOptions, bool withTitle);
+
+		static void internal_getValue(ScriptGUIVector4Field* nativeInstance, Vector4* output);
+		static void internal_setValue(ScriptGUIVector4Field* nativeInstance, Vector4* value);
+		static void internal_hasInputFocus(ScriptGUIVector4Field* nativeInstance, bool* output);
+		static void internal_setTint(ScriptGUIVector4Field* nativeInstance, Color* color);
+
+		typedef void(__stdcall *OnChangedThunkDef) (MonoObject*, MonoObject*, MonoException**);
+		typedef void(__stdcall *OnConfirmedThunkDef) (MonoObject*, MonoException**);
+
+		static OnChangedThunkDef onChangedThunk;
+		static OnConfirmedThunkDef onConfirmedThunk;
+	};
 }
 }

+ 101 - 105
Source/SBansheeEditor/Source/BsScriptGUIVector2Field.cpp

@@ -1,106 +1,102 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsScriptGUIVector2Field.h"
-#include "BsScriptMeta.h"
-#include "BsMonoField.h"
-#include "BsMonoClass.h"
-#include "BsMonoManager.h"
-#include "BsMonoMethod.h"
-#include "BsSpriteTexture.h"
-#include "BsMonoUtil.h"
-#include "BsGUILayout.h"
-#include "BsGUIVector2Field.h"
-#include "BsGUIOptions.h"
-#include "BsGUIContent.h"
-#include "BsScriptGUIElementStyle.h"
-#include "BsScriptGUILayout.h"
-#include "BsScriptHString.h"
-#include "BsScriptGUIContent.h"
-
-using namespace std::placeholders;
-
-namespace BansheeEngine
-{
-	ScriptGUIVector2Field::OnChangedThunkDef ScriptGUIVector2Field::onChangedThunk;
-	ScriptGUIVector2Field::OnConfirmedThunkDef ScriptGUIVector2Field::onConfirmedThunk;
-
-	ScriptGUIVector2Field::ScriptGUIVector2Field(MonoObject* instance, GUIVector2Field* vector2Field)
-		:TScriptGUIElement(instance, vector2Field)
-	{
-
-	}
-
-	void ScriptGUIVector2Field::initRuntimeData()
-	{
-		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptGUIVector2Field::internal_createInstance);
-		metaData.scriptClass->addInternalCall("Internal_GetValue", &ScriptGUIVector2Field::internal_getValue);
-		metaData.scriptClass->addInternalCall("Internal_SetValue", &ScriptGUIVector2Field::internal_setValue);
-		metaData.scriptClass->addInternalCall("Internal_HasInputFocus", &ScriptGUIVector2Field::internal_hasInputFocus);
-		metaData.scriptClass->addInternalCall("Internal_SetTint", &ScriptGUIVector2Field::internal_setTint);
-
-		onChangedThunk = (OnChangedThunkDef)metaData.scriptClass->getMethod("Internal_DoOnChanged", 1)->getThunk();
-		onConfirmedThunk = (OnConfirmedThunkDef)metaData.scriptClass->getMethod("Internal_DoOnConfirmed", 0)->getThunk();
-	}
-
-	void ScriptGUIVector2Field::internal_createInstance(MonoObject* instance, MonoObject* title, UINT32 titleWidth,
-		MonoString* style, MonoArray* guiOptions, bool withTitle)
-	{
-		GUIOptions options;
-
-		UINT32 arrayLen = (UINT32)mono_array_length(guiOptions);
-		for (UINT32 i = 0; i < arrayLen; i++)
-			options.addOption(mono_array_get(guiOptions, GUIOption, i));
-
-		String styleName = toString(MonoUtil::monoToWString(style));
-
-		GUIVector2Field* field = nullptr;
-		if (withTitle)
-		{
-			GUIContent nativeContent(ScriptGUIContent::getText(title), ScriptGUIContent::getImage(title), ScriptGUIContent::getTooltip(title));
-			field = GUIVector2Field::create(nativeContent, titleWidth, options, styleName);
-		}
-		else
-		{
-			field = GUIVector2Field::create(options, styleName);
-		}
-
-		field->onValueChanged.connect(std::bind(&ScriptGUIVector2Field::onChanged, instance, _1));
-		field->onConfirm.connect(std::bind(&ScriptGUIVector2Field::onConfirmed, instance));
-
-		ScriptGUIVector2Field* nativeInstance = new (bs_alloc<ScriptGUIVector2Field>()) ScriptGUIVector2Field(instance, field);
-	}
-
-	void ScriptGUIVector2Field::internal_getValue(ScriptGUIVector2Field* nativeInstance, Vector2* output)
-	{
-		GUIVector2Field* field = static_cast<GUIVector2Field*>(nativeInstance->getGUIElement());
-		*output = field->getValue();
-	}
-
-	void ScriptGUIVector2Field::internal_setValue(ScriptGUIVector2Field* nativeInstance, Vector2* value)
-	{
-		GUIVector2Field* field = static_cast<GUIVector2Field*>(nativeInstance->getGUIElement());
-		return field->setValue(*value);
-	}
-
-	void ScriptGUIVector2Field::internal_hasInputFocus(ScriptGUIVector2Field* nativeInstance, bool* output)
-	{
-		GUIVector2Field* field = static_cast<GUIVector2Field*>(nativeInstance->getGUIElement());
-		*output = field->hasInputFocus();
-	}
-
-	void ScriptGUIVector2Field::internal_setTint(ScriptGUIVector2Field* nativeInstance, Color* color)
-	{
-		GUIVector2Field* field = (GUIVector2Field*)nativeInstance->getGUIElement();
-		field->setTint(*color);
-	}
-
-	void ScriptGUIVector2Field::onChanged(MonoObject* instance, Vector2 newValue)
-	{
-		MonoUtil::invokeThunk(onChangedThunk, instance, newValue);
-	}
-
-	void ScriptGUIVector2Field::onConfirmed(MonoObject* instance)
-	{
-		MonoUtil::invokeThunk(onConfirmedThunk, instance);
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsScriptGUIVector2Field.h"
+#include "BsScriptMeta.h"
+#include "BsMonoClass.h"
+#include "BsMonoManager.h"
+#include "BsMonoMethod.h"
+#include "BsSpriteTexture.h"
+#include "BsMonoUtil.h"
+#include "BsGUIVector2Field.h"
+#include "BsGUIOptions.h"
+#include "BsGUIContent.h"
+#include "BsScriptGUIContent.h"
+#include "BsScriptVector.h"
+
+using namespace std::placeholders;
+
+namespace BansheeEngine
+{
+	ScriptGUIVector2Field::OnChangedThunkDef ScriptGUIVector2Field::onChangedThunk;
+	ScriptGUIVector2Field::OnConfirmedThunkDef ScriptGUIVector2Field::onConfirmedThunk;
+
+	ScriptGUIVector2Field::ScriptGUIVector2Field(MonoObject* instance, GUIVector2Field* vector2Field)
+		:TScriptGUIElement(instance, vector2Field)
+	{
+
+	}
+
+	void ScriptGUIVector2Field::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptGUIVector2Field::internal_createInstance);
+		metaData.scriptClass->addInternalCall("Internal_GetValue", &ScriptGUIVector2Field::internal_getValue);
+		metaData.scriptClass->addInternalCall("Internal_SetValue", &ScriptGUIVector2Field::internal_setValue);
+		metaData.scriptClass->addInternalCall("Internal_HasInputFocus", &ScriptGUIVector2Field::internal_hasInputFocus);
+		metaData.scriptClass->addInternalCall("Internal_SetTint", &ScriptGUIVector2Field::internal_setTint);
+
+		onChangedThunk = (OnChangedThunkDef)metaData.scriptClass->getMethod("Internal_DoOnChanged", 1)->getThunk();
+		onConfirmedThunk = (OnConfirmedThunkDef)metaData.scriptClass->getMethod("Internal_DoOnConfirmed", 0)->getThunk();
+	}
+
+	void ScriptGUIVector2Field::internal_createInstance(MonoObject* instance, MonoObject* title, UINT32 titleWidth,
+		MonoString* style, MonoArray* guiOptions, bool withTitle)
+	{
+		GUIOptions options;
+
+		UINT32 arrayLen = (UINT32)mono_array_length(guiOptions);
+		for (UINT32 i = 0; i < arrayLen; i++)
+			options.addOption(mono_array_get(guiOptions, GUIOption, i));
+
+		String styleName = toString(MonoUtil::monoToWString(style));
+
+		GUIVector2Field* field = nullptr;
+		if (withTitle)
+		{
+			GUIContent nativeContent(ScriptGUIContent::getText(title), ScriptGUIContent::getImage(title), ScriptGUIContent::getTooltip(title));
+			field = GUIVector2Field::create(nativeContent, titleWidth, options, styleName);
+		}
+		else
+		{
+			field = GUIVector2Field::create(options, styleName);
+		}
+
+		field->onValueChanged.connect(std::bind(&ScriptGUIVector2Field::onChanged, instance, _1));
+		field->onConfirm.connect(std::bind(&ScriptGUIVector2Field::onConfirmed, instance));
+
+		ScriptGUIVector2Field* nativeInstance = new (bs_alloc<ScriptGUIVector2Field>()) ScriptGUIVector2Field(instance, field);
+	}
+
+	void ScriptGUIVector2Field::internal_getValue(ScriptGUIVector2Field* nativeInstance, Vector2* output)
+	{
+		GUIVector2Field* field = static_cast<GUIVector2Field*>(nativeInstance->getGUIElement());
+		*output = field->getValue();
+	}
+
+	void ScriptGUIVector2Field::internal_setValue(ScriptGUIVector2Field* nativeInstance, Vector2* value)
+	{
+		GUIVector2Field* field = static_cast<GUIVector2Field*>(nativeInstance->getGUIElement());
+		return field->setValue(*value);
+	}
+
+	void ScriptGUIVector2Field::internal_hasInputFocus(ScriptGUIVector2Field* nativeInstance, bool* output)
+	{
+		GUIVector2Field* field = static_cast<GUIVector2Field*>(nativeInstance->getGUIElement());
+		*output = field->hasInputFocus();
+	}
+
+	void ScriptGUIVector2Field::internal_setTint(ScriptGUIVector2Field* nativeInstance, Color* color)
+	{
+		GUIVector2Field* field = (GUIVector2Field*)nativeInstance->getGUIElement();
+		field->setTint(*color);
+	}
+
+	void ScriptGUIVector2Field::onChanged(MonoObject* instance, const Vector2& newValue)
+	{
+		MonoUtil::invokeThunk(onChangedThunk, instance, ScriptVector2::box(newValue));
+	}
+
+	void ScriptGUIVector2Field::onConfirmed(MonoObject* instance)
+	{
+		MonoUtil::invokeThunk(onConfirmedThunk, instance);
+	}
 }
 }

+ 101 - 105
Source/SBansheeEditor/Source/BsScriptGUIVector3Field.cpp

@@ -1,106 +1,102 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsScriptGUIVector3Field.h"
-#include "BsScriptMeta.h"
-#include "BsMonoField.h"
-#include "BsMonoClass.h"
-#include "BsMonoManager.h"
-#include "BsMonoMethod.h"
-#include "BsSpriteTexture.h"
-#include "BsMonoUtil.h"
-#include "BsGUILayout.h"
-#include "BsGUIVector3Field.h"
-#include "BsGUIOptions.h"
-#include "BsGUIContent.h"
-#include "BsScriptGUIElementStyle.h"
-#include "BsScriptGUILayout.h"
-#include "BsScriptHString.h"
-#include "BsScriptGUIContent.h"
-
-using namespace std::placeholders;
-
-namespace BansheeEngine
-{
-	ScriptGUIVector3Field::OnChangedThunkDef ScriptGUIVector3Field::onChangedThunk;
-	ScriptGUIVector3Field::OnConfirmedThunkDef ScriptGUIVector3Field::onConfirmedThunk;
-
-	ScriptGUIVector3Field::ScriptGUIVector3Field(MonoObject* instance, GUIVector3Field* vector3Field)
-		:TScriptGUIElement(instance, vector3Field)
-	{
-
-	}
-
-	void ScriptGUIVector3Field::initRuntimeData()
-	{
-		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptGUIVector3Field::internal_createInstance);
-		metaData.scriptClass->addInternalCall("Internal_GetValue", &ScriptGUIVector3Field::internal_getValue);
-		metaData.scriptClass->addInternalCall("Internal_SetValue", &ScriptGUIVector3Field::internal_setValue);
-		metaData.scriptClass->addInternalCall("Internal_HasInputFocus", &ScriptGUIVector3Field::internal_hasInputFocus);
-		metaData.scriptClass->addInternalCall("Internal_SetTint", &ScriptGUIVector3Field::internal_setTint);
-
-		onChangedThunk = (OnChangedThunkDef)metaData.scriptClass->getMethod("Internal_DoOnChanged", 1)->getThunk();
-		onConfirmedThunk = (OnConfirmedThunkDef)metaData.scriptClass->getMethod("Internal_DoOnConfirmed", 0)->getThunk();
-	}
-
-	void ScriptGUIVector3Field::internal_createInstance(MonoObject* instance, MonoObject* title, UINT32 titleWidth,
-		MonoString* style, MonoArray* guiOptions, bool withTitle)
-	{
-		GUIOptions options;
-
-		UINT32 arrayLen = (UINT32)mono_array_length(guiOptions);
-		for (UINT32 i = 0; i < arrayLen; i++)
-			options.addOption(mono_array_get(guiOptions, GUIOption, i));
-
-		String styleName = toString(MonoUtil::monoToWString(style));
-
-		GUIVector3Field* field = nullptr;
-		if (withTitle)
-		{
-			GUIContent nativeContent(ScriptGUIContent::getText(title), ScriptGUIContent::getImage(title), ScriptGUIContent::getTooltip(title));
-			field = GUIVector3Field::create(nativeContent, titleWidth, options, styleName);
-		}
-		else
-		{
-			field = GUIVector3Field::create(options, styleName);
-		}
-
-		field->onValueChanged.connect(std::bind(&ScriptGUIVector3Field::onChanged, instance, _1));
-		field->onConfirm.connect(std::bind(&ScriptGUIVector3Field::onConfirmed, instance));
-
-		ScriptGUIVector3Field* nativeInstance = new (bs_alloc<ScriptGUIVector3Field>()) ScriptGUIVector3Field(instance, field);
-	}
-
-	void ScriptGUIVector3Field::internal_getValue(ScriptGUIVector3Field* nativeInstance, Vector3* output)
-	{
-		GUIVector3Field* field = static_cast<GUIVector3Field*>(nativeInstance->getGUIElement());
-		*output = field->getValue();
-	}
-
-	void ScriptGUIVector3Field::internal_setValue(ScriptGUIVector3Field* nativeInstance, Vector3* value)
-	{
-		GUIVector3Field* field = static_cast<GUIVector3Field*>(nativeInstance->getGUIElement());
-		return field->setValue(*value);
-	}
-
-	void ScriptGUIVector3Field::internal_hasInputFocus(ScriptGUIVector3Field* nativeInstance, bool* output)
-	{
-		GUIVector3Field* field = static_cast<GUIVector3Field*>(nativeInstance->getGUIElement());
-		*output = field->hasInputFocus();
-	}
-
-	void ScriptGUIVector3Field::internal_setTint(ScriptGUIVector3Field* nativeInstance, Color* color)
-	{
-		GUIVector3Field* field = (GUIVector3Field*)nativeInstance->getGUIElement();
-		field->setTint(*color);
-	}
-
-	void ScriptGUIVector3Field::onChanged(MonoObject* instance, Vector3 newValue)
-	{
-		MonoUtil::invokeThunk(onChangedThunk, instance, newValue);
-	}
-
-	void ScriptGUIVector3Field::onConfirmed(MonoObject* instance)
-	{
-		MonoUtil::invokeThunk(onConfirmedThunk, instance);
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsScriptGUIVector3Field.h"
+#include "BsScriptMeta.h"
+#include "BsMonoClass.h"
+#include "BsMonoManager.h"
+#include "BsMonoMethod.h"
+#include "BsSpriteTexture.h"
+#include "BsMonoUtil.h"
+#include "BsGUIVector3Field.h"
+#include "BsGUIOptions.h"
+#include "BsGUIContent.h"
+#include "BsScriptGUIContent.h"
+#include "BsScriptVector.h"
+
+using namespace std::placeholders;
+
+namespace BansheeEngine
+{
+	ScriptGUIVector3Field::OnChangedThunkDef ScriptGUIVector3Field::onChangedThunk;
+	ScriptGUIVector3Field::OnConfirmedThunkDef ScriptGUIVector3Field::onConfirmedThunk;
+
+	ScriptGUIVector3Field::ScriptGUIVector3Field(MonoObject* instance, GUIVector3Field* vector3Field)
+		:TScriptGUIElement(instance, vector3Field)
+	{
+
+	}
+
+	void ScriptGUIVector3Field::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptGUIVector3Field::internal_createInstance);
+		metaData.scriptClass->addInternalCall("Internal_GetValue", &ScriptGUIVector3Field::internal_getValue);
+		metaData.scriptClass->addInternalCall("Internal_SetValue", &ScriptGUIVector3Field::internal_setValue);
+		metaData.scriptClass->addInternalCall("Internal_HasInputFocus", &ScriptGUIVector3Field::internal_hasInputFocus);
+		metaData.scriptClass->addInternalCall("Internal_SetTint", &ScriptGUIVector3Field::internal_setTint);
+
+		onChangedThunk = (OnChangedThunkDef)metaData.scriptClass->getMethod("Internal_DoOnChanged", 1)->getThunk();
+		onConfirmedThunk = (OnConfirmedThunkDef)metaData.scriptClass->getMethod("Internal_DoOnConfirmed", 0)->getThunk();
+	}
+
+	void ScriptGUIVector3Field::internal_createInstance(MonoObject* instance, MonoObject* title, UINT32 titleWidth,
+		MonoString* style, MonoArray* guiOptions, bool withTitle)
+	{
+		GUIOptions options;
+
+		UINT32 arrayLen = (UINT32)mono_array_length(guiOptions);
+		for (UINT32 i = 0; i < arrayLen; i++)
+			options.addOption(mono_array_get(guiOptions, GUIOption, i));
+
+		String styleName = toString(MonoUtil::monoToWString(style));
+
+		GUIVector3Field* field = nullptr;
+		if (withTitle)
+		{
+			GUIContent nativeContent(ScriptGUIContent::getText(title), ScriptGUIContent::getImage(title), ScriptGUIContent::getTooltip(title));
+			field = GUIVector3Field::create(nativeContent, titleWidth, options, styleName);
+		}
+		else
+		{
+			field = GUIVector3Field::create(options, styleName);
+		}
+
+		field->onValueChanged.connect(std::bind(&ScriptGUIVector3Field::onChanged, instance, _1));
+		field->onConfirm.connect(std::bind(&ScriptGUIVector3Field::onConfirmed, instance));
+
+		ScriptGUIVector3Field* nativeInstance = new (bs_alloc<ScriptGUIVector3Field>()) ScriptGUIVector3Field(instance, field);
+	}
+
+	void ScriptGUIVector3Field::internal_getValue(ScriptGUIVector3Field* nativeInstance, Vector3* output)
+	{
+		GUIVector3Field* field = static_cast<GUIVector3Field*>(nativeInstance->getGUIElement());
+		*output = field->getValue();
+	}
+
+	void ScriptGUIVector3Field::internal_setValue(ScriptGUIVector3Field* nativeInstance, Vector3* value)
+	{
+		GUIVector3Field* field = static_cast<GUIVector3Field*>(nativeInstance->getGUIElement());
+		return field->setValue(*value);
+	}
+
+	void ScriptGUIVector3Field::internal_hasInputFocus(ScriptGUIVector3Field* nativeInstance, bool* output)
+	{
+		GUIVector3Field* field = static_cast<GUIVector3Field*>(nativeInstance->getGUIElement());
+		*output = field->hasInputFocus();
+	}
+
+	void ScriptGUIVector3Field::internal_setTint(ScriptGUIVector3Field* nativeInstance, Color* color)
+	{
+		GUIVector3Field* field = (GUIVector3Field*)nativeInstance->getGUIElement();
+		field->setTint(*color);
+	}
+
+	void ScriptGUIVector3Field::onChanged(MonoObject* instance, const Vector3& newValue)
+	{
+		MonoUtil::invokeThunk(onChangedThunk, instance, ScriptVector3::box(newValue));
+	}
+
+	void ScriptGUIVector3Field::onConfirmed(MonoObject* instance)
+	{
+		MonoUtil::invokeThunk(onConfirmedThunk, instance);
+	}
 }
 }

+ 100 - 105
Source/SBansheeEditor/Source/BsScriptGUIVector4Field.cpp

@@ -1,106 +1,101 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsScriptGUIVector4Field.h"
-#include "BsScriptMeta.h"
-#include "BsMonoField.h"
-#include "BsMonoClass.h"
-#include "BsMonoManager.h"
-#include "BsMonoMethod.h"
-#include "BsSpriteTexture.h"
-#include "BsMonoUtil.h"
-#include "BsGUILayout.h"
-#include "BsGUIVector4Field.h"
-#include "BsGUIOptions.h"
-#include "BsGUIContent.h"
-#include "BsScriptGUIElementStyle.h"
-#include "BsScriptGUILayout.h"
-#include "BsScriptHString.h"
-#include "BsScriptGUIContent.h"
-
-using namespace std::placeholders;
-
-namespace BansheeEngine
-{
-	ScriptGUIVector4Field::OnChangedThunkDef ScriptGUIVector4Field::onChangedThunk;
-	ScriptGUIVector4Field::OnConfirmedThunkDef ScriptGUIVector4Field::onConfirmedThunk;
-
-	ScriptGUIVector4Field::ScriptGUIVector4Field(MonoObject* instance, GUIVector4Field* vector4Field)
-		:TScriptGUIElement(instance, vector4Field)
-	{
-
-	}
-
-	void ScriptGUIVector4Field::initRuntimeData()
-	{
-		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptGUIVector4Field::internal_createInstance);
-		metaData.scriptClass->addInternalCall("Internal_GetValue", &ScriptGUIVector4Field::internal_getValue);
-		metaData.scriptClass->addInternalCall("Internal_SetValue", &ScriptGUIVector4Field::internal_setValue);
-		metaData.scriptClass->addInternalCall("Internal_HasInputFocus", &ScriptGUIVector4Field::internal_hasInputFocus);
-		metaData.scriptClass->addInternalCall("Internal_SetTint", &ScriptGUIVector4Field::internal_setTint);
-
-		onChangedThunk = (OnChangedThunkDef)metaData.scriptClass->getMethod("Internal_DoOnChanged", 1)->getThunk();
-		onConfirmedThunk = (OnConfirmedThunkDef)metaData.scriptClass->getMethod("Internal_DoOnConfirmed", 0)->getThunk();
-	}
-
-	void ScriptGUIVector4Field::internal_createInstance(MonoObject* instance, MonoObject* title, UINT32 titleWidth,
-		MonoString* style, MonoArray* guiOptions, bool withTitle)
-	{
-		GUIOptions options;
-
-		UINT32 arrayLen = (UINT32)mono_array_length(guiOptions);
-		for (UINT32 i = 0; i < arrayLen; i++)
-			options.addOption(mono_array_get(guiOptions, GUIOption, i));
-
-		String styleName = toString(MonoUtil::monoToWString(style));
-
-		GUIVector4Field* field = nullptr;
-		if (withTitle)
-		{
-			GUIContent nativeContent(ScriptGUIContent::getText(title), ScriptGUIContent::getImage(title), ScriptGUIContent::getTooltip(title));
-			field = GUIVector4Field::create(nativeContent, titleWidth, options, styleName);
-		}
-		else
-		{
-			field = GUIVector4Field::create(options, styleName);
-		}
-
-		field->onValueChanged.connect(std::bind(&ScriptGUIVector4Field::onChanged, instance, _1));
-		field->onConfirm.connect(std::bind(&ScriptGUIVector4Field::onConfirmed, instance));
-
-		ScriptGUIVector4Field* nativeInstance = new (bs_alloc<ScriptGUIVector4Field>()) ScriptGUIVector4Field(instance, field);
-	}
-
-	void ScriptGUIVector4Field::internal_getValue(ScriptGUIVector4Field* nativeInstance, Vector4* output)
-	{
-		GUIVector4Field* field = static_cast<GUIVector4Field*>(nativeInstance->getGUIElement());
-		*output = field->getValue();
-	}
-
-	void ScriptGUIVector4Field::internal_setValue(ScriptGUIVector4Field* nativeInstance, Vector4* value)
-	{
-		GUIVector4Field* field = static_cast<GUIVector4Field*>(nativeInstance->getGUIElement());
-		return field->setValue(*value);
-	}
-
-	void ScriptGUIVector4Field::internal_hasInputFocus(ScriptGUIVector4Field* nativeInstance, bool* output)
-	{
-		GUIVector4Field* field = static_cast<GUIVector4Field*>(nativeInstance->getGUIElement());
-		*output = field->hasInputFocus();
-	}
-
-	void ScriptGUIVector4Field::internal_setTint(ScriptGUIVector4Field* nativeInstance, Color* color)
-	{
-		GUIVector4Field* field = (GUIVector4Field*)nativeInstance->getGUIElement();
-		field->setTint(*color);
-	}
-
-	void ScriptGUIVector4Field::onChanged(MonoObject* instance, Vector4 newValue)
-	{
-		MonoUtil::invokeThunk(onChangedThunk, instance, newValue);
-	}
-
-	void ScriptGUIVector4Field::onConfirmed(MonoObject* instance)
-	{
-		MonoUtil::invokeThunk(onConfirmedThunk, instance);
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsScriptGUIVector4Field.h"
+#include "BsScriptMeta.h"
+#include "BsMonoClass.h"
+#include "BsMonoManager.h"
+#include "BsMonoMethod.h"
+#include "BsMonoUtil.h"
+#include "BsGUIVector4Field.h"
+#include "BsGUIOptions.h"
+#include "BsGUIContent.h"
+#include "BsScriptGUIContent.h"
+#include "BsScriptVector.h"
+
+using namespace std::placeholders;
+
+namespace BansheeEngine
+{
+	ScriptGUIVector4Field::OnChangedThunkDef ScriptGUIVector4Field::onChangedThunk;
+	ScriptGUIVector4Field::OnConfirmedThunkDef ScriptGUIVector4Field::onConfirmedThunk;
+
+	ScriptGUIVector4Field::ScriptGUIVector4Field(MonoObject* instance, GUIVector4Field* vector4Field)
+		:TScriptGUIElement(instance, vector4Field)
+	{
+
+	}
+
+	void ScriptGUIVector4Field::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptGUIVector4Field::internal_createInstance);
+		metaData.scriptClass->addInternalCall("Internal_GetValue", &ScriptGUIVector4Field::internal_getValue);
+		metaData.scriptClass->addInternalCall("Internal_SetValue", &ScriptGUIVector4Field::internal_setValue);
+		metaData.scriptClass->addInternalCall("Internal_HasInputFocus", &ScriptGUIVector4Field::internal_hasInputFocus);
+		metaData.scriptClass->addInternalCall("Internal_SetTint", &ScriptGUIVector4Field::internal_setTint);
+
+		onChangedThunk = (OnChangedThunkDef)metaData.scriptClass->getMethod("Internal_DoOnChanged", 1)->getThunk();
+		onConfirmedThunk = (OnConfirmedThunkDef)metaData.scriptClass->getMethod("Internal_DoOnConfirmed", 0)->getThunk();
+	}
+
+	void ScriptGUIVector4Field::internal_createInstance(MonoObject* instance, MonoObject* title, UINT32 titleWidth,
+		MonoString* style, MonoArray* guiOptions, bool withTitle)
+	{
+		GUIOptions options;
+
+		UINT32 arrayLen = (UINT32)mono_array_length(guiOptions);
+		for (UINT32 i = 0; i < arrayLen; i++)
+			options.addOption(mono_array_get(guiOptions, GUIOption, i));
+
+		String styleName = toString(MonoUtil::monoToWString(style));
+
+		GUIVector4Field* field = nullptr;
+		if (withTitle)
+		{
+			GUIContent nativeContent(ScriptGUIContent::getText(title), ScriptGUIContent::getImage(title), ScriptGUIContent::getTooltip(title));
+			field = GUIVector4Field::create(nativeContent, titleWidth, options, styleName);
+		}
+		else
+		{
+			field = GUIVector4Field::create(options, styleName);
+		}
+
+		field->onValueChanged.connect(std::bind(&ScriptGUIVector4Field::onChanged, instance, _1));
+		field->onConfirm.connect(std::bind(&ScriptGUIVector4Field::onConfirmed, instance));
+
+		ScriptGUIVector4Field* nativeInstance = new (bs_alloc<ScriptGUIVector4Field>()) ScriptGUIVector4Field(instance, field);
+	}
+
+	void ScriptGUIVector4Field::internal_getValue(ScriptGUIVector4Field* nativeInstance, Vector4* output)
+	{
+		GUIVector4Field* field = static_cast<GUIVector4Field*>(nativeInstance->getGUIElement());
+		*output = field->getValue();
+	}
+
+	void ScriptGUIVector4Field::internal_setValue(ScriptGUIVector4Field* nativeInstance, Vector4* value)
+	{
+		GUIVector4Field* field = static_cast<GUIVector4Field*>(nativeInstance->getGUIElement());
+		return field->setValue(*value);
+	}
+
+	void ScriptGUIVector4Field::internal_hasInputFocus(ScriptGUIVector4Field* nativeInstance, bool* output)
+	{
+		GUIVector4Field* field = static_cast<GUIVector4Field*>(nativeInstance->getGUIElement());
+		*output = field->hasInputFocus();
+	}
+
+	void ScriptGUIVector4Field::internal_setTint(ScriptGUIVector4Field* nativeInstance, Color* color)
+	{
+		GUIVector4Field* field = (GUIVector4Field*)nativeInstance->getGUIElement();
+		field->setTint(*color);
+	}
+
+	void ScriptGUIVector4Field::onChanged(MonoObject* instance, const Vector4& newValue)
+	{
+		MonoUtil::invokeThunk(onChangedThunk, instance, ScriptVector4::box(newValue));
+	}
+
+	void ScriptGUIVector4Field::onConfirmed(MonoObject* instance)
+	{
+		MonoUtil::invokeThunk(onConfirmedThunk, instance);
+	}
 }
 }

+ 1 - 1
Source/SBansheeEngine/Include/BsScriptCharacterController.h

@@ -60,7 +60,7 @@ namespace BansheeEngine
 		static void internal_SetSlopeLimit(ScriptCharacterController* thisPtr, float value);
 		static void internal_SetSlopeLimit(ScriptCharacterController* thisPtr, float value);
 		static void internal_SetLayer(ScriptCharacterController* thisPtr, UINT64 layer);
 		static void internal_SetLayer(ScriptCharacterController* thisPtr, UINT64 layer);
 
 
-		typedef void(__stdcall *OnHitThunkDef) (MonoObject*, ScriptControllerCollision*, MonoException**);
+		typedef void(__stdcall *OnHitThunkDef) (MonoObject*, MonoObject*, MonoException**);
 
 
 		static OnHitThunkDef onColliderHitThunk;
 		static OnHitThunkDef onColliderHitThunk;
 		static OnHitThunkDef onControllerHitThunk;
 		static OnHitThunkDef onControllerHitThunk;

+ 147 - 143
Source/SBansheeEngine/Source/BsScriptCharacterController.cpp

@@ -1,144 +1,148 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsScriptCharacterController.h"
-#include "BsMonoUtil.h"
-#include "BsMonoClass.h"
-#include "BsMonoMethod.h"
-
-using namespace std::placeholders;
-
-namespace BansheeEngine
-{
-	ScriptCharacterController::OnHitThunkDef ScriptCharacterController::onColliderHitThunk = nullptr;
-	ScriptCharacterController::OnHitThunkDef ScriptCharacterController::onControllerHitThunk = nullptr;
-
-	ScriptCharacterController::ScriptCharacterController(MonoObject* instance, const SPtr<CharacterController>& charController)
-		:ScriptObject(instance), mCharacterController(charController)
-	{
-		charController->onColliderHit.connect(std::bind(&ScriptCharacterController::onColliderHit, instance, _1));
-		charController->onControllerHit.connect(std::bind(&ScriptCharacterController::onControllerHit, instance, _1));
-	}
-
-	void ScriptCharacterController::initRuntimeData()
-	{
-		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptCharacterController::internal_CreateInstance);
-		metaData.scriptClass->addInternalCall("Internal_Destroy", &ScriptCharacterController::internal_Destroy);
-		metaData.scriptClass->addInternalCall("Internal_Move", &ScriptCharacterController::internal_Move);
-		metaData.scriptClass->addInternalCall("Internal_GetPosition", &ScriptCharacterController::internal_GetPosition);
-		metaData.scriptClass->addInternalCall("Internal_SetPosition", &ScriptCharacterController::internal_SetPosition);
-		metaData.scriptClass->addInternalCall("Internal_GetFootPosition", &ScriptCharacterController::internal_GetFootPosition);
-		metaData.scriptClass->addInternalCall("Internal_SetFootPosition", &ScriptCharacterController::internal_SetFootPosition);
-		metaData.scriptClass->addInternalCall("Internal_SetRadius", &ScriptCharacterController::internal_SetRadius);
-		metaData.scriptClass->addInternalCall("Internal_SetHeight", &ScriptCharacterController::internal_SetHeight);
-		metaData.scriptClass->addInternalCall("Internal_SetClimbingMode", &ScriptCharacterController::internal_SetClimbingMode);
-		metaData.scriptClass->addInternalCall("Internal_SetNonWalkableMode", &ScriptCharacterController::internal_SetNonWalkableMode);
-		metaData.scriptClass->addInternalCall("Internal_SetMinMoveDistance", &ScriptCharacterController::internal_SetMinMoveDistance);
-		metaData.scriptClass->addInternalCall("Internal_SetContactOffset", &ScriptCharacterController::internal_SetContactOffset);
-		metaData.scriptClass->addInternalCall("Internal_SetSlopeLimit", &ScriptCharacterController::internal_SetSlopeLimit);
-		metaData.scriptClass->addInternalCall("Internal_SetLayer", &ScriptCharacterController::internal_SetLayer);
-
-		onColliderHitThunk = (OnHitThunkDef)metaData.scriptClass->getMethod("Internal_DoOnColliderHit", 1)->getThunk();
-		onControllerHitThunk = (OnHitThunkDef)metaData.scriptClass->getMethod("Internal_DoOnControllerHit", 1)->getThunk();
-	}
-
-	void ScriptCharacterController::onColliderHit(MonoObject* instance, const ControllerColliderCollision& collisionData)
-	{
-		ScriptControllerCollision scriptCollisionData = ScriptControllerCollisionHelper::create(collisionData);
-		MonoUtil::invokeThunk(onColliderHitThunk, instance, &scriptCollisionData);
-	}
-
-	void ScriptCharacterController::onControllerHit(MonoObject* instance, const ControllerControllerCollision& collisionData)
-	{
-		ScriptControllerCollision scriptCollisionData = ScriptControllerCollisionHelper::create(collisionData);
-		MonoUtil::invokeThunk(onControllerHitThunk, instance, &scriptCollisionData);
-	}
-
-	void ScriptCharacterController::internal_CreateInstance(MonoObject* instance, CHAR_CONTROLLER_DESC* initData)
-	{
-		SPtr<CharacterController> charController = CharacterController::create(*initData);
-		charController->_setOwner(PhysicsOwnerType::Script, instance);
-
-		ScriptCharacterController* scriptCharacterController = 
-			new (bs_alloc<ScriptCharacterController>()) ScriptCharacterController(instance, charController);
-	}
-
-	void ScriptCharacterController::internal_Destroy(ScriptCharacterController* thisPtr)
-	{
-		thisPtr->mCharacterController = nullptr;
-	}
-
-	CharacterCollisionFlags ScriptCharacterController::internal_Move(ScriptCharacterController* thisPtr, Vector3* displacement)
-	{
-		return thisPtr->mCharacterController->move(*displacement);
-	}
-
-	void ScriptCharacterController::internal_GetPosition(ScriptCharacterController* thisPtr, Vector3* position)
-	{
-		*position = thisPtr->mCharacterController->getPosition();
-	}
-
-	void ScriptCharacterController::internal_SetPosition(ScriptCharacterController* thisPtr, Vector3* position)
-	{
-		thisPtr->mCharacterController->setPosition(*position);
-	}
-
-	void ScriptCharacterController::internal_GetFootPosition(ScriptCharacterController* thisPtr, Vector3* position)
-	{
-		*position = thisPtr->mCharacterController->getFootPosition();
-	}
-
-	void ScriptCharacterController::internal_SetFootPosition(ScriptCharacterController* thisPtr, Vector3* position)
-	{
-		thisPtr->mCharacterController->setFootPosition(*position);
-	}
-
-	void ScriptCharacterController::internal_SetRadius(ScriptCharacterController* thisPtr, float radius)
-	{
-		thisPtr->mCharacterController->setRadius(radius);
-	}
-
-	void ScriptCharacterController::internal_SetHeight(ScriptCharacterController* thisPtr, float height)
-	{
-		thisPtr->mCharacterController->setHeight(height);
-	}
-
-	void ScriptCharacterController::internal_SetUp(ScriptCharacterController* thisPtr, Vector3* up)
-	{
-		thisPtr->mCharacterController->setUp(*up);
-	}
-
-	void ScriptCharacterController::internal_SetClimbingMode(ScriptCharacterController* thisPtr, CharacterClimbingMode mode)
-	{
-		thisPtr->mCharacterController->setClimbingMode(mode);
-	}
-
-	void ScriptCharacterController::internal_SetNonWalkableMode(ScriptCharacterController* thisPtr, CharacterNonWalkableMode mode)
-	{
-		thisPtr->mCharacterController->setNonWalkableMode(mode);
-	}
-
-	void ScriptCharacterController::internal_SetMinMoveDistance(ScriptCharacterController* thisPtr, float value)
-	{
-		thisPtr->mCharacterController->setMinMoveDistance(value);
-	}
-
-	void ScriptCharacterController::internal_SetContactOffset(ScriptCharacterController* thisPtr, float value)
-	{
-		thisPtr->mCharacterController->setContactOffset(value);
-	}
-
-	void ScriptCharacterController::internal_SetStepOffset(ScriptCharacterController* thisPtr, float value)
-	{
-		thisPtr->mCharacterController->setStepOffset(value);
-	}
-
-	void ScriptCharacterController::internal_SetSlopeLimit(ScriptCharacterController* thisPtr, float value)
-	{
-		thisPtr->mCharacterController->setSlopeLimit(Radian(value));
-	}
-
-	void ScriptCharacterController::internal_SetLayer(ScriptCharacterController* thisPtr, UINT64 layer)
-	{
-		thisPtr->mCharacterController->setLayer(layer);
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsScriptCharacterController.h"
+#include "BsMonoUtil.h"
+#include "BsMonoClass.h"
+#include "BsMonoMethod.h"
+
+using namespace std::placeholders;
+
+namespace BansheeEngine
+{
+	ScriptCharacterController::OnHitThunkDef ScriptCharacterController::onColliderHitThunk = nullptr;
+	ScriptCharacterController::OnHitThunkDef ScriptCharacterController::onControllerHitThunk = nullptr;
+
+	ScriptCharacterController::ScriptCharacterController(MonoObject* instance, const SPtr<CharacterController>& charController)
+		:ScriptObject(instance), mCharacterController(charController)
+	{
+		charController->onColliderHit.connect(std::bind(&ScriptCharacterController::onColliderHit, instance, _1));
+		charController->onControllerHit.connect(std::bind(&ScriptCharacterController::onControllerHit, instance, _1));
+	}
+
+	void ScriptCharacterController::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptCharacterController::internal_CreateInstance);
+		metaData.scriptClass->addInternalCall("Internal_Destroy", &ScriptCharacterController::internal_Destroy);
+		metaData.scriptClass->addInternalCall("Internal_Move", &ScriptCharacterController::internal_Move);
+		metaData.scriptClass->addInternalCall("Internal_GetPosition", &ScriptCharacterController::internal_GetPosition);
+		metaData.scriptClass->addInternalCall("Internal_SetPosition", &ScriptCharacterController::internal_SetPosition);
+		metaData.scriptClass->addInternalCall("Internal_GetFootPosition", &ScriptCharacterController::internal_GetFootPosition);
+		metaData.scriptClass->addInternalCall("Internal_SetFootPosition", &ScriptCharacterController::internal_SetFootPosition);
+		metaData.scriptClass->addInternalCall("Internal_SetRadius", &ScriptCharacterController::internal_SetRadius);
+		metaData.scriptClass->addInternalCall("Internal_SetHeight", &ScriptCharacterController::internal_SetHeight);
+		metaData.scriptClass->addInternalCall("Internal_SetClimbingMode", &ScriptCharacterController::internal_SetClimbingMode);
+		metaData.scriptClass->addInternalCall("Internal_SetNonWalkableMode", &ScriptCharacterController::internal_SetNonWalkableMode);
+		metaData.scriptClass->addInternalCall("Internal_SetMinMoveDistance", &ScriptCharacterController::internal_SetMinMoveDistance);
+		metaData.scriptClass->addInternalCall("Internal_SetContactOffset", &ScriptCharacterController::internal_SetContactOffset);
+		metaData.scriptClass->addInternalCall("Internal_SetSlopeLimit", &ScriptCharacterController::internal_SetSlopeLimit);
+		metaData.scriptClass->addInternalCall("Internal_SetLayer", &ScriptCharacterController::internal_SetLayer);
+
+		onColliderHitThunk = (OnHitThunkDef)metaData.scriptClass->getMethod("Internal_DoOnColliderHit", 1)->getThunk();
+		onControllerHitThunk = (OnHitThunkDef)metaData.scriptClass->getMethod("Internal_DoOnControllerHit", 1)->getThunk();
+	}
+
+	void ScriptCharacterController::onColliderHit(MonoObject* instance, const ControllerColliderCollision& collisionData)
+	{
+		ScriptControllerCollision scriptCollisionData = ScriptControllerCollisionHelper::create(collisionData);
+		MonoObject* managedData = ScriptControllerCollisionHelper::box(scriptCollisionData);
+
+		MonoUtil::invokeThunk(onColliderHitThunk, instance, managedData);
+	}
+
+	void ScriptCharacterController::onControllerHit(MonoObject* instance, const ControllerControllerCollision& collisionData)
+	{
+		ScriptControllerCollision scriptCollisionData = ScriptControllerCollisionHelper::create(collisionData);
+		MonoObject* managedData = ScriptControllerCollisionHelper::box(scriptCollisionData);
+
+		MonoUtil::invokeThunk(onControllerHitThunk, instance, managedData);
+	}
+
+	void ScriptCharacterController::internal_CreateInstance(MonoObject* instance, CHAR_CONTROLLER_DESC* initData)
+	{
+		SPtr<CharacterController> charController = CharacterController::create(*initData);
+		charController->_setOwner(PhysicsOwnerType::Script, instance);
+
+		ScriptCharacterController* scriptCharacterController = 
+			new (bs_alloc<ScriptCharacterController>()) ScriptCharacterController(instance, charController);
+	}
+
+	void ScriptCharacterController::internal_Destroy(ScriptCharacterController* thisPtr)
+	{
+		thisPtr->mCharacterController = nullptr;
+	}
+
+	CharacterCollisionFlags ScriptCharacterController::internal_Move(ScriptCharacterController* thisPtr, Vector3* displacement)
+	{
+		return thisPtr->mCharacterController->move(*displacement);
+	}
+
+	void ScriptCharacterController::internal_GetPosition(ScriptCharacterController* thisPtr, Vector3* position)
+	{
+		*position = thisPtr->mCharacterController->getPosition();
+	}
+
+	void ScriptCharacterController::internal_SetPosition(ScriptCharacterController* thisPtr, Vector3* position)
+	{
+		thisPtr->mCharacterController->setPosition(*position);
+	}
+
+	void ScriptCharacterController::internal_GetFootPosition(ScriptCharacterController* thisPtr, Vector3* position)
+	{
+		*position = thisPtr->mCharacterController->getFootPosition();
+	}
+
+	void ScriptCharacterController::internal_SetFootPosition(ScriptCharacterController* thisPtr, Vector3* position)
+	{
+		thisPtr->mCharacterController->setFootPosition(*position);
+	}
+
+	void ScriptCharacterController::internal_SetRadius(ScriptCharacterController* thisPtr, float radius)
+	{
+		thisPtr->mCharacterController->setRadius(radius);
+	}
+
+	void ScriptCharacterController::internal_SetHeight(ScriptCharacterController* thisPtr, float height)
+	{
+		thisPtr->mCharacterController->setHeight(height);
+	}
+
+	void ScriptCharacterController::internal_SetUp(ScriptCharacterController* thisPtr, Vector3* up)
+	{
+		thisPtr->mCharacterController->setUp(*up);
+	}
+
+	void ScriptCharacterController::internal_SetClimbingMode(ScriptCharacterController* thisPtr, CharacterClimbingMode mode)
+	{
+		thisPtr->mCharacterController->setClimbingMode(mode);
+	}
+
+	void ScriptCharacterController::internal_SetNonWalkableMode(ScriptCharacterController* thisPtr, CharacterNonWalkableMode mode)
+	{
+		thisPtr->mCharacterController->setNonWalkableMode(mode);
+	}
+
+	void ScriptCharacterController::internal_SetMinMoveDistance(ScriptCharacterController* thisPtr, float value)
+	{
+		thisPtr->mCharacterController->setMinMoveDistance(value);
+	}
+
+	void ScriptCharacterController::internal_SetContactOffset(ScriptCharacterController* thisPtr, float value)
+	{
+		thisPtr->mCharacterController->setContactOffset(value);
+	}
+
+	void ScriptCharacterController::internal_SetStepOffset(ScriptCharacterController* thisPtr, float value)
+	{
+		thisPtr->mCharacterController->setStepOffset(value);
+	}
+
+	void ScriptCharacterController::internal_SetSlopeLimit(ScriptCharacterController* thisPtr, float value)
+	{
+		thisPtr->mCharacterController->setSlopeLimit(Radian(value));
+	}
+
+	void ScriptCharacterController::internal_SetLayer(ScriptCharacterController* thisPtr, UINT64 layer)
+	{
+		thisPtr->mCharacterController->setLayer(layer);
+	}
 }
 }