.. _expressions:

Expressions
-----------

Шаблонизатор поддерживает выражения, с помощью которых можно создавать сложные связи между фигурами или изменять значения
переменных "на лету", передавая их в параметр фигуры.

Ссылка на другой элемент шаблона
================================

Если у фигуры указать параметр ``id`` то можно будет ссылаться на его параметры из других фигур.

.. note:: Фигура должна быть определена до обращения к ней

Следующий пример показывает как создать простую зависимость второго прямоугольника от размера и положения первого:

.. code-block:: json

    {
      "shapes": [

        {
          "": "определяем первый прямоугольник",
          "type": "rect", "x": 0, "y": 0,
          "width": 100, "height": 100,
          "id": "rect_1"
        },

        {
          "": "определяем второй прямоугольник",
          "type": "rect",
          "": "параметр Х ссылается на такой же параметр другой фигуры.",
          "x": "rect_1.x",
          "": "параметр Y ссылается на параметр высоты другой фигуры",
          "y": "rect_1.height"
        }
      ]
    }

Для того чтобы ссылаться на свои параметры используйте специальное слово ``self``. Например ``"x": "self.y"``.

Ссылка на переменные
====================

С помощью символа ``$`` можно ссылаться на значения из контекста или специальные значения, которые генерируются шаблонизатором.

В этом примере мы ссылаемся на цвет из переменных контекста.

.. code-block:: json

    {
      "variables": {
        "backdrop_color": [0, 0, 0, 100]
      },
      "shapes": [
        {
          "type": "rect", "x": 0, "y": 0, "width": 100, "height": 100,
          "color": "$backdrop_color"
        }
      ]
    }

Ссылка на родительский объект
=============================

Любая фигура имеет родительский объект. Если он не задан явно, то родительским объектом будет исходный кадр.
Координаты рассчитываются относительно родительского объекта.

.. note:: Такие поля как ``left``, ``right``, ``top`` и ``bottom`` возвращают глобальные координаты вне зависимости от родительского объекта.

Для ссылки на параметры родительского объекта используйте имя ``parent``

.. note:: Нельзя создать фигуру указав ей параметр ``id`` равный ``"parent"`` или ``"self"``. Это зарезервированы слова.

В следующем примере для второй фигуры указан родительский объект. Параметр ``"width"`` ссылается на ширину родительского объекта.
Значение будет автоматически измениться если изменить родительский объект.

.. code-block:: json

    {
      "shapes": [
        {
          "type": "rect", "x": 0, "y": 0,
          "width": 100, "height": 100,
          "id": "rec1"
        },
        {
          "type": "rect", "parent": "rec1",
          "x": 0, "y": 0,

          "":"указываем ширину равную ширине родительского объекта",
          "width": "parent.width",
          "height": 50
        }
      ]
    }


Сложные выражения
=================

Шаблонизатор поддерживает сложные выражения, которые транслируются в Python через ``eval``, подставляя значения переменных.
Если в выражении есть какие-либо операции, а не только ссылка на другой параметр, то его следует начинать со знака ``=``.

В следующем шаблоне второй прямоугольник всегда в 2 раза меньше родителя и вписан в его центр.

.. code-block:: json

    {
      "shapes": [
        {
          "type": "rect",
          "x": 0, "y": 0,
          "width": 200, "height": 200,
          "id": "rec1"
        },
        {
          "type": "rect", "parent": "rec1",
          "x": 0, "y": 0,
          "align_h": "center", "align_v": "center",
          "width": "=parent.width/2", "height": "=parent.height/2",
          "color": "red"
        }
      ]
    }

В сложных выражениях можно точно так же использовать переменные.

**Внимание!** При распаковке переменных в место имени переменной подставляется её значение. Если вы пишете экспрешен со
строкой то нужно добавлять кавычки.

.. code-block:: json

    {
    "variables": {
        "name": "some_name"
        },
    "shapes": [
        {
            "type": "label", "text": "hello",
            "enabled": "='$name'=='name1'"
        }
        ]
    }

В этом примере переменная ``$name`` дополнительно берётся в кавычки, чтобы она определилась как строка.

Второй способ создавать выражения - писать однострочный код на Python. Для этого выражение нужно обернуть в бектики " ` "
и также начинать выражение с символа ``=``.

Формат такой: ```=expression```

.. note:: В одной строке может быть несколько выражений.

.. code-block:: json

   {
    "variables": {
        "entity_path": "assets/characters/char1"
        },
    "shapes": [
        {
            "type": "label", "text": "`='$entity_path'.split('/')[-2]` / `='$entity_path'.split('/')[-1]`"
        }
        ]
    }

В значении параметра ``text`` есть два выражения. В результате мы получим такой текст: ``characters / char1``.

Аналогичный результат можно получить таким выражением:

.. code-block:: json

   {"type": "label", "text": "`=' / '.join('$entity_path'.split('/')[-2:])`"}


Переменные в ``variables`` могут ссылаться на переменные из ``defaults`` и наоборот

.. code-block:: json

   {
    "defaults": {
      "value": 2
    },
    "variables": {
      "value2": "=$value * 2"
    }
   }



Специальные переменные
======================

Шаблонизатор автоматически добавляет в контекст несколько переменных

source
    Ссылка на исходное изображение, поверх которого производится рендер шаблона. С помощью этой переменной можно ссылаться
    на исходную картинку в фигуре ``image`` в параметре ``source``.

.. code-block:: json

    [
        {"type": "image", "source": "$source"}
    ]

source_width
    Ширина исходной картинки

source_height
    Высота иходной картинки

source_aspect
    Отношение высоты исходной картинки к её ширине `(height/width)`

unit
    Одна сотая от высоты картинки. Может использоваться как множитель к числам.

point
    Автоматически рассчитываемое значение которое для любого размера исходного кадра будет иметь примерно одинаковую относительную величину.


Unit и Point
============

В выражениях есть возможность записывать числа с помощью относительных величин от размера картинки.
В переменных эти значения доступны в под именами ``"$unt"`` и ``"$pnt"``.

Значение ``unit`` является короткой записью выражения ``source_height / 100``, то есть одна сотая часть от высоты
исходного изображения, или 1%.

Этот параметр можно использовать в записи чисел в виде суффикса "u" для чисел. Например: ``10u``, ``2.5u``, ``50u``.

.. code-block:: json

    [
        {"type": "label", "text": "$unt", "font_size": "10u"}
    ]

Данный код создаст текст в котором будет записан размер одного "юнита" в пикселях.
Высота этого текста всегда будет 10% от высоты картинки.

Значение ``point`` рассчитывается учитывая и высоту и ширину. В итоге получаем примерно одинаковый относительный
размер для любого изображения и не экстремального соотношения сторон.

Формула расчёта: ``round(0.01*sqrt(width*height), 3)``.

Этот параметр используется в виде суффикса "p". Например: ``10p``, ``2.5p``, ``50p``.

Эти переменные полезно использовать для адаптивных шаблонов, которые могут рендериться на картинках разного размера.

