Настройка графических элементов в программе Hobdrive

В первой части было рассказано как разместить нужные нам датчики на экране программы в нужном нам порядке, поменять размеры, занять пару тройку ячеек и т.д. На этот раз будем рассматривать графические элементы, так сказать украшательства.
Что бы не ломать логики, продолжать будем на том же примере, что и в первой части.
Графическое оформление программы Hobdrive


Для начала об ограничениях программы, которые необходимо учитывать. 
- Размер любого графического элемента не ограничивается размером поля датчика. То есть если рисунок датчика D10 сделать достаточно большим, то он сможет накрыть весь экран.
- Слои. Все графические элементы как бы находятся каждый в своем слое. А слои, лежат стопкой. Самый нижний слой, это слой первого датчика, самый верхний слой - последний датчик. Из этого следует, что изображение лежащее в датчике D5, если оно выходит за пределы границ своей ячейки, накроет изображения датчиков D1, D2, D4. Так же изображение D5 может накрыть и вышестоящие ячейки, но только если там нет своих картинок.  
Для лучшего понимания, картинка
Графическое оформление программы HobdriveИз картинки должно быть понятно, что первая картинка(оранжевая), накрывает только себя, вторая(синяя), себя и первую, третья(красная) накрывает вторую, и т.д. Пятая, синяя накрыть может все предыдущие. но в примере для этого у нее не хватает размеров. О размерах ниже. 

Все изображения должны находиться в папке images внутри папки hobdrive. Можно создавать подпапки. В нашем примере это будет папка pic. Так что дальше путь к изображению будет иметь вид images/pic/название_файла_картинки.расширение
Настройки вывода изображений, могут находиться в двух файлах, user.gauge или user.layout. Мне удобней работать с одним файлом, так что снова user.layout. 

Статические изображения. Или изображения на которые не влияют показания датчиков. Являются просто декораторами.
В это файле уже есть наши датчики в виде строк <item id="TripTime"/>

  1. <item id="TripTime"
  2. decorator-a="image"
  3. a-image-path="images/pic/8.png"
  4. a-image-zorder="bottom"
  5. a-image-align="center"
  6. a-image-scale="2"
  7. a-image-rotate="17"
  8. a-image-rotate-align="top"
  9. a-image-aspect="false"
  10. />

Первая строка и девятая у нас были, точнее это была одна строка которую мы "разорвали" и вставили в разрыв описание датчика.
Вторая строка - использовать декоратор с префиксом "a"
Третья - путь до файла изображения относительно папки hobdrive
Четвертая - размещение изображение над показаниями (top) датчика или под (bottom)
Графическое оформление программы Hobdrive bottom

Пятая - выравнивание изображения относительно поля датчика. Значения top, bottom, left, right, vcenter, hcenter, center. Если не использовать эту строку,  геометрические центры изображения и поля датчика совпадут.
center
В случаях top, bottom, left, right, происходит "пристегивание" соответствующих сторон изображения и поля датчика. Как пример top. Хотя этот же результат будет и при переменной left
left
vcenter, hcenter, center  - соответственно совмещать вертикальные центры, горизонтальные и оба центра. 
Что бы избежать этого, необходимо прописать два значения через запятую, например a-image-align="top, hcenter". То есть пристегнуть изображение к верху и выровнять по центру в горизонтали.
12

Шестая строка - масштаб изображения относительно размера поля датчика. Можно писать десятичные значения. Разделитель между целым и дробью - точка.

Седьмая - вращение изображения. Значение прописывать в градусах.
Восьмая - центр вращения изображения. Все точно так же как и в  image-align
Девятая - значение false заставляет принять изображение пропорции поля датчика. Значение true сохраняет "родные" пропорции изображения. на примере оригинал изображения с равными сторонами
false true

 
Практика. Накроем "рамкой" весь экран.
Делаем скриншот программы, загоняем в графический редактор и смотрим размеры всего поля датчиков. У меня получилось 1280*594 пикселя. Рисуем рамку с таким же разрешением, и в формате png для прозрачности. Кладем изображение в папку image и дальше настраиваем датчик. Так как изображение должно накрыть все поле, а у нас все по слоям, если еще не забыли, то помещаем его в самый последний датчик.  Настраиваем датчик. Для этого понадобиться всего 5 строк. Третья строка  - путь к изображению. Четвертая - пристегивание картинки к нижней и правой границам. Масштабироваться изображение будет в противоположные стороны.
Последняя строка, это масштаб. С ним придется повозиться. 

<item id="TripTime"
decorator-r="image"
r-image-path="images/pic/bk.png"
r-image-align="bottom, right"
r-image-scale="3.535"/>
Получилось это
Графическое оформление программы Hobdrive
На скриншоте есть огрехи, но я не ставил цель сделать идеал, главное донести принцип.


Динамические декораторы. Изображения которые меняются или сами или меняют свое положение в зависимости от показания датчиков.

В принципе ничего нового относительно статических изображений нет. Единственное изменение, это то, что атрибуты image-path=" "и image-rotate=" " могут получать значения из датчиков.

a-image-path='$${ Sensor_Value }.png' смена изображений.
Тут все и как прежде. С начала указываем путь к изображениям - a-image-path="images/pic/", но вместо имени файла пишем переменную датчика $${Sensor_Value}.png. Должно получится так -  a-image-path="images/pic/$${Sensor_Value}.png. Если показания нашего датчика равны 1, то нарисуется изображение 1.png, если значение 2, то соответственно  2.png. Внутри {} над показаниями датчика можно выполнять арифметические действия. Например $${Sensor_Value - 75}.png, Получили значение датчика и отняли от него 75. 

a-image-rotate='$${ Sensor_Value }' -  вращение изображений.
Опять все тоже самое, но происходит вращение изображения  в зависимости от показаний датчика. Арифметические действия также доступны.
Будем делать стрелку температуры ОЖ. Стрелку рисуем по своему вкусы и кладем файл в папку с изображениями.
Что бы долго не мудрить, вот код-

<item id="CoolantTemp"
decorator-i4="image"
i4-image-zorder="top"
i4-image-path="images/pic/arr9.png"
i4-image-rotate='$${Sensor_Value}'
i4-image-scale="1.5"
i4-image-align="top,hcenter"
/>

Но при таком коде, мы получаем довольно скучное изображение стрелки. Она просто лежит при показаниях датчика равным нулю или при отсутствии показаний вообще. Это "нулевой" угол.
Графическое оформление программы Hobdrive
для более понятного объяснения дальнейших действий на рисунке ниже некоторые понятия,
Графическое оформление программы HobdriveКрасная окружность, это окружность вокруг центра которой вращается стрелка.
Черный отрезок - дефолтное положение стрелки при нулевом показании датчика. 
Синий отрезок - начальное положение стрелки, которое нам необходимо получить по тем или иным соображениям.
Зеленый отрезок - конечное положение стрелки при значениях датчика от нужной нам величины и больше. К примеру это температура 100 градусов и выше. Стрелка займет это положение при температуре 100Градусов и дальше двигаться не будет, даже если температура поднимется выше 100 градусов.
Угол между синим и зеленым отрезком, это рабочий угол стрелки.


 

Самое сложное. это когда изображению надо задать "стартовый и (или) финишный угол, а так же когда угол поворота не равен разнице между начальными и конечными показаниями датчиков. К примеру температура ОЖ отдает показания от 0 до 110, а необходимо, что бы стрелка перемещалась на угол 70 градусов и показывала значения от 55 до 110 градусов Цельсия.
берем нашу i4-image-rotate='$${Sensor_Value}'. Что бы получить стартовое положение как на рисунке, вставляем значение угла между черным отрезком и синим, и с учетом движения стрелки против часовой, значение это отрицательное и в моем примере равно 26 градусам. Получаем i4-image-rotate='$${ - 26 (Sensor_Value)}' Если так и оставить, то при значении датчика температуры в 10 градусов, стрелка сдвинется со своего стартового положения на значение датчика, то есть на 10 градусов.  Мне это не нужно, будем устанавливать минимальное значение показаний датчика после которого стрелка начнет двигаться. Сразу установим и максимальное значение, после которого стрелка замирает. И еще необходим угол межну начальным положением стрелки и конечным, у меня он равен 115 градусов.
В итоге получится так - i4-image-rotate='$${ -26 - ((Max(Min(115; Sensor_Value);55) - 55)*115/60 )}'
Расшифровка
-26 - начальное положение стрелки 
115 - максимальное значение, после которого движение стрелки прекращается.
55 - минимальное значение датчика до достижения которого стрелка не двигается.
- 55 - снова минимальное значение датчика до достижения которого стрелка не двигается. 
115 - угол поворота стрелки между стартовым и конечным углами.
60 - разница между максимальным и минимальным значениями. в нашем случае от 55 до 115 градусов.

На этом всё) Дальше только частные случаи.

ПыСы
Красивые картинки это конечно хорошо, но во первых это занимает ресурсы вашего устройства, а во вторых Хобдрайв не обладает "инерционностью" при выводе изображений. Стрелка для температуры ОЖ будет смотреться вполне вменяемо, так как показания датчика не меняются в больших диапазонах за короткое время. Но уже стрелка тахометра будет выглядеть не столь красиво. Только что стояла на 1000 оборотах и вот уже на 3000. И проблема даже не в скорости передачи данных. а в том, что в отличии от обычного аналогового тахометра, который при любом раскладе все равно пройдет путь от 1000 до 2000, стрелке в Хобдрайве этого делать необязательно, и она этого не делает.

 Как у меня вышло в итоге?

Вот так)
Hobdrive внешний вид

UPD.
Отказался от стрелок везде кроме спидометра, вышло так
Screenshot 2016-07-07-10-32-12

Архив первого варианта - hobdrive.zip
Архив второго варианта - hobdrive2.zip
файлы user.layout в корень программы, изображения в папку hobdrive\images