Developer Guide

The following is a set of guidelines for creating new systems as extension to current ones and some information about ground architecture of the ATF assets.

Creating new system

Here is some base steps for creating and integrating some new system.

Initializer

The AtfInitializer class is for instantiating automatically all MonoSingleton<T> instances as Initializer game object child that are marked by AtfSystem attribute.

In context of ATF it is used to instantiate all main systems described below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
using ATF.Scripts.DI;
using ATF.Scripts.Helper;

namespace MyLovely.Namespace
{
    [AtfSystem]
    public class MyNewSystem : MonoSingleton<MyNewSystem>
    {
        ...
    }
}

If you now enter the Play Mode the AtfInitializer class will instantiate as child of itself your newly created class MyNewSystem.

DI Container

DI Container stands for Dependency Injection Container. It’s a common method to implement the Dependency Inversion Principle (DIP) of SOLID principles. Usage:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
using ATF.Scripts.DI;
using ATF.Scripts.Helper;

namespace MyLovely.Namespace
{
    public interface IMySystem {
       ...
    }

    [AtfSystem]
    [Injectable]
    public class MyNewSystemA : MonoSingleton<MyNewSystemA>, IMySystem
    {
        ...
    }

    [AtfSystem]
    [Injectable]
    public class MyNewSystemB : MonoSingleton<MyNewSystemB>
    {
        ...
    }

    [AtfSystem]
    [Injectable]
    public class MyNewSystemC : MonoSingleton<MyNewSystemC>, IMySystem
    {
      [Inject(typeof(MyNewSystemA))]
      public static readonly IMySystem SYSTEM_A;

      [Inject(typeof(MyNewSystemB))]
      public static readonly MyNewSystemB SYSTEM_B;

        ...
    }
}

The main attributes here are Injectable and Inject. First is used to appear in queue to dependency injection. Second is used with one required parameter of Type class. The purpose of the second is to mark field of class that is to be populated by instance of class that has type Type via DI Container.

Note

Every ATF system has Injectable and AtfSystem attributes so you can use them in your own systems.

Platform Diagram

Platform diagram

Every block at the ATF platform diagram above is an isolated class group:

  • Custom Unity Input Module – an abstraction that combines input management;
  • Custom Input API – module that calls native methods on an input request;
  • Custom BaseInput – an entity that is an implementation of a data flow processing object across a bridge combining static methods for intercepting/simulating input and wrapped events;
  • Storage – a group of classes that is responsible for storing and manipulating recorded actions;
  • Recorder – a group of classes that is responsible for recording actions;
  • Custom Editor UI – a system of custom windows for managing all processes;
  • PlayerPrefs Save/Load Module – system for implementing the module for saving / loading recorded actions based on the standard PlayerPrefs class;
  • Dictionary based Module – implementation of the recorded action store abstraction based on the Dictionary data structure;
  • Queue based Recorder Module – implementation of the module responsible for recording actions based on the Queue data structure with RLE-compression;

Main systems

The next several titles are describing the base system interfaces of the ATF.

Some of them implement the following interface describing cursor get and set methods.

To check the current realisations just visit our github page.

1
2
3
4
5
6
7
namespace ATF.Scripts.Helper {
    public interface IAtfGetSetRecordName
    {
        string GetCurrentRecordName();
        void SetCurrentRecordName(string recordName);
    }
}

Recorder System

The Recorder System is serving as arbitrator. It’s current realisation based on classic state machine. And it implements the following interface.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using ATF.Scripts.Helper;

namespace ATF.Scripts.Recorder
{
    public interface IAtfRecorder : IAtfGetSetRecordName
    {
        bool IsRecording();
        bool IsPlaying();

        bool IsRecordingPaused();
        bool IsPlayPaused();

        bool IsInputStopped();

        void PlayRecord();
        void PausePlay();
        void ContinuePlay();
        void StopPlay();

        void StartRecord();
        void PauseRecord();
        void ContinueRecord();
        void StopRecord();

        void SetRecording(bool value);
        void SetPlaying(bool value);
        void SetRecordingPaused(bool value);
        void SetPlayPaused(bool value);
        void SetInputStopped(bool value);

        void Record(FakeInput kind, object input, object fakeInputParameter);
        object GetLastInput(FakeInput kind, object fakeInputParameter);
        void SetLastInput(FakeInput kind, object realInput, object fakeInputParameter);
    }
}

Action Storage System

The Action Storage System is a core of the ATF. It implements the following interface and stores recorded actions in format of generic type Dictionary<string, Dictionary<FakeInput, Dictionary<object, AtfActionRleQueue>>>.

Where string - is name of the record, FakeInput is enum described below, object - is parameter of the input and AtfActionRleQueue is basic queue data structure but with RLE-compression of the elements.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System.Collections.Generic;
using ATF.Scripts.Helper;
using ATF.Scripts.Storage.Utils;
using UnityEditor.IMGUI.Controls;

namespace ATF.Scripts.Storage.Interfaces
{
    public interface IAtfActionStorage : IAtfGetSetRecordName
    {
        object GetPartOfRecord(FakeInput kind, object fakeInputParameter);
        void Enqueue(string recordName, FakeInput kind, object fakeInputParameter, AtfAction atfAction);
        AtfAction Dequeue(string recordName, FakeInput kind, object fakeInputParameter);
        AtfAction Peek(string recordName, FakeInput kind, object fakeInputParameter);
        bool PrepareToPlayRecord(string recordName);
        void ClearPlayStorage();
        void SaveStorage();
        void LoadStorage();
        void ScrapSavedStorage();
        List<TreeViewItem> GetSavedRecordNames();
        List<TreeViewItem> GetCurrentRecordNames();
        List<TreeViewItem> GetCurrentActions(string recordName);
        List<TreeViewItem> GetSavedActions(string recordName);
        void Export(string fullPath);
        void Import(string fullPath);
    }
}

FakeInput enum is the following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public enum FakeInput {
    NONE,
    ANY_KEY_DOWN,
    ANY_KEY,
    GET_AXIS,
    GET_AXIS_RAW,
    GET_BUTTON,
    GET_BUTTON_DOWN,
    GET_BUTTON_UP,
    GET_KEY,
    GET_KEY_DOWN,
    GET_KEY_UP,
    GET_MOUSE_BUTTON,
    GET_MOUSE_BUTTON_DOWN,
    GET_MOUSE_BUTTON_UP,
    GET_TOUCH,
    MOUSE_POSITION,
    TOUCH_COUNT,
    MOUSE_SCROLL_DELTA,
    TOUCH_SUPPORTED,
    COMPOSITION_STRING,
    IME_COMPOSITION_MODE,
    COMPOSITION_CURSOR_POS,
    MOUSE_PRESENT,
    SIMULATE_MOUSE_WITH_TOUCHES
}

And it’s represent any kind of input that we can acquire from Input class.

Packer System

The following interface define how to pack and unpack storage data into serializable Slot class.

The current realisation of it is using greedy algorithm.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
using System.Collections.Generic;
using ATF.Scripts.Storage.Utils;
using UnityEngine;

namespace ATF.Scripts.Storage.Interfaces
{
    public interface IAtfPacker
    {
        List<Record> Pack(Dictionary<string, Dictionary<FakeInput,
           Dictionary<object, AtfActionRleQueue>>> input);
        Dictionary<string, Dictionary<FakeInput, Dictionary<object,
           AtfActionRleQueue>>> Unpack(Slot slot);
        string ValidatePacked(List<Record> packed);
    }
}

Action Storage Saver System

Because of the potential need in saving storage data in different places (ex. file system, PlayerPrefs class, etc.) this interface was created. The current realisation uses PlayerPrefs class. You can always expand this on file system for example by implementing this interface with specific file system API usage.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
using System.Collections;
using System.Collections.Generic;
using ATF.Scripts.Helper;
using UnityEditor.IMGUI.Controls;

namespace ATF.Scripts.Storage.Interfaces
{
    public interface IAtfActionStorageSaver : IAtfGetSetRecordName
    {
        void SaveRecord();
        void LoadRecord();
        void ScrapRecord();

        IEnumerable GetActions();
        void SetActions(IEnumerable actionEnumerable);
        List<TreeViewItem> GetSavedNames();
        List<TreeViewItem> GetSavedRecordDetails(string recordName);
        void ExportFile(string fullPath);
        void ImportFile(string fullPath);
    }
}

Integrator System

This interface define methods for automatic integrator system that allow preparing and saving group of selected source files and integrating them.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
using System.Collections.Generic;
using ATF.Scripts.Helper;

namespace ATF.Scripts.Integration.Interfaces
{
    public interface IAtfIntegrator : IAtfGetSetRecordName
    {
        void SetUris(IEnumerable<string> filePaths);
        void Integrate();
        void IntegrateAndReplace();
        void IntegrateAll();
        void SaveUris();
        IEnumerable<string> LoadUris();
    }
}

Note

This current realisations might be changed during the development of the ATF, so in this page only interfaces are illustrated. SOLID rules.