Enabling object snapping to buildable objects

Introduction
This article serves as a guide to enabling snapping capabilities to buildable objects. It is advised that the objects should be added as buildable objects before enabling snapping. There are two main procedures which must be done to make an object snappable:


 * 1) Adding snap points in the respective SCENE files
 * 2) Modifying respective entry in BASEBUILDINGTABLE.MBIN

For the purpose of demonstrating in a more practical form, we shall assume the case of adding snapping capabilities to two different buildable objects via custom snap points.

Adding snap points in the respective SCENE files
Open the SCENE file which you wish to enable snapping to. A basic snap point data structure is as such: '''                             </Property>   </Property>  <Property name="Name" value=" NullSnap_1 " /> <Property name="Type" value="LOCATOR" /> <Property name="Transform" value="TkTransformData.xml"> <Property name="TransX" value="0" /> <Property name="TransY" value="0" /> <Property name="TransZ" value="0" /> <Property name="RotX" value="0" /> <Property name="RotY" value="0" /> <Property name="RotZ" value="0" /> <Property name="ScaleX" value="1" /> <Property name="ScaleY" value="1" /> <Property name="ScaleZ" value="1" /> </Property> <Property name="Attributes" /> <Property name="Children" /> </Property> </Property> </Property>'''

Understanding SnapPoint data structure
The SnapPoint data structure contains a parent LOCATOR, with all snap point that belongs to the group as the children of the parent LOCATOR.

Below are descriptions of different parts within the structure:

SnapPoint{_[Name]}{_[Counter]}:

The parent LOCATOR to the entire snap point group. If any one of the children snap points in the group is used, all the other snap points in the the group will be disabled.

Objects with multiple snap points which will not interfere with each other requires separate SnapPoint groups. This LOCATOR's position and orientation in the scene also define its visual snap point representation in the game. The {_[Name]} and {_[Counter]} are the descriptions of the SnapPoint group. It has not been tested whether the parent name will affect its functionality, but it is advised to add a description to the SnapPoint name, such as SnapPoint_Example_1 or SnapPoint_Front to clarify how it's being used.

[Name]_In{_[Counter]}, [Name]_Out{_[Counter]}:

The children LOCATOR of the SnapPoint{_[Name]}{_[Counter]} LOCATOR parent. These define the position, relative to the object's origin point, of where the object will be placed when snapped to the other object.

[Name]_In and [Name]_Out are the defining values that decide which snap points the object can snap to. An object with a snap point can only be snapped to another object with a snap point carrying the same name. In addition, an Out snap point can only be snapped onto an In (capital 'i', lower case 'n')snap point, and not vice versa.

{_[Counter]} is the counter, likely used for differentiating LOCATORs that would otherwise have the same name. For example, a snap point with the name Example_In_1 can be snapped to Example_Out_3, but not Example_In_2 or Cuberoom_Out. Multiple snap points like these can be made children of one single parent SnapPoint LOCATOR.

NullSnap{_[Name]}{_[Counter]}:

The exact functionality of this LOCATOR is not researched. However, the NullSnap LOCATOR is requisite to make a SnapPoint group functional. Again, {_[Name]} and {_[Counter]} are the descriptions and do not have practical functionality, but is still suggested to have one.

An entry after modification can look like this:

Object A:    '''<Property value="TkSceneNodeData.xml"> <Property name="Name" value="SnapPoint_Server_Top" /> <Property name="Type" value="LOCATOR" /> <Property name="Transform" value="TkTransformData.xml"> <Property name="TransX" value="0" /> <Property name="TransY" value="0.365" /> <Property name="TransZ" value="0" /> <Property name="RotX" value="0" /> <Property name="RotY" value="0" /> <Property name="RotZ" value="0" /> <Property name="ScaleX" value="1" /> <Property name="ScaleY" value="1" /> <Property name="ScaleZ" value="1" /> </Property> <Property name="Attributes" /> <Property name="Children"> <Property value="TkSceneNodeData.xml"> <Property name="Name" value="Server_In_Top" /> <Property name="Type" value="LOCATOR" /> <Property name="Transform" value="TkTransformData.xml"> <Property name="TransX" value="0" /> <Property name="TransY" value="0" /> <Property name="TransZ" value="0" /> <Property name="RotX" value="0" /> <Property name="RotY" value="0" /> <Property name="RotZ" value="0" /> <Property name="ScaleX" value="1" /> <Property name="ScaleY" value="1" /> <Property name="ScaleZ" value="1" /> </Property> <Property name="Attributes" /> <Property name="Children" /> </Property> <Property value="TkSceneNodeData.xml"> <Property name="Name" value="NullSnap_Top" /> <Property name="Type" value="LOCATOR" /> <Property name="Transform" value="TkTransformData.xml"> <Property name="TransX" value="0" /> <Property name="TransY" value="0" /> <Property name="TransZ" value="0" /> <Property name="RotX" value="0" /> <Property name="RotY" value="0" /> <Property name="RotZ" value="0" /> <Property name="ScaleX" value="1" /> <Property name="ScaleY" value="1" /> <Property name="ScaleZ" value="1" /> </Property> <Property name="Attributes" /> <Property name="Children" /> </Property> </Property> </Property>''' Notice the Server_In_Top name, which will only snap to Server_Out points.

Object B:    '''<Property value="TkSceneNodeData.xml"> <Property name="Name" value="SnapPoint_Server_Bottom" /> <Property name="Type" value="LOCATOR" /> <Property name="Transform" value="TkTransformData.xml"> <Property name="TransX" value="0" /> <Property name="TransY" value="0" /> <Property name="TransZ" value="0" /> <Property name="RotX" value="0" /> <Property name="RotY" value="0" /> <Property name="RotZ" value="0" /> <Property name="ScaleX" value="1" /> <Property name="ScaleY" value="1" /> <Property name="ScaleZ" value="1" /> </Property> <Property name="Attributes" /> <Property name="Children"> <Property value="TkSceneNodeData.xml"> <Property name="Name" value="Server_Out_Bottom" /> <Property name="Type" value="LOCATOR" /> <Property name="Transform" value="TkTransformData.xml"> <Property name="TransX" value="0" /> <Property name="TransY" value="0" /> <Property name="TransZ" value="0" /> <Property name="RotX" value="0" /> <Property name="RotY" value="0" /> <Property name="RotZ" value="0" /> <Property name="ScaleX" value="1" /> <Property name="ScaleY" value="1" /> <Property name="ScaleZ" value="1" /> </Property> <Property name="Attributes" /> <Property name="Children" /> </Property> <Property value="TkSceneNodeData.xml"> <Property name="Name" value="ServerBase_In" /> <Property name="Type" value="LOCATOR" /> <Property name="Transform" value="TkTransformData.xml"> <Property name="TransX" value="-0.08" /> <Property name="TransY" value="0" /> <Property name="TransZ" value="-0.08" /> <Property name="RotX" value="0" /> <Property name="RotY" value="0" /> <Property name="RotZ" value="0" /> <Property name="ScaleX" value="1" /> <Property name="ScaleY" value="1" /> <Property name="ScaleZ" value="1" /> </Property> <Property name="Attributes" /> <Property name="Children" /> </Property> <Property value="TkSceneNodeData.xml"> <Property name="Name" value="NullSnap_Bottom" /> <Property name="Type" value="LOCATOR" /> <Property name="Transform" value="TkTransformData.xml"> <Property name="TransX" value="0" /> <Property name="TransY" value="0" /> <Property name="TransZ" value="0" /> <Property name="RotX" value="0" /> <Property name="RotY" value="0" /> <Property name="RotZ" value="0" /> <Property name="ScaleX" value="1" /> <Property name="ScaleY" value="1" /> <Property name="ScaleZ" value="1" /> </Property> <Property name="Attributes" /> <Property name="Children" /> </Property> </Property> </Property>''' Note that multiple snap points can be put in one SnapPoint group as children, namely Server_Out_Bottom and ServerBase_In.

The positions and orientations of these snap points will be used in game as the positions and orientations where the object will be placed relative to the object which it is snapping to.

Modifying entry in BASEBUILDINGTABLE.MBIN
Open BASEBUILDINGTABLE.MBIN and navigate to the entry of the object you have added snap points to.

Enabling snapping
The "Type" value controls the snapping capabilities of an object, provided the object has snap point LOCATORs in them. The GcBaseBuildingObjectTypes struct list has the following values, providing different snapping abilities: Therefore, if the object is desired to be snapped and to be placed outdoors, BuildingFoundation should be used.
 * Building: cannot be placed on terrain by itself, and can and must be placed by snapping onto other objects, can only be placed outdoors.
 * BuildingFoundation: can be placed on terrain ,and actively snaps to other objects, but can't be placed indoors.
 * BuildingDecoration: can be placed on terrain if the "Biome" value matches the current biome (and not "All"), and can and must be placed by snapping onto other BuildingFoundation and BuildingDecoration objects indoors.
 * Decoration: can be placed on terrain, indoors and outdoors surfaces by itself, other objects can be snapped to the object, but it cannot actively snap to other objects.
 * Foundation: can snap to and be snapped on by other objects, cannot be placed indoors.

Enabling snapping for custom objects indoors
As seen above, there is no Building Object type which can be placed freely indoors while having snapping capabilities. To allow this functionality, two procedures need to be done:
 * 1) Making a "Decoration" object with snap points.
 * 2) Configuring the snappable object in BASEBUILDINGTABLE.MBIN.

"Decoration" object with snap points
Simply add an object as a "base" of the snappable object with snap points, this provides a mobile snap point which can be placed indoors.

Configuring the snappable object in BASEBUILDINGTABLE.MBIN
Add matching snap points to the object SCENE. Change the "Type" value of the object into "BuildingDecoration" as objects of this type can be snapped onto other objects indoors, and can be affected by the DecorationType value, unlike other snappable object types.

Next, change the "DecorationType" value to "Plant", this enables the object to be snappable to Decoration objects indoors. Now the snappable object will be able to be snapped onto the Decoration object which you created.