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 value="TkSceneNodeData.xml">**
      <Property name="Name" value="SnapPoint\_Example\_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 value="TkSceneNodeData.xml">

          <Property name="Name" value="Example\_In\_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 value="TkSceneNodeData.xml">

          <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:

* **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.

Therefore, if the object is desired to be snapped and to be placed outdoors, **BuildingFoundation** should be used.

### 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.