> For the complete documentation index, see [llms.txt](https://jorge-jgnz94.gitbook.io/hptk/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jorge-jgnz94.gitbook.io/hptk/master/customization/modules.md).

# Modules

## Introduction

This section seeks to act as guide to implement new HPTK modules. Structure of HPTK modules is described in detail [here](/hptk/master/customization/modules.md).

HPTK modules can be child of:

* AvatarModel.
* BodyModel.
* PartModel (HandModel or FingerModel).

## Requirements

Custom HPTK modules must fulfill the following requirements:

* Follow MVC pattern.
* Overriden functions must call their base function.
* View must expose only safe operations.
  * It shouldn't be possible to make the module fail from the view.
* View must hide the reference to its model.
* Controller must self-register in its parent's registry as soon as possible (Awake).
* Controller must search the reference to the other 2 components if missing.
* Controller shouldn't update if its GameObject is disabled.
* Model must work with only the reference to its parent module.
  * Numbers and strings must have a default value.
  * Missing references must be searched in the scene automatically if they are missing.
  * If some mandatory references or value could not be found, a warning or error message should be logged and the module should be automatically disabled.

## Code skeletons

Model:

```csharp
public class CustomModel : HPTKModel
{
    // Parent can also be AvatarModel, BodyModel, PartModel or FingerModel
    public HandModel hand;

    public int someValue = 5;
    public Transform someRef;
    
    CustomController _controller;
    public CustomController controller
    {
        get
        {
            if (!_controller)
            {
                _controller = GetComponent<CustomController>();
                if (!_controller) _controller = gameObject.AddComponent<CustomController>();
            }
    
            return _controller;
        }
    }
    
    CustomView _view;
    public CustomView view
    {
        get
        {
            if (!_view)
            {
                _view = GetComponent<CustomView>();
                if (!_view) _view = gameObject.AddComponent<CustomView>();
            }
    
            return _view;
        }
    }
    
    public override void Awake()
    {
        base.Awake();
        
        if (!someRef)
        {
            // Find someRef automatically
        }
    }
}
```

View:

```csharp
[RequireComponent(typeof(CustomModel))]
public class CustomView : HPTKView
{
    CustomModel model;

    public HandView hand { get { return model.hand.specificView; } }

    // Public properties
    
    // Public events
    
    // Public functions

    public override sealed void Awake()
    {
        base.Awake();
        model = GetComponent<CustomModel>();
    }
}
```

Controller:

```csharp
[RequireComponent(typeof(CustomModel))]
public class CustomController : HPTKController
{
    [ReadOnly]
    public CustomModel model;

    public override void Awake()
    {
        base.Awake();
        model = GetComponent<CustomModel>();
        SetGeneric(model.view, model);
        
        // ...
    }
    
    public void OnEnable()
    {
        model.hand.registry.Add(this);
    }
    
    public void OnDisable()
    {
        model.hand.registry.Remove(this);
    }

    public override void ControllerStart()
    {
        base.ControllerStart();
        
        // ...
    }
    
    public override void ControllerUpdate()
    {
        base.ControllerUpdate();
  
        // ...
    }
}
```
