Log in
Перейти к содержимому
Для публикации в этом разделе необходимо провести 1 боёв.
MatroseFuchs

[UB2] Документация по Unbound 2.0

В этой теме 20 комментариев

Рекомендуемые комментарии

5 070
[LESTA]
Разработчик
1 323 публикации
7 439 боёв

Системный уровень

Вычисляемые выражения

Unbound предоставляет возможность работать с так называемыми вычисляемыми выражениями (не путать с s-expressions). Это выражения, которые вычисляются на этапе исполнения. Содержимое выражения заключено в " ". Для удобства будем называть их просто expression, если речь будет идти об s-expressions, то это будет явно выделено. 

Выражения предназначены для несложной обработки данных, формирования значения свойств или параметров вызова метода. В выражениях можно использовать variables и events, объявленные в scope, а также числовые, строковые, логические литералы и использовать операторы.

(tf
    (text = "' ' + tankmanName + ' — '")
)
(mc forsage_progress_bar
	(style (position  = "absolute"))
	...
)

Такие выражения будут вычислены при исполнении верстки, непосредственно при вызове методов. Выражение можно использовать как для вызова метода, как пример gotoAndStop, так и вызове s-expression как пример  (element …)

(def element AircraftForsage(activeSquadron:number) layout=true
	(scope
		(event evForsageFinishedAnimate)
	...
)

 

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

 

Т.к за основу взят синтаксис action script, в выражениях можно использовать соответствующие операторы.

  Показать содержимое

 

Грамматика

  Показать содержимое

 

Также в expressions можно вызывать функции.

(bind text "toUpper('Skorpion G')")

 

  • Плюс 1

Рассказать о публикации


Ссылка на публикацию
5 070
[LESTA]
Разработчик
1 323 публикации
7 439 боёв

Базовая функциональность

 

Базовая функциональность определяет базовые возможности фреймворка:

  • формирование сцены (создание и добавление sprites, textfields, symbols, blocks)
  • scope, bindings system
  • построение definitions - element, css, animation, macro, constant.
  • holders глобальных данных (enums, глобальные константы, глобальные указатели на объекты, глобальные методы)

Build stage

Дисплей обджект (DO) - это общее наименование всех экранных объектов. Они отоборажаются по списку (дисплей лист) в порядке вызова, в координатах [х:0;у:0]. Наполнение и отображение, а так же набор свойств у разных диспл.обдж разный.

 

Основной возможностью языка разметки unbound является создание, конфигурация и добавление instance of display objects (DO) в соответствующий target-объект в display list'е . Target-объектом является родительский DO для текущего фрагмента верстки  Все DOs разделяются на 2 группы по наличию/отсутствию layout system. Layout system отвечает за позиционирование DO на сцене.

(block
    (tf
    )
)

где нода block является target-объектом для DO tf.

 

Display objects list

методы верхнего уровня описание
sprite Создание экземпляра Sprite
symbol  Создание экземпляра Symbol (MovieClip or Sprite) по имени из библиотеки
tf Создание экземпляра текстового блока TextField
element Создание экземпляра элемента описанного в верстке

block

Создает дочерний DO
   

 

 

 

 

 

 

 

 

 

 

 

 

 

Для всех отображаемых объектов доступны некоторые свойства, такие как:

Название свойства Описание Формат
height высота объекта в px или % :number
width ширина объекта в px или % :number
x позиция по оси X в px или % :number
y позиция по оси Y в px или % :number
scaleX горизонтальный множитель :number
scaleY вертикальный множитель :number
alpha прозрачность объекта от 0 до 1 :number
rotation поворот в градусах :number

 

 

 

 

 

 

Пример создания Sprite размером 500x500px с координатами [x=100; y=200] и прозрачностью 50%

(sprite
    (width = 500)
    (height = 500)
    (x = 100px)
    (y = 200px)
    (scaleX = 2)
    (alpha = 0.5)
    (rotation = 45)
)

Определение элемента

Верхнеуровневым DO верстки является element. Element – именованный параметризированный фрагмент верстки на базе спрайта. Element может иметь Scope, который содержит данные, доступные в теле element. Работа с элементом разделяется на 2 стадии: definition и create instance. Для определения элемента используется метод def.

(def element CommanderPersonalInfo() layout=true
)

Создание экземпляра:

(element CommanderPersonalInfo)

Scope

Scope - это хранилище данных и событий, доступных в теле определения элемента. Scope может иметь только Element, остальные DO могут работать только со scope родительского Element.

В scope должны быть объявлены все переменные и события, которые используются в теле element. Попытка обращения к несуществующему свойству или событию вызывает ошибку: access of undefined scope event 'nameEvent'

методы верхнего уровня описание
scope  Метод возвращает scope элемента для дальнейшей работы.

 

 

 

 

(scope
    (var lvlVal:str = '')
    (var title:str = '')
    (var cost:str = '')
    (var text:str = '')
    (var lvlTextColor:number = 0xffcac8c1)
    (var imageUrl:str = '')
)

Байндинги

Общее описание

Байндинги отвечают за простую синхронизацию данных (свойство, вызов метода, диспатч события). Существует три элемента синхронизации

  • свойство
  • вызов метода
  • событие

Для своей работы байндинги делают снимок данных исполнения и используют этот снимок при вычислении выражений, чтобы в этих выражениях были доступны все данные, которые были доступны на момент инициализации байндинга.

 

методы верхнего уровня описание
scope -> object  
bind запись значения в свойство объекта
bindcall вызов метода у объекта
object -> scope  
sync значение переменной в scope-е синхронизируется с значением свойства объекта
dispatch событие в scope-е синхронизируется с событием у объекта (диспатчится событие в scope-е по событию от объекта)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Все байндинги имеют общие свойства:

  • watch - следить ли за изменением значения свойств scope-а, которые используются в выражениях
  • init - производить ли действие (соответствующее типу байндинга) при инициализации байндинга
  • on - событие target-объекта, по которому будет срабатывать байндинг
  • enabled - можно использовать для включения и выключения срабатывания, может принимать выражения типа (enabled = "$event.buttonIdx == 1")

и общие методы:

  • event - добавляет произвольное событие в качестве триггера к байндингу

Bind

Синтаксис:

(bind scopeVar|property "scopeVar|$target|$event.field" [init=false|true] [watch=false|true] [on='scopeEventName|flashEventName|cppEventName']|[(event "scopeEventName")] [(enabled "expression")]), по-умолчанию init=true watch=true

Синхронизировать можно как переменную из scope, так и свойство target-объекта. 

  • Для синхронизирования переменной из scope, bind нужно поместить в scope.

    (scope
        (var count:number = 30)
        (var total:number = 100)
        (var percent:number = 0)
        (bind percent "count / total")
    )

     

  • Для синхронизации свойства target-объекта, bind должен вызываться в target-объекте, свойство которого мы синхронизируем.

    (scope
        (var vehicleType:str = 'vehicleHeavy')
    )
    (tf
        (bind text "vehicleType")
    )

     

В обоих случаях изменение любой переменной из выражения приводит к его вычислению, а результат записывается в синхронизируемую переменную или свойство. Управлять этим поведением можно через параметр watch=true|false.

 

Второй способ вызвать синхронизирование выражения - подписаться на событие. Поддерживается 2 способа для подписки на событие

  • Передать в аргумент on имя ивента как строку. Используется для подписки на флешовые события или события, которые распространяются из core c++. Если в этом ивенте есть аргументы, к ним можно получить доступ через объект $event. На момент выполнения выражения в bind все переменные должны уже быть известны. Но в $event аргументы попадут, если распространится событие. Так как события никакого еще не было, но на старте $event не определен, для этого у всех типов биндингов существует параметр init=true|false, которое позволяет настроить выполнение выражения при инициализации.

    (tf
        (class GrandTitleTextStyle)
        (text = 'default text')
        (bind text "$event.localX" init=false on='click')
    )

     

  • Передавать из scope объект event

    (scope
        (event onCustomEvent)
    )
    (tf
        (bind text "$event.localY" (event "onCustomEvent"))
        (dispatch onCustomEvent on='click')
    )

     

Примечание:

Подписаться на событие конкретного экземпляра элемента можно в его скоупе. Тогда передавать event нужно с использованием аргумента on.

Пример:

(element ButtonPrimary
    (scope
        (bind label "$event.localX+ $event.localY" init=false on='evBtnLeftClickEvent')
    )
)

Управлять исполнением синхронизации можно через вложенную конструкцию enabled, которая принимает выражение, результатом которого должно быть булевское значение. В свою очередь, если требуется подписать изменение enabled на event или выражение, нужно использовать bind.

  Показать содержимое

 

Инкрементальный счетчик по событию

Параметры watch= и init= блока bind :

  • watch - подписывать или нет на событие изменения переменных в выражении

  • init - производить ли рассчет выражения при создании переменной
(def element TestElement() layout=true
    (scope
        (var counter:number = 100)
        (bind counter "counter-10" watch=false init=false (event "evMouseClick")) #при watch=false возможно вычисление по событию
    )
    (style (backgroundColor = 0xFF00FF00) (width = 200) (height = 100) )
    (macro trace "counter")
)

 

Bindcall

Синтаксис:

(bindcall functionName "scopeVar|$target"* [init=false|true] [watch=false|true] [on='scopeEventName|flashEventName|cppEventName']|[(event "scopeEventName")] [(enabled "expression")]), по умолчанию init=false watch=true

Используется для вызова метода у target-объекта по условиям (событие, изменение аргумента).

Пример использования при подписке вызов метода у DO:

(mc 'CloseBtnCrossAnim'
    (bindcall gotoAndPlay "stateFrame")
)

 

Таким образом, при изменении переменной stateFrame будет вызван метод gotoAndPlay. 

Другой пример - вызов методов у контроллеров:

(controller $Animation
    (bindcall play duration=0.2 from={alpha:0} to={alpha:0.5} (event "evBtnOverEvent") (bind enabled "_isPressed"))
)

Поведение параметров eventenabled такое же, как у конструкции bind.

Dispatch

Синтаксис:

(dispatch scopeEventName delay=0.1 on='flashEventName|scopeEventName|cppEventName'|[(event "scopeEventName")] [args="{key1: value1, ...}"] [dir=0|1|2] [(enabled "expression")]), по умолчанию dir=0

Рассылка события по событию, которое генерируется scaleform или core c++ unbound. Перед тем как рассылать событие, его нужно объявить в scope.

(scope
    (event onClick)
)
(dispatch onClick on='click')

Передача аргументов

При рассылке события можно передавать аргументы. Аргументы передаются как dict. По умолчанию если не задан параметр args, то все свойства исходного event'a (тот ивент, который выступает тригером) передаются в рассылаемый event.

(scope
    (event onClick)
) 
(element ButtonPrimary
    (dispatch onClick on='click')
)
(trace "$event" init=false (event "onClick"))

Результат в ub_player_errors.log:

========================================================================
-------------------------------------------
UBTRACE: {altKey:false,bubbles:true,buttonDown:false,buttonIdx:0,cancelable:false,clickCount:0,commandKey:false,controlKey:false,ctrlKey:false,currentTargetFЧ',delta:0,eventPhase:2,localX:41,localY:18,mouseIdx:0,nestingIdx:0,relatedObject:[null],shiftKey:false,stageX:41,stageY:18,target:°FЧ',type:click}

Если же передать аргументы, то передача свойств исходного ивента не происходит.

Задержка рассылки события

Для решения вопросов отложенной рассылки события необходимо добавить параметр delay

(scope
    (event onClick)
    (var argument:number = 100)
)
(element ButtonPrimary
    (dispatch onClick delay=0.15 args="{param: argument}" on='click')
)
 
(macro eventChecker "onClick")
(trace "$event" init=false (event "onClick"))

Результат в ub_player_errors.log:

========================================================================
-------------------------------------------
UBTRACE: {param:100}

Направление распространения события

Направлением распространения event можно управлять параметром dir. Поддерживаются 3 значения:

  • 0 - event распространяется внутри element. По умолчанию dir=0.
  • 1 - event распространяется от ребенка к родителю.
      Показать содержимое

    Примечание:

Важно помнить о том, что прежде чем использовать event, он должен быть объявлен в scope. Даже несмотря на то, что в scope определении element ChildElement event уже объявлен, его нужно также объявить и в TestView.

  • 2 - event распространяется от родителя к ребенку.
      Показать содержимое

     

Разделение событий

В приведенных примерах вложенный элемент распространяет событие и на сцене в родителе был только один экземпляр. Но часто бывают случаи, когда несколько одинаковых элементов лежат на одном уровне вложенности. Тогда отличить, от кого именно пришло событие, будет сложно. Рассмотрим пример:

  Показать содержимое

 

на сцене 4 экземпляра ChildElement, и каждый из них распространяет событие onClick. Текстовый блок будет ловить события от каждого элемента. Конечно, можно проверять id кнопки в выражении bind. Но также для этого можно передиспатчивать события из scope вложенного элемента в уникальное событие родителя.

  Показать содержимое

 

Т.е. событие onClickChild1 синхронизируется с событием onClick только у кнопки с id=0, поэтому поле text у текстового блока будет обновляться только при клике на эту кнопку.

Dispatch при enabled=true

Не срабатывает событие при переключении enabled в true, но продолжает срабатывать при переключении trigger в true.

  Показать содержимое

 

Dispatch property change event

Побочным результатом изменений в dispatch стал контроль за событием изменения выражения

(dispatch evUpdateMouse (bind enabled "isActive") (bind trigger "isActive"))

При таком порядке биндингов сначала пересчитается enabled и событие сработает только при isActive=true.

Контроллеры

Сontroller  - это атомарная функциональность над target-объектом. Позволяет расширить функционал за счет выполнения кастомной логики над объектом. 

Controller реализуется на С++. 

 

методы верхнего уровня описание
controller Метод возвращает style текущего DO для дальнейшей работы

 

 

 

 

(controller $Animation
    (play duration=0.2 to="{
    alpha:(isMouseOver ? 1.0 : 0.0),
    visible:(isMouseOver ? true : false)
    }")
)

Стилизация display object.

Elements и blocks имеют Style, что позволяет настраиваить их визуальное представление, например, изменять размеры, накладывать фильтры и т.д.

top-level methods  
style Метод возвращает style текущего DO для дальнейшей работы

 

 

 

 

У каждого блока свой набор пропертей style. Так, например, блоку tf можно задавать font, size и color.

(tf
    (style
        (fontFamily = $TitleFont)
        (fontSize = 36)
        (textColor = 0xf5eed5)
    )
)

Также через изменение свойств style: paddings, margins, position, flow и т.п, - можно управлять позиционированием блока.

(block
    (style
        (position = "absolute")
        (bottom = 18px)
        (paddingLeft = 24px)
        (paddingRight = 24px)
    )
)

Style обладают только объекты с layout-system, а именно element с параметром layout=true и различного рода блоки, унаследованные от BaseBlock в c++. Обращение к свойством style у DO без layout system приводит к ошибке: access of undefined method 'style' through a reference with type element 

 

  • Плюс 2

Рассказать о публикации


Ссылка на публикацию
5 070
[LESTA]
Разработчик
1 323 публикации
7 439 боёв

Декларативный язык разметки и S-выражения

 

Верстка состоит из S-выражений. Существует 4 вида s-выражения, каждый из которых предназначен для конкретного действия:

  • Call method
    (<method name> <positional argument value>* <named argument>*
        <nested s-expression>+
    )
    <named argument> := <argument name> = <argument value>
    (bind isEnabled "$event.enabled" init=false
        (event "isEnableChanged")
    )

    bind - <method name>

    isEnabled, "$event.enabled" - <positional argument value>*

    init=false - <named argument>*

    (event "isEnableChanged") - <nested s-expression>+

  • Add definition
    (def <definition type> <difinition name> (<declaration argument>*) <named argument>*
        <nested s-expression>+
    )
    <declaration argument> := <argument name> : <argument type> [ = <default value> ]
    <named argument> := <argument name> = <argument value>
    По сути является частным случаем s-выражения-метода и введен только ради особого синтаксиса декларации параметров.
    (def element TestView(name:str = '', count:number) layout=true
        (block      
        )
    )

     

  • задать значение свойства
    (<property name> = <property value>)
    (style
        (width = 100px)
    )
      
    (tf
        (text = 'Hello world!')
    )
  • взять значение свойства
    (.<property name>
        <nested s-expression>+
    )
    (.graphics
        (lineStyle 1 0xffffdc84 1)
        (beginFill "0xff414141" "0")
        (drawRect 0 0 450 64)
        (endFill)
    )

На этих 4 типах выражений и строится вся разметка.

  Показать содержимое

 

Макросы 

Макрос - именованный параметризированный фрагмент верстки, который подставляется в место вызова на этапе парсинга.

Макросы реализованы на уровне AST (Abstract syntax tree). 

Определение макроса:

(def macro <macro name> (<declaration argument>*)
    <nested s-expression>+
)
<declaration argument> := <argument name> : <argument type> [ = <default value> ]
(def macro StatusesVehicleTypes(width:number=100%, height:number=100%, renderer:str='VehicleTypeItem', name:str='statusesVehicleTypes')
    (element List "name" "renderer" "width" "height"
        (scope
            (containerFlow = "Flow.HORIZONTAL")
            (listVscrollPolicy = 'off')
            (listHscrollPolicy = 'off')
        )
    )
)

Использовать макрос можно с помощью ключевого слова macro. 

(macro <macro name> <positional argument value>* <named argument>*)
(macro StatusesVehicleTypes 160 height=32)

Несмотря на то что это выглядит как обычный вызов метода, это не так. Подстановка макроса происходит на этапе парсинга.

В определении макроса можно использовать макросы, определенные ранее. Подстановка происходит рекурсивно. 

(def macro ComponentStateBase (statesDict:expression)
    (macro ComponentStateBaseScope "statesDict")
    (macro ComponentStateBaseContent)
)

 

Исполнение верстки

Движок, исполняющий верстку, максимально абстрагирован от каких-либо конкретных функциональностей. В нем нет знания о спрайтах, скоупах и т д.

Здесь есть такое понятие, как таргет-объект. Это текущий объект, над которым выполняются действия, описанные s-выражениями. S-выражения различаются по типам (метод, сеттер, геттер) и не более (даже definition на этом уровне будет просто методом).

Первое исполнение верстки происходит после загрузки текста файла в фреймворк. После парсинга файла - мы имеем список s-выражений, которые содержатся в файле (как правило, это дефенишины, задания глобальных констант). Для исполнения этого списка s-выражений создается фейковый объект (хотя по факту этим методам он не нужен).

Другим частым случаем запуска движка на исполнение списка s-выражений является построение дефинишина, здесь создается соответствующий дефинишину объект и s-выражения, которые содержатся в теле дефинишина, исполняются над ним.

По ходу исполнения s-выражений таргет-объект меняется. Это происходит при исполнении вложенных s-выражений, для них таргет-объектом будет объект, который вернуло родительское s-выражение. Если s-выражение ничего не вернуло или вернуло не объект, то вложенные s-выражения исполняться не будут. Возвращать значения (в том числе объекты) могут методы и геттеры.

 

На примере подробно расписано, как меняется таргет-объект:

  Показать содержимое

 

Типы данных

В верстке введена строгая типизация (параметры definitions, свойства скоупа), проверка типов происходит на этапе исполнения (кроме макросов, для них на этапе подстановки, т е на этапе парсинга)

Введение типизации позволяет лучше контролировать ошибки.

тип описание синтаксис комментарии
number number 12.34 для типа number можно уточнить единицы
  percent 12.34%  
  pixels 12px  
bool boolean expression true / false  
str string 'text123' single quotes
dict dictionary {a : 1, b: 2}  
array array [1, 2, 3]  
expression вычиляемое выражение "a ? 1 : 2"

в двойных кавычках

константа не может быть определена внутри выражения

gfx указатель на любой GFx::Value нет константа не может быть определена в верстке и в выражениях
cpp сложный объект, такой как коллекции или сущность нет  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Примечание:

Важной особенностью при работе со строковыми литералами и переменными является то, что одинарные кавычки можно не использовать, т.к. парсер при разборе интерпретирует значения как строку. Поэтому существует двойственность при объявлении строковых переменных.

  Показать содержимое

 

Эта особенность проявляется и при использовании bindings конструкций (bind, bindcall, sync, dispatch), например:

# Dispatch события evBtnUpEvent
(dispatch evBtnUpEvent on=mouseUp)

Первым аргументом toplevel функция dispatch ожидает строку, но явно обозначать, что это строка, не требуется.

 

Enums

В выражениях можно использовать перечисления, которые заданы в core c++ части Unbound.

enum name свойства описание пример комментарии
Flow

HORIZONTAL

VERTICAL - значение по умолчанию

TILE_HORIZONTAL

TILE_VERTICAL

REVERSE_HORIZONTAL

REVERSE_VERTICAL

Свойства определяют то, как будут выстраиваться вложенные display objects.
(block 
    (style
        (flow = "Flow.HORISONTAL")
    )
)
  
  
# Эквивалент записи выше
(hblock
)

Для block с выставленным в стиле свойством flow существуют алиасы:

  • block - вертикальный блок
  • hblock - горизонтальный блок
  • vtile - вертикальный tile блок
  • htile - горизонтальный tile блок
  • reverse - вертикальный блок с обратным порядком элементов в блоке
  • hreverse - горизонтальный блок с обратным порядком элементов в блоке

У block параметр flow = Flow.VERTICAL

Easing

line

elastic_in

elastic_out

bounce_in

bounce_out

back_in

back_out

cubic_in

cubic_out

quint_in

quint_out

expo_in

expo_out

expo_in_out

sine_in

sine_out

sine_in_out

Types of easing for animation.
(controller $Animation
    (play duration=0.3 to={alpha:0} easing="Easing.cubic_out")
)
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • Плюс 2

Рассказать о публикации


Ссылка на публикацию
5 070
[LESTA]
Разработчик
1 323 публикации
7 439 боёв

Конструкции языка разметки

Constant

Константы имеют такое же назначение, как и в других языках, и служат для хранения неизменяемых значений.

В unbound можно использовать 2 типа constant:

  • Глобальные констатнты
    Для объявления глобальной константы используется функция (def. В поле аргумента передается содержимое, которое может принимать переменная при объявлении.

    # объявление
    (def constant C_ALLY 0xFF80c0ff)
    ...
    # использование
    (style 
        (width = "32px")
        (height = "32px")
        (backgroundColor = "C_ALLY")
    )
      Показать содержимое
      Показать содержимое

     

  • Локальные константы
    Эти константы объявляются в scope element и могут быть использованы только в element'е.

      Показать содержимое

     

 

  • Плюс 2

Рассказать о публикации


Ссылка на публикацию
5 070
[LESTA]
Разработчик
1 323 публикации
7 439 боёв

Controllers

Контроллер -- сущность, выполняющая один тип действий с заданным объектом. У контроллеров $Instance, $FxInstance и $Repeat - объект указывается в поле renderer; контроллер $Animation направлен на родительский объект; контроллер $Sector сам является объектом.

$Instance

Добавляет на сцену экземляр element'a.

  Показать содержимое

 

  • renderer задаёт элемент, с которым контроллер будет производить операции. Доступен для биндинга.
  • layout отвечает за то, будет ли работать layout система. Значение по умолчанию false
  • args при вызове передаёт в рендерер значение из скоупа, в котором находится.
  • exprs выполняется на стороне рендерера, но имеет доступ к родительскому скоупу. Может содержать выражения и биндинги. Через этот атрибут позволяет слушать в ребенке переменные из родительского скоупа.
  • enabled задаёт выражение для срабатывания контроллера. Контроллер сработает, если выражение == true.
  • trigger задаёт выражение для срабатывания контроллера. Контроллер сработает, если выражение изменит значение.
  • event, аналог enabled, но реагирует на Events

 

В некоторых случаях не требуется выделять отдельный элемент, тогда блоки можно вложить в атрибут (exprs и выставить layout=true у контроллера.

  Показать содержимое

 

  Показать содержимое

recreate - метод, который пересоздает инстанс

$FxInstance

Временно добавляет на сцену экземпляр элемента, который будет удалён со сцены через «lifetime» секунд.

  Показать содержимое

 

  Показать содержимое

 

  Показать содержимое

 

  • renderer, args, exprs, enabled, layout - поведение аналогично поведению в $Instance контроллере
  • bindcall create - определяет эвент (событие) срабатывания для контроллера. Контроллер вызывается когда в скоупе ловится указанное событие. В примере выше мы обращаемся напрямую к $datahub, поэтому переменную или эвент отдельно для этого события можно не заводить (но так делать не рекомендуется, т.к. компонента на момент инициализации может не оказаться и подписка не произойдёт. Лучше объявлять entity, component и уже обращаться к эвенту внутри переменной-компонента). 
  • lifetime определяет время жизни элемента на сцене. Если не задано - значение по умолчанию  15 секунд.

$Repeat

Создает указанное число копий рендерера.

(controller $Repeat renderer='MapMarkerItem'
    (bind count "collection.items.length" (event "collection.evAdded"))
    (args size="size" mapScale="mapScale" scaleRatio="scaleRatio")
)

 

  Показать содержимое
  • renderer, args, exprs, enabled, layout - поведение аналогично поведению в $Instance контроллере
  • count задаёт число копий рендерера. Может быть любым expression'ом. В примере выше -- counter равен количеству элементов в коллекции collection.
  • removeChildAt(index) - удаляет со сцены рендерер по index
  • $index - целое число, номер ребенка по порядку от 0 до конечного элемента. У первого созданного элемента будет $index=0 и т.д. Автоматически находится в скоупе ребенка с момента создания.

 

$Animation

Анимирует родительский display object или значение переменной в скоупе.

Доступные методы контроллера  с примерами заполнения параметров:

  • play - запуск одной анимации
      Показать содержимое
      Показать содержимое
    если (keystate == Key.DOWN), то изменяет значение longTapArc с 0 до 360 за 0.5сек
     
      Показать содержимое

    если переменная tacticalMap меняет значение - отыгрывает появление, если tacticalMap меняет значение на первоначальное - отыгрывается исчезновение.
     

    • bindcall указывает, что запустить анимацию следует в соответствии с условиями, указанными в bind enabledbind trigger или event.
    • duration указывает длительность анимации в секундах.
    • delay указывает задержку перед проигрыванием анимации.
    • from стартовые значения анимации. Если не указать - анимация начнется с тех значений, которые находятся в скоупе.
    • to финальные значения анимации. Обязательное поле.
    • reverse условия отыгрывания анимации в обратную сторону, to → from (при условии наличия обоих полей).
    • trigger условия срабатывания анимации, когда значение условия меняется. Отличие от enabled в том, что enabled срабатвает только когда выражение == toBoolean(true). ВАЖНО! На момент запуска delay -- контроллер уже принял в себя значения всех переменных на всех позициях. Если на момент окончания задержки значения переменных изменились - контроллер об этом не узнает.
    • killAll - свойство, при старте анимации уничтожает все активные анимации у объекта
        Показать содержимое

 

Доступные изинги:

https://easings.net/

параметр easing принимает следующие значения:

  Показать содержимое

 

Примеры:

  1. Пример запуска анимации по клику на кнопку и отображение в текстовом блоке изменяющихся значений. Анимация переменной в scope :
      Показать содержимое

     

  2. Пример анимации свойств стилей
      Показать содержимое
  3. Trigger vs Enabled
    (controller $Animation
            (bindcall play  duration = "HEALTH_ANI_MIN"
                            enabled="isEnabled"
    .....
    )
     
    (controller $Animation
            (bindcall play  duration = "HEALTH_ANI_MIN"
                            trigger="isTarget == 'ally'"
    .....
    )

    trigger - условие срабатывания анимации, когда значение условия меняется на противоположное. Отличие от enabled в том, что enabled срабатывает только когда выражение true.

 

Внимание!

Особенность работы контроллера с параметром delay. Значения анимируемых переменных в параметре to вычитываются контроллером без учета delay. Поэтому если на момент окончания задержки значения переменных изменились контроллер об этом не узнает.

$Sector

Рисует сектор используя flash.display.Graphics target объекта

  Показать содержимое

 

$Tooltip

В общем случае, тултип – это элемент, который показывается надо всей остальной вёрсткой. Примеры:

  • всплывающая подсказка: появляется при наведении мыши на некоторый блок, пропадает, когда мышь уходит.
  • контекстное меню: появляется по клику на блоке, пропадает, если кликнуть на экране за пределами меню.

Например,

  Показать содержимое

 

Элемент и аргументы

Как реализуется: в блок включаем controller $Tooltip, задаём ему название элемента и аргументы для всплывающей подсказки:

 

  Показать содержимое

 

Положение

Задаётся тип точки привязки ("position"):

  • тултип прилипает к краю блока, и в дальнейшем следит за положением блока,
  • тултип прилипает к краю блока и так и стоит в этой точке (даже если блок уехал)
  • тултип едет за мышью,
  • тултип появляется в той позиции, где была мышь на момент его появления, и потом там стоит.

Потом – выравнивание ("align") и сдвиг ("offset") относительно этой точки, и минимальное расстояние до границы экрана ("screenBoundsOffset").

Если тултип подъезжает к границе экрана (с учетом "screenBoundsOffset"), то он упрётся в эту границу и не будет смещаться... при условии, если он не перекроет точку приязки. То есть, если тултип имеет выравнивание "outerLeft|bottom" (слева и снизу от точки привязки) – то при приближении к нижней границе экрана он может в неё упереться – и не перекрыть точку.  А вот при выравнивании "innerLeft|outerBottom" (под точкой привязки, у левого её края) тултип не может просто упереться в нижний край: точка привязки будет перекрыта. Поэтому он "перепрыгивает" на противоположную сторону от точки привязки, т.е. меняет выравнивание на "innerRight|outerBottom". Пины тултипа (см. ниже) при этом тоже поменяются.

Примеры "упирания" и "перепрыгивания" см. Sandbox/Unbound2/TooltipSamples.

  Показать содержимое

Пины

Также тултип может иметь пины (стрелочки от края тултипа к точке привязки); нужный пин (левый, правый, верхний или нижний) выбирается автоматически. Правда, с пинами есть сложности, на них не работают отступы (маржины и паддинги). Если нужен отступ – то приходится добавлять в пин фон нужного размера с прозрачной заливкой (например, цветом 0x00000001). А отрицательный отступ (т.е. наложение стрелочки на тело тултипа) и вовсе можно задать только с помощью параметра pinOffset.

  Показать содержимое

 

Другой способ сделать "пины" – это подписать элемент тултипа на событие evPinPositionChanged, и переключать подложку в зависимости от того, какую стрелочку нужно показать. Это работает надёжнее и даёт больше контроля, чем задание стрелочек в отдельных элементах.

  Показать содержимое

 

Появление/пропадание и анимация

Здесь указываем, по каким событиям и с какой анимацией тултип появляется и пропадает. Анмация настраивается так же, как в controller $Animation.

  Показать содержимое

 

События

Контроллер тултипа бросает события при появлении, исчезновении, или клике за пределами тултипа.

  Показать содержимое

Те же самые события могут направляться не только контроллеру тултипа, но и его элементу (renderer'у). Для этого события с таким же именами нужно вручную определить в скоупе рендерера; контроллер их там найдёт (так же, как прописывается событие evPinPositionChanged – см. выше).

 

scroll_bar

Элементы полосы прокрутки

Полоса прокрутки состоит из 4 элементов: "трэка", по которому перемещается "тумб", и кнопок слева и справа от "трэка":

(scroll_bar
    ...
    (btn_decr = 'имя элемента')
    (track = 'имя элемента')
    (thumb = 'имя элемента')
    (btn_incr = 'имя элемента')
    ...
)

"Тумб" можно подцеплять мышкой и тащить, кнопки можно нажимать (сдвиг на одну "строчку" влево или вправо), на "трэк" тоже можно нажимать ("тумб" приедет в ту точку, на которую нажали).

Каждый из 4 элементов в простейшем случае может быть просто закрашенным блоком с заданной высотой и шириной (но трэк и тумб автоматически растянутся под размер и диапазон области прокрутки). Можно прописать автоматическое изменение стиля элемента при наведении мыши и при нажатии. Для этого прописываем четыре стиля:

  Показать содержимое

 

собираем их в dict,

(def constant SB_LEFT_BTN {
    up : 'SBLeftBtnUpStyle',
    over : 'SBLeftBtnHoverStyle',
    down : 'SBLeftBtnPressStyle',
    disabled : 'SBLeftBtnDisabledStyle' }
)

и подписываем элемент на событие stateChanged:

(def element SBLeftBtn() layout=true
    (style
        (width = 12px)
        (height = 13px)
    )
    (bind class "SB_LEFT_BTN[$event.state]" init=false on='stateChanged')
)

а потом подсовываем этот элемент в scroll_bar:

(scroll_bar
    (btn_decr = 'SBLeftBtn')
    ...

Имейте в виду, что какой-то элемент должен ловить события мыши – то он должен быть залит каким-то цветом или изображением (а вот альфу ему можно поставить в 0). Т.е., если нужно сделать прозрачный трэк – то ему всё равно надо указывать непрозрачную заливку, а потом писать (alpha=0).

 

Параметры и события полосы прокрутки

  Показать содержимое

 

Когда scroll_bar работает в составе scrollArea, задавать надо только orientation, прочие параметры устанавливаются автоматически (и на события scrollArea тоже сама подписывается).

Кстати, если поставить параметр alignThumbToBorders в false и не задавать btn_decr и btn_incr (задать только трэк и тумб) – то получится слайдер.

 

scrollArea

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

  Показать содержимое

 

Область прокрутки можно двигать колёсиком мыши (если зажать шифт – то по горизонтали); но scroll_bar для этого всё равно должен быть задан, т.к. именно он отвечает за параметры прокрутки и скорость анимации.

 

Тени и анимация области прокрутки

Можно задать четыре тени, и настроить анимацию при появлении/пропадании теней и при наведении мыши на область прокрутки:

  Показать содержимое

 

Методы для прокрутки

  Показать содержимое

 

Динамическая прокрутка

Если в content поместить controller $Repeat, то контроллер может создавать свои элементы динамически, по мере того, как scrollArea прокручивает до них. Для этого контроллеру надо указать, какие размеры имеют его элементы:

  Показать содержимое

 

 

 

  • Плюс 2

Рассказать о публикации


Ссылка на публикацию
5 070
[LESTA]
Разработчик
1 323 публикации
7 439 боёв

Element

Объект верхнего уровня. Имеет собственное имя, может быть вызван (в том числе извне документа, в котором находится) и переиспользован (с помощью Controllers или прямого объявления). Имеет свой обособленный scope, в который может принимать извне присланные значения. Элемент может быть 2 видов: участвовать в layout (иметь стили) и не участвовать. Это регулируется свойством layout=true или использование алиаса def layout:

  Показать содержимое

 

 

  • Плюс 1

Рассказать о публикации


Ссылка на публикацию
5 070
[LESTA]
Разработчик
1 323 публикации
7 439 боёв

Event

Событие - объект который генерируется и рассылается по какому-либо действию пользователя (например клик мыши, нажатие клавиши и т.п.). Для распространения события используется метод dispatch

Событие либо происходит (что эквивалентно bool == true) либо отсутствует. Событие может срабатывать по различным условиям, а ловить (или слушать) событие могут как родители, так дети и сиблинги. Для этого нужно объявить это же событие в скоупах всех элементов, где планируется их ловить.

(event valChanged)
(event evKilled)
...
(dispatch evKilled args={} dir="EventDirection.DOWN" (event $datahub.getEntity(entityId).health.evKilled))

event это событие по которому происходит dispatch.

dir задаёт направление события по иерархии. По умолчанию dispatch отсылает событие только в рамках самого элемента. Чтобы отправить событие в родителя - нужно в dir указать EventDirection.UP. В ребёнка - EventDirection.DOWN. В сиблингов - достаточно просто объявить эвент в нужном сиблигне, а dir можно не указывать. Для dir в hud_replaces заведён dict со значениями. По умолчанию dir=0.

(def constant EventDirection {  NONE:  0,
                                UP:    1,
                                DOWN:  2
})

 

События в unbound могут генерироваться:

  • Из core C++ части. Например в блоке slider генерируется event valueChanged когда изменяется его value.
    (dispatch valChanged on='valueChanged' dir=1)

     

  • Из Scaleform части. Например событие клика по display object'у
    (block
        (style
            (width = 100)
            (height = 100)
            (backgroundColor = 0xff00ff00)
        )
        (bind alpha "0.5" init=false on='click')
    )

Различия использования подписки на события с помощью on и event

Биндинг-конструкции могут подписываться на события двумя способами:

  • Передача имени события в аргумент on.
    (bind eventArgs "$event" init=false on='eventScope')
  • Передача вложенного объекта event
    (trace "$event" init=false (event "eventScope"))

Событие может быть сгенерировано:

  • в scalefom, например событие мыши click или событие клавиатуры keyDown
  • в core c++ части unbound, например блок slider генерирует событие sliderPositionChanged когда изменятся положение ползунка
  • в верстке, т.е. событие объявлено в scope элемента и генерируется в его определении.
    (def element TestView() layout = true entrance=true
        (scope
            (event eventScope)
        )
      
        (element Button
            (dispatch eventScope on='click')
        )
    )

    Но по сути своей это не генерация события, а превращение из события scalefom/core c++ (в данном примере 'click')  в событие скоупа (в данном пример eventScope)

Рассмотрим различия между этими двумя способами

Если событие генерируется в scaleform или в core c++ unbound, то подписаться можно только с использованием аргумента on. 

  Показать содержимое

 

Если событие объявлено в scop'e элемента, то существует 2 случая подписки в зависимости от расположения подписки. 

  • Подписку в scope можно осуществлять и через on и через event
      Показать содержимое
  • Подписку вне скоупа можно осуществлять только через event
      Показать содержимое

 

Таким образом подписываться через аргумент on можно на те события которые генерирует target-объект

Отдельно рассмотрим случай подписки на события scop'а при создании элемента.

(element Button
    (scope
        (label = 'default text')
        (bind label 'leftClick' init=false on='evBtnLeftClickEvent')
        (bind label 'rightClick' init=false on='evBtnRightClickEvent')
    )
)

События 'evBtnLeftClickEvent' и 'evBtnRightClickEvent' генерируются в определении element'а Button.

Если использовать конструкцию event, то события должны быть объявлены в родительском скоупе

  Показать содержимое

 

 

  • Плюс 2

Рассказать о публикации


Ссылка на публикацию
5 070
[LESTA]
Разработчик
1 323 публикации
7 439 боёв

Функции для вычисляемых выражений

Список глобальных функцией представлен в таблице.

Функция Описание Пример
abs(number) Математический модуль  
ceil(number) Наибольшее цело число от данного  
countdownFormat(numberSeconds, numberOfDigits, isShowMinutes)

Форматирует переданное число секунд в формат min:secongs

Если минут 0, отображается 00

"countdownFormat(125, 0, true)"
floor(number) Наименьшее цело число от данного  
formatFloatingPoint(number, numberOfDigits=1)

Округление дробной части до numberOfDigits знака после запятой. По умолчанию numberOfDigits = 1

Не учитывает региональные настройки формата.

Нет разделителя разрядов.

"formatFloatingPoint(1.193454334123)" # result 1.2

"formatFloatingPoint(0.423456, 3)" # result 0.423

formatSeparator(number)

Группировка целочисленной части на группы по 3 цифры, разделенных пробелами. Округление дробной части до второго знака.

Не учитывает региональные настройки формата.

Целые числа отображаются без дробной части, а дробные - с 2 знаками после запятой.

"formatSeparator(1103569353.789254232)" # result 110 123 123 123.79

Примеры:

999.595 => "999.60"

999.59 => "999.59"

1000.5 => "1 000.50"

999 => "999"

1 999.0 => "1 999"

999.001 => "999.00"

max(x, y) Максимальное из двух чисел. return x > y ? x : y (var test: number  = "max(smth, smth2)")
min(x, y) Минимальное из двух чисел. return x < y ? x : y (var test:number = "min(smth, smth2)")
pow(basis, exponent) Возведение числа basis в степень exponent  
radToGrad(radNumber) Перевод из радиан в градусы  
gradToRad(gradNumber) Перевод из градусов в радианы  
round(number) Математическое округление до целого числа "round(0.423456)" # 0
roundToDecimal(number, знаков_после_запятой) Математическое округление до заданного числа знаков после запятой. roundToDecimal(12.1645, 1) # result 12.2
subst(str, array_values, dict_values) Подстановка переданных аргументов в плейсхолдеры

"subst('first number is %d, second is %d', [50, 51])"

subst('%(min)d - %(max)d', [], {min:1, max:2})

sin(radNumber) Синус угла в радианах  
cos(radNumber) Косинус угла в радианах  
tan(radNumber) Тангенс угла в радианах  
atan2(y, x) Арктангенс от y/x, в радианах.  
toLower(str) Преобразует прописные символы в строчные  
toUpper(str) Преобразует строчные символы в прописные  
tr Локализация строк по IDS  
isMatch(строка, регулярное_выражение) Подходит ли строка под регулярное_выражение.  
indexOf(значение, массив) В каком индексе значение находится в массиве (-1 если его там нет).  
isIn(значение, массив) Есть ли значение в массиве.  

isStr(значение)

isNumber(значение)

isBool(значение)

Проверка типа значения.  
toNumber(значение) Приведение значения к числу
toNumber('5') → 5
toString(значение) Приведение значения к строке, без каких-либо настроек. Умеет печатать не только числа, но и массивы и словари.  
toBool(значение) Приведение значения к  логическому значению Boolean.
toBool(null) → false
toBool(5) → true
toBool(0) → false
toBool('hi') → true
toBool('') → false
toBool(['hi']) → true
toBool([]) → false
toBool({'key': 'val'}) → true
toBool({}) → false
toHex(число, ширина) Печатает шестнадцатеричное целое в строку, с заданной шириной.
Если получившееся число короче, чем заданная ширина, то дополняется слева нулями; если длиннее, то старшие  биты обрезаются (полезно, чтобы отрезать альфа-канал при печати цвета).
 
shipLevelsToRoman(уровни, супер_корабль=false) Печатает уровни кораблей (массив целых чисел) римскими цифрами, собирает по диапазонам (т.е. массив [1, 2, 4, 5, 6, 7] будет напечатан как "I, II, IV-VII"). Если "супер_корабль"=true, то уровень 11 исключается из диапазона, и добавляется в конце как "★".

shipLevelsToRoman([8, 9,10,11], false) # result VIII, IX, X, XI

shipLevelsToRoman([8, 9,10,11], true) # result VIII, IX, X, ★

callExternal(имя_команды, массив_аргументов) Вызывает заданную команду Питона с заданными аргументами.  
log(сообщение) Вызывает команду "inputMapping.onMsg" с заданным сообщением; одновременно – печатает сообщение и отладочную информацию в строку. bind text "log('message')"
clamp(число, нижняя_граница, верхняя_граница) Приводит число к диапазону от нижней_границы до верхней_границы. Принцип работы аналогичен функции clamp() в css  
sqrt(number) Квадратный корень.  
random() Случайное действительное число от 0 до 1 (включительно)  
randomFloor(max) Случайное целое число от 0 до макс (включительно)  
currentServerSeconds() Время на сервере, в секундах и долях секунд.  
currentClientSeconds() Время, прошедшее после запуска клиента игры, в секундах.  
formatTime(секунды, формат, локализация, локальное_время) Форматирует время (в секундах), в зависимости от "формата".

Варианты следующие:

  • yyyy.MM.dd hh:mm:ss
    • yyyy – полный год
    • yy – год, 2 цифры
    • M, MM – месяц в году, 1 или 2 цифры
    • d, dd – день в месяце
    • H, HH – общее количество часов (включая дни)
    • h, hh – часы (с начала суток)
    • m, mm – минуты (с начала часа)
    • s, ss – секунды (с начала минуты), 1 или 2 цифры
  •     HIGHEST – старший ненулевой элемент даты-времени, начиная с месяца: если интервал больше месяца – печатает месяцы, если больше дня – печатает дни, и так до секунд.
  •     HIGHESTDAYS - старший ненулевой элемент даты-времени, начиная с дней (т.е. напечатает не "2 месяца", а "63 дня").
  •     HIGHEST,WITH_DAYS - старший ненулевой элемент даты-времени, начиная с месяцев И дней (т.е. напечатает не "2 месяца", а "2 месяца 3 дня").

 

"Локализация" – суффикс локализации, добавляется после IDS_PL_HOUR_FULL в режимах HIGHEST*. Особое значение "ABB": тогда используются сокращённые локализации, IDS_PL_HOUR. По умолчанию пустой.

"Локальное время" – если "true", то дата в режиме "yyyy.MM.dd hh:mm:ss", печатается в клиентском локальном времени, если "false" – то в UTC. В режимах HIGHEST* игнорируется. По умолчанию "false" ("печатать в UTC").

"formatTime(time, 'dd.MM.yy', '', true)"
"formatTime(time, 'dd.MM.yyyy hh:mm', '', true)"
"formatTime(time,'HIGHEST,WITH_DAYS')"
Оператор "in"

Оператор in ищет

  • подстроку в строке,
  • элемент в массиве,
  • ключ в ключах (не элементах!) словаря,
  • подмассив или набор ключей в массиве или ключах словаря.
  • 'abc' in 'dfgabc1tyu'
  • 8 in [7, 8, 9]
  • 'szh' in {'bbb':1'szh':2'vvv':3}
  • ['8''7'] in {'7':6'8':0'9':'aa'}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • Плюс 2

Рассказать о публикации


Ссылка на публикацию
5 070
[LESTA]
Разработчик
1 323 публикации
7 439 боёв

Layout

Unbound имеет layout system, которая занимается позиционированием блоков, расположенных в одном контейнере по определенным параметрам. Для включения layout system используется атрибут layout=true|false определения element'a. Описание element c атрибутом layout=true эквивалентно def layout

Атрибут объекта «элемент». Используется чаще всего для разметки несокльких элементов друг относительно друга. Т.е. второй дочерний элемент будет построен следом за первым и т.д. Координаты всех дочерних элементов относительны друг друга, т.е. все DisplayObject знаю о размерах друг друга и выстраиваются соответственно. Удобно применять для проектирования сложных объектов, состоящих из нескольких объектов.

Так же позволяет использовать атрибут style для изменения внешнего вида и динамического изменения параметров блоков.

Пример:

  Показать содержимое

 

  Показать содержимое

Позиционирование блоков

Layout system'a позиционирует блоки согласно значения свойства position. Position может принимать следующие значения:

  • flow - layout system'а позиционирует вложенные блоки один за другим (положение одного блока зависит от положения предыдущего), по умолчанию position="flow"

  • absolute - layout system'а исключает блок из потока (списка позиционирования).

Для позиционирования блоков относительно друг друга при position="flow" можно использовать следующие свойства стиля:

  • paddingLeft / paddingRight / paddingTop / paddingBottom - отступ слева / справа / сверху/ снизу для вложенных блоков.
      Показать содержимое

    Если нужно задать сразу все 4 параметра можно использовать следующую конструкцию:

    (style
        (padding = [5, 10, 15, 20]) # [paddingLeft, paddingTop, paddingRight, paddingBottom]
    )

     

  • marginLeft / marginRight / marginTop / marginBottom - отступ слева / справа / сверху/ снизу для текущего блока

      Показать содержимое

    Если нужно задать сразу все 4 параметра можно использовать следующую конструкцию

    (style
        (margin = [5, 10, 15, 20]) # [marginLeft, marginTop, marginright, bottom]
    )
    Примечание:
    Главное отличие margins от paddings в том, что параметры paddings устанавливаются в родительском блоке и влияют на позиционирование вложенных блоков. Margins же влияют на позиционирование текущего блока.

     

  • gap, hgap, vgap - отступ по горизонтали / вертикали между каждым вложенным блоком

      Показать содержимое

    Если отступ между блоками по горизонтали и вертикали одинаковый, то можно использовать параметр gap.

    Пример использования:

      Показать содержимое

    В результате получим:

    unbound2_htile_gap.PNG

  • align - позиционирование всех вложенных блоков как единого блока. Может принимать следующие значения: 
    left  - выравнивание контента по левому краю
    right - выравнивание контента по правому краю
    top - выравнивание контента по верхнему краю 
    bottom - выравнивание контента по нижнему краю
    center - выравнивание контента по центру по горизонтали
    middle - выравнивание контента по центру по вертикали

    Пример выравнивания блока по левому краю:

      Показать содержимое

    Можно использовать несколько значений одновременно разделенных "|". Например если требуется выровнять по центру и по вертикали и по горизонтали. Пример:

    (align = "center | middle")

     

Для позиционирования блоков при position="absolute" вышеперечисленные свойства не применяются, нужно использовать следющие:

  • left / right / top / bottom - отступ от левого / правого / верхнего / нижнего края контейнера, в котором находится блок

Пример использования:

  Показать содержимое

 

В результате получим

unbound2_position_absolute.PNG

 

  • hcenter  / vcenter- отступ от центра по горизонтали / по вертикали
      Показать содержимое

     

В результате получим

unbound2_position_absolute_center.png

 

Примечание:

Размер блока у которого параметр position="flow" равны размерам вложенных в него блоков.

Размер блока у которого параметр position="absolute" по умолчанию равны 0.

 

  • Плюс 2

Рассказать о публикации


Ссылка на публикацию
5 070
[LESTA]
Разработчик
1 323 публикации
7 439 боёв

Macro

Макрос - именованный параметризированный фрагмент верстки, который место вызова заменяет на содержимое макроса на этапе разбора. Тем не менее не может работать со скоупом родителя и переменные для работы нужно передавать как при вызове элемента. Позволяет переиспользовать одинаковые блоки кода несколько раз.

 

Вот одно из самых распространенных использований:

  Показать содержимое

 

Пример использования:

  Показать содержимое

 

После того как макрос был определен, его можно вызывать в любом месте.

Пример:

# Вызов макроса
(macro trace expr="variable")

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

Пример:

  Показать содержимое

 

  • Плюс 1

Рассказать о публикации


Ссылка на публикацию
5 070
[LESTA]
Разработчик
1 323 публикации
7 439 боёв

Scope

Scope - это хранилище данных, находящихся в распоряжении элемента. Не наследуетcя от родительских элементов. В разметке используется строгая типизация - все используемые переменные и их типы, а также events должны быть объявлены до момента использования в вычисляемом выражении, либо переданы из внешнего scope при вызове элемента.

Может содержать

  • переменные (var)
  • объявление события
  • вызов bind
  • dispatch события
  • $Animation контроллер для анимации переменных в scope
Примечание: если вы отправляли переменные без имени - список отправки и список получения должны быть согласованными, т.е. первая отправляемая переменная попадает в первую объявленную переменную.

 

Пример:

  Показать содержимое

 

  Показать содержимое

 

Scope можно описывать в разных частях элемента (пример: переменная level). В итоге при исполнении все части объединятся в один scope. Отображение содержимого scope:

(trace "$scope")

UBTRACE: Scope:
        Events: __onParamChange
        Vars:
                color : 1.67738e+07
                level : 0
                radius : 13

Примечание:

Переменные, переданные в элемент как аргументы определения, НЕ попадают в scope. В примере выше переменной textStyle нет в scope.

 

При создании экземпляра элемента можно изменять его значения переменных scope:

Создание экземляра элемента

(element LevelView 'PromoTitleTextStyle'
    (scope
        (level = 10)
        (radius = 40)
    )
)

Переменные scope при вызове элемента можно синхронизировать с переменными родительского scope

Создание экземляра элемента

(scope
    (var parentLevel:number = 15)
)
  
(element LevelView 'PromoTitleTextStyle'
    (scope
        (bind level "parentLevel")
    )
)

 

Переменным при прямом вызове можно давать имена, поэтому нет необходимости устанавливать их последовательно.

(element MinimapBG  _boolEnter="boolEnterParent" _scaleRatio="scaleRatioParent)
...
(def element MinimapBG (_scaleRatio:number, _boolEnter:bool))

или через контроллер $ Instance:

  Показать содержимое

 

В примерах выше переменные попадают в область видимости элемента только один раз, по вызову. Для дальнейшего обновления переменных во время выполнения вы можете применить эту конструкцию:

  Показать содержимое

или через контроллер $ Instance:

  Показать содержимое

 

 

  • Плюс 2

Рассказать о публикации


Ссылка на публикацию
5 070
[LESTA]
Разработчик
1 323 публикации
7 439 боёв

toplevel def

(def) или Definition

Конструкция (def object Name)  позволяет объявить глобальный объект, доступный для вызова из всей области в рамках рабочих каталогов.

 

Внимание!

Имя объекта должно быть уникальным. Не важно в одном или разных файлах эти объявления сделаны. Иначе будет ошибка и только первый объект будет создан

(def element TestView())
  
(def element TestView())
  
  
ERROR: Duplicate element definition: 'TestView'

 

  • Плюс 1

Рассказать о публикации


Ссылка на публикацию
5 070
[LESTA]
Разработчик
1 323 публикации
7 439 боёв

datahub

Datahub - это среда для передачи данных из Game Logic в Unbound.

$datahub object

Объект $datahub - это точка входа для использования datahub в разметке. Для доступа к datahub в *.unbound используйте ключевое слово "$datahub" внутри eval-выражения:

(scope)
    (var myEntity:cpp = "$datahub.getEntity(123)")
(scope)

Entity object

Сущности (Entities) хранятся в коллекциях (Collections), а также могут быть получены по идентификатору из объекта $datahub. Вы можете получить доступ к компонентам объекта с синтаксисом .dot, то есть:

(scope
    (var myEntity:cpp = "$datahub.getEntity(123)")
    (var goodComponent:cpp = "myEntity.goodComponent")
)

Component object

Компоненты - это объекты, содержащие реальные данные. Вы можете получить доступ к свойствам компонента с помощью синтаксиса .dot, то есть:

(scope
    (var myEntity:cpp = "$datahub.getEntity(123)")
    (var goodComponent:cpp = "myEntity.goodComponent")
    (var propertyOfGoodComponent:int = "goodComponent.someProperty")
)

 

  • Плюс 1

Рассказать о публикации


Ссылка на публикацию
5 070
[LESTA]
Разработчик
1 323 публикации
7 439 боёв

Debug

Выводит в лог сообщение об ошибке.

 

Активация:

  1. Перед запуском клиента в редакторе открыть актуальный файл "Мир Кораблей\bin\<current_build_number>\res\ engine_config.xml"
      Показать содержимое

     

  2. Добавить ключ "engine_config.xml/debug/enableUbPlayerViewLogger = true"
    <enableUbPlayerViewLogger>true</enableUbPlayerViewLogger>
      Показать содержимое

     

Логирование:

лог файл находится в каталоге "Мир Кораблей\profile\ub_player_errors.log"

  Показать содержимое

 

  • Плюс 2

Рассказать о публикации


Ссылка на публикацию
5 070
[LESTA]
Разработчик
1 323 публикации
7 439 боёв

UI Widgets

Symbol

Добавление на сцену MovieClip по его имени (linkage). Используется в объявлениях элемента с параметром layout=false. Т.е. создается display object без layout system'ы.

Пример использования:

(def element TestView() layout=false
    (symbol 'linkageName')
)
(symbol " 'torpedo_markers_ally_c' ")

Sprite

Добавление на сцену экземпляра класса Sprite. Используется в объявлениях элемента с параметром layout=false.

Пример использования:

  Показать содержимое

 

MC

Добавление на сцену экземпляра класса MovieClip по его имени (linkage). Используется в объявлениях элемента с параметром layout=true. (т.е. поддержка layout system и styles)

Пример использования:

(def element TestView() layout=true
    (mc 'FWCloseButtonSlimMC'
        (name = 'closeBtnCrossAnim')
        (bindcall gotoAndPlay "stateFrame")
    )
)

TextField

Добавление на сцену экземпляра класса TextField. Поддерживается во всех элементов с layout=true|false. Для задания текста используется свойство text или htmlText. Если будет задан text и htmlText, применится только последнее действие.

Пример использования:

(tf
    (text = 'Hello world!')
)

 

  Показать содержимое

 

Для случая когда текст слишком большой и не влазит в текстовое поле, существует свойство elideMode. Если elideMode=true, то текст обрезается под размер всего блока и последние 3 символа заменяются на ".". При каждом обрезании текста генерируются event textElideStatus в аргументе передается статус: обрезан текст или нет.

  Показать содержимое

substitute

substitute - метод textblock'а, который позволяет заменять подстроки на картинки.

init=true - обязательный аргумент

(tf
    (class $TextDefault19NM)
    (bindcall substitute imageOffset="_frameTextCount"
                        substitutionMap={'[test_icon]' : 'icon_ground_radar_ally' }
                        sourceText='radar: [test_icon] mouse: [KEY_LEFTMOUSE]'
                        postfix='_bg'
                        init=true
    )
)

 

Element

Block

Добавляет на сцену контейнер-экземпляр класса Sprite, Все вложенные блоки будут добавляться в этот контейнер и позиционироваться друг за другом взависимости от значения свойства стиля flow.

Для block существуют aliases:

  • block - вертикальный блок, дочерние элементы расположены сверху вниз
  • hblock - горизонтальный блок, дочерние элементы расположены слева направо
  • vtile - вертикальный tile блок, дочерние элементы расположены сверху вниз, оборачиваются на нижней границе родителя
  • htile - горизонтальный tile блок, дочерние элементы расположены слева направо, оборачиваются на правой границе родителя
  • reverse - вертикальный блок с обратным порядком элементов в блоке, дочерние элементы расположены снизу вверх
  • hreverse - горизонтальный блок с обратным порядком элементов в блоке, дочерние элементы расположены справа налево

 

Пример:

  Показать содержимое

 

backgroundImage

Добавляет на сцену экземпляр класса Bitmap.

  • передать путь до файла (для этого используется R-class - ресурсный менеджер)
  • передать текстуру из атласа - экземпляр класса BitmapData
  • url адрес до изображения в сети

 

Если блоку не заданы размеры в style, то после загрузки изображения размеры блока станут такими же как размеры изображения.

(bind backgroundImage "markerIcon")
----------------
(style
	(bind backgroundImage "'bitmap:' + toLower(markerIcon)")
)
----------------
(block
	(style
		(backgroundImage = 'url:../aircraft/icon_lock.png')
	)
)

 

Slider

Компонент, предоставляющий собой обычный Slider.

Имеет ряд переменных скоупа для настройки:

  • value (number) - текущее значение слайдера в единицах (не процент);
  • minimum (number) - минимальное значение;
  • maximum (number) - максимальное значение.
  • enabled (true/false) - доступен ли слайдер.

 

Может отправлять событие:

  • evValueChanged  - изменилось значение слайдера.

 

Значения параметров по умолчанию указаны в примере ниже:

  Показать содержимое

 

 

  • Плюс 1

Рассказать о публикации


Ссылка на публикацию
5 070
[LESTA]
Разработчик
1 323 публикации
7 439 боёв

Styles and CSS

Общее описание

Блоки поддерживают настройку параметров layout'а через style. Каждый блок обладает своим набором параметров стиля.

Настройка стиля у блока tf:

(tf
    (style
        (fontSize = 32)
        (textColor = 0xFFFFFFFF)
    )
    (text = 'Hello world!!!')
)

Настройка стиля у блока block:

(block
    (style
        (backgroundColor = 0xffff0000)
        (width = 100px)
        (height = 100px)
    )
)

Настройка стиля у блока mc:

  Показать содержимое

 

Стили можно описывать в отдельном определении. И передавать как параметр в блок в свойство class.

(def element TestView() layout = true
    (block
        (class BlockStyle)
    )
)
  
(def css BlockStyle()
    (backgroundColor = 0xffff0000)
    (width = 100px)
    (height = 100px)
)

Значение для свойства class может быть вычислено в выражении, таким образом можно стилизовать блоки в зависимости от условий.

  Показать содержимое

 

Если к блоку будет применено несколько стилей с одинаковыми свойствами, то последующие будут перезаписывать значения предыдущих. Важен порядок применения.

(block
    (class BlockStyle_1)
    (class BlockStyle_2)
)

Примечание:

Но если изменить свойство стиля непосредственно в style и передать css как параметр с тем же свойством. То порядок расположения применения стилей не важен. Блок style выполнится последним.

  Показать содержимое

 

Таблица стилей

Виды блоков:

  • базовые блоки: tf, mc, image, text_input.
  • контейнер-блоки (наследуются от базового блока): block (и все алиасы hblock, vtile, gtile, reverse, hreverse), list, view_holder, slider, scroll_bar, progress. scrollArea.

 

свойство аналог css кто поддерживает свойство принимаемые значения пример возможных значений
width width все блоки number, %, px 10px; 10%
minWidth min-width все блоки number, %, px 100px; 50%
maxWidth max-width все блоки number, %, px 100px; 50%
height height все блоки number, %, px 10px; 10%
minHeight min-height все блоки number, %, px 100px; 50%
maxHeight max-height все блоки number, %, px 100px; 50%
position position все блоки absolute, flow absolute
left left все блоки number, %, px 10px; 10%
right right все блоки number, %, px 10px; 10%
top top все блоки number, %, px 10px; 10%
bottom bottom все блоки number, %, px 10px; 10%
center смещение от центра все блоки number, %, px -170
hcenter смещение от центра по горизонтали все блоки number, %, px 10px; 10%
vcenter смещение от центра по вертикали все блоки number, %, px 10px; 10%
marginLeft margin-left все блоки number, %, px 10px
marginRight margin-right все блоки number, %, px 10px
marginTop margin-top все блоки number, %, px 10px
marginBottom margin-bottom все блоки number, %, px 10px
paddingLeft padding-left контейнер-блоки number, %, px 10px
paddingRight padding-right контейнер-блоки number, %, px 10px
paddingTop padding-top контейнер-блоки number, %, px 10px
paddingBottom padding-bottom контейнер-блоки number, %, px 10px
padding padding контейнер-блоки number, %, px 10px
backgroundColor background-color контейнер-блоки 0xARGB 0x1000ff00
backgroundImage background-image контейнер-блоки str, 'url: {url}', 'bitmap: {linkage}', 'symbol: {linkage}' backgroundImage = 'url:..\icons\ico.png'
backgroundSize

background-size

background-repeat

контейнер-блоки fill; crop; cover; repeat; autosize backgroundSize = "crop"
flow flex-direction контейнер-блоки Flow.HORISONTAL, Flow.VERTICAL, Flow.TILE_HORIZONTAL, Flow.TILE_VERTICAL flow = "Flow.HORISONTAL"
align

justify-content

align-items

контейнер-блоки left, right, bottom, top, center, middle align = "middle|right"
alpha opacity все блоки number от 0 до 1 1; 0; 0.4
fontSize font-size tf number 36
leading междустрочный интервал tf number  
letterSpacing letter-spacing tf number 2
fontFamily font-family tf str  
textColor color tf 0xRGB 0xCFC7A8
textAlign text-align tf left; right; center textAlign = "center"
multiline white-space tf bool true; false
ubScaleX transform: scaleX() все блоки number

изменяет scale блока по горизонтали

1.25

ubScaleY transform: scaleY() все блоки number

изменяет scale блока по вертикали

1.25

rotation поворот блока если его позиция absolute все блоки с позицией absolute number (значения угла поворота в градусах)
(style
    (rotation = 30)
)
pivotX

нулевая точка по X

используется для поворота, скейла, абсолютной позиции

все блоки с позицией absolute number, %, px
(style
    (pivotX = 50%)
)
или 
(style
    (pivotX = 100px)
)
pivotY

нулевая точка по Y

используется для поворота, скейла, абсолютной позиции

все блоки с позицией absolute number, %, px
(style
    (pivotY = 10%)
)
или 
(style
    (pivotY = 20px)
)
scaleX

масштаб по оси X

может быть отрицательным, применяется к блоку и его чайлдам

все блоки double

(style

    (scaleX = 1.2)
)
scaleY

масштаб по оси Y

может быть отрицательным, применяется к блоку и его чайлдам

все блоки double

(style

    (scaleY = -1.0)
)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BackgroundSize

(def element NationFlagsSmall () layout=true
    (style
        (bind backgroundImage "'url:../nation_flags/small/flag_USA.png'" init=false)
        (backgroundSize = "fill")
        (width = 117)
        (height = 72)
    )
)
  • cover - растягиваем текстуру по размеру контейнера с сохранением пропорций текстуры, чтобы она заполняла всю площадь, с обрезанием текстуры за пределами контейнера.
  • crop - обрезаем изображение по размеру контейнера.
  • fill - растягиваем изображение по размеру контейнера без сохранения пропорций.
  • align - позиционируем изображение по центру контейнера с обрезанием текстуры за пределами контейнера.

 

BackgroundRepeatX и BackgroundRepeatY

(block
    (style
        (width = 42) (height = 42)
        (backgroundImage = 'url:../service_kit/icons/icon_warning_red.png')
        (backgroundRepeatX = true)
        (backgroundRepeatY = false)
    )
)

Повторение изображение по горизонтали и/или вертикали. По-умолчанию отключено.

 

substitute

substitute - метод textblock'а, который позволяет заменять подстроки на картинки. 

init=true - обязательный аргумент

(tf
    (class $TextDefault19NM)
    (bindcall substitute imageOffset="_frameTextCount"
                        substitutionMap={'[test_icon]' : 'icon_ground_radar_ally' }
                        sourceText='radar: [test_icon] mouse: [KEY_LEFTMOUSE]'
                        postfix='_bg'
                        init=true
    )
)

 

Outline

Возможность задать стиль обводки для текста.

 

Внимание!

Нельзя использовать для большого числа разнообразного по размеру текста - быстро заполняется текстура с глифами и будет влиять на производительность.
Нежелательно применять анимацию со scale к такому тексту - могут быть артефакты и др.
(tf
    (class $TextDefault)
    (style
        (outlineColor = 0x08222A) #цвет обводки
        (outlineAlpha = 0.4) #прозрачность обводки
        (outlineThickness = 1) #толщина обводки
        (outlineScaled = false) #влияет ли скейл на толщину обводки. При анимации скейла текста всегда выставлять в false
    )
     
    (text = 'The quick brown fox jumps over the lazy dog. 1234567890?!-+')
)

 

scale9grid

набор параметров идентичен background9Slice в unbound1

(def element TestElement() layout=true
    (mc wows_logo
        (style
            (width = "500")
            (height = "500")
            (scale9grid = "rect(30)")
        )
    )
)

 

 

  • Плюс 1

Рассказать о публикации


Ссылка на публикацию
5 070
[LESTA]
Разработчик
1 323 публикации
7 439 боёв

CSS Tips and Tricks

Использование объекта стилей (аналог css-классов)

Создание объекта стилей:

(def css SomeStyleObject()
    (position = "absolute")
    (width = 100%)
    (height = 100%)
)

Вызов:

(block
    (class SomeStyleObject)
)

Пример реализации псевдокласса hover

  Показать содержимое

 

Срабарывание ховера при наведении на конкретную область, а не на весь блок

Если нужно задать определенныую область в качестве hitArea, то добавьте block с name='hoverArea' и передайте имя блока в свойство hitArea элемента parentElement с помощью объекта $target.

  Показать содержимое

 

Изменение стилей в зависимости от ширины/высоты экрана (аналог медаизапросов)

  Показать содержимое

 

 

  • Плюс 1

Рассказать о публикации


Ссылка на публикацию
5 070
[LESTA]
Разработчик
1 323 публикации
7 439 боёв

Live coding

Перезагрузка файлов *.unbound в бою.

 

Активация:

  1. Перед запуском клиента в редакторе открыть актуальный файл "Мир Кораблей\bin\<current_build_number>/res/engine_config.xml"
      Показать содержимое

     

  2. Добавить ключ "engine_config.xml/debug/enableUbPlayerReload = true"
    <enableUbPlayerReload>true</enableUbPlayerReload>
     
      Показать содержимое

     

Использование:

в бою сочетание клавиш Ctrl+F5

 

 

  • Плюс 2
  • Круто 1

Рассказать о публикации


Ссылка на публикацию
5 070
[LESTA]
Разработчик
1 323 публикации
7 439 боёв

Drag & Drop

 

Позволяет блоку, содержащему controller $Draggable перемещаться в блоки, содержащие controller $Droppable
controller $Draggable - текущий элемент/блок становится перетаскиваемым.
controller $Droppable - текущий элемент/блок становится слотом для перетаскиваемых элементов

 

  Показать содержимое

 

  • Плюс 1

Рассказать о публикации


Ссылка на публикацию
4 042
[GA]
Разработчик, Коллекционер
2 871 публикация
23 455 боёв

Smart Datahub

Представлен в UB2 следующими типами данных: dhdhEntitydhComponent и dhCollection. Обеспечивает возможность автоматически подписываться на события и тонко настраивать взаимодействие с ними.

 

1. Автоматическая подписка

Одна из основных особенностей Smart Datahub - возможность автоматически подписываться на распространённые события, такие как collection.evChildAdded и collection.evChildRemoved, к примеру.

По умолчанию она  ВКЛЮЧЕНА!  Не забывайте выключать её в местах, где она не нужна.

 

Для того чтобы отключить автоподписку, достаточно прописать autoUpdate=false в биндинге (по аналогии с (watch=true) или (init=true)). Тогда никаких подписок создано не будет и биндинг будет работать только с событиями, прописанными вручную.

Пример:

(scope
    (var myEntity:dhComponent= "getSingleComponent(CC.testComponent)" autoUpdate=false)
)

Список ивентов, на которые автоматически подписываются методы:

  Показать содержимое

2. Типы данных

2.1 Entity object

Сущности (Entities) хранятся в коллекциях (Collections), а также могут быть получены по идентификатору из объекта datahub. В Smart datahub сущности имеют тип dhEntity. Вы можете получить доступ к компонентам объекта с синтаксисом .dot, то есть:

(var myAutoEntity:dhEntity = "getPrimaryEntity(CC.test, 'id')")
(var myComponent:dhComponent = "myAutoEntity.test")

Сущности имеют два события:

  • evAdded - вызывается при добавлении компонента в сущность. Автоматическая подписка по переменным.
  • evRemoved - вызывается при удалении компонента из сущности. Автоматическая подписка по переменным.

 

Примеры:

(var waveHitDanger:dhComponent = "entity.waveHitDanger" autoUpdate=false (event "entity.evAdded"))
(var diplomacyRelationComponent:dhComponent = "entity.diplomacyRelation" autoUpdate=false (event "entity.evAdded") (event "entity.evRemoved"))

Список ивентов, на которые автоматически подписываются методы:

  Показать содержимое

 

2.2 Collection object

Коллекция - это набор сущностей, которые имеют общий компонент. Коллекции и компоненты очень близки, но коллекция содержит только сущности и не содержит никаких свойств.

В Smart datahub коллекции имеют тип dhCollection.

 

Использование коллекций:

  • getCollection(CC.someComponentName) - возвращает коллекцию сущностей, содержащих указанный компонент.
    • (var markersCollection:dhCollection = "$datahub.getCollection(CC.worldMarker)")
  • getChildByPath('collectionName') - дает доступ к подколлекциям по их имени.
    • (var visibleDangers:dhCollection = "getCollection(CC.visibleDanger)")
      (var searchPointCol:dhCollection = "visibleDangers.getChildByPath('submarineSearchPoints')")
  • firstEntity() - позволяет получить первую сущность, включающую в себя указанный компонент (подходит для использования, если в коллекции только один элемент (getSingleEntity), или если нужно взять любой элемент)
    • (var visibleDangers:dhCollection = "getCollection(CC.visibleDanger)")
      (var firstVisibleDanger:dhEntity = "visibleDangers.firstEntity()")

 

События коллекций:

  • evAdded - Вызывается при добавлении объекта в коллекцию. Автоматическая подписка по переменным.
    • (var diplomacyRelationCollection:dhCollection = "getCollection(CC.diplomacyRelation)")
      (vardiplomacyRelationComponent:dhComponent = "entity.diplomacyRelationComponent" autoUpdate=false (event "diplomacyRelationCollection.evAdded"))
  • evRemoved - Вызывается при удалении объекта из коллекции. Автоматическая подписка по переменным.
    • (var diplomacyRelationCollection:dhCollection = "getCollection(CC.diplomacyRelation)")
      (var diplomacyRelationComponent:dhComponent = "entity.diplomacyRelation" autoUpdate=false (event "diplomacyRelationCollection.evAdded") (event "diplomacyRelationCollection.evRemoved"))
  • evUpdated - Сортированная коллекция - это тип коллекции, компоненты которой организованы в определенном порядке. Во всех остальных аспектах это обычная коллекция. Вызывается при обновлении сортировки. Автоматическая подписка по переменным.
    • (var itemsList:array = "col.items" autoUpdate=false (event "col.evUpdated"))
  • evChildAdded - Вызывается при добавлении дочерней коллекции.
    • (var realPlayersCollection:dhCollection = "collection.getChildByPath('realPlayers')"  autoUpdate=false(event "collection.evChildAdded") (event "collection.evChildRemoved"))
  • evChildRemoved - Вызывается при удалении дочерней коллекции.
    • (var allyCollection:dhCollection = "collection ? collection.getChildByPath('team.ally.alive') : null"  autoUpdate=false(event "collection.evChildAdded") (event "collection.evChildRemoved"))

Список ивентов, на которые автоматически подписываются методы:

  Показать содержимое


2.3 Component object

Компоненты - это объекты, содержащие реальные данные. Вы можете получить доступ к свойствам компонента с помощью синтаксиса .dot:

(var myEntity:dhEntity = "getEntity(123)")
(var goodComponent:dhComponent = "myEntity.goodComponent")
(var propertyOfGoodComponent:int = "goodComponent.someProperty")

 

Любое арифметическое действие при участии null вернет результат null.

#Рассмотрим ситуацию, когда элемент существует, а какой-то энтити или компонента нет.
(scope
    # Здесь в ownCarrierComponent будет записан Null, если мы не на авианосцк или гибриде с авиагруппой
    (var ownCarrierComponent:dhComponent = "getSingleComponent(CC.aircarrier)")

    #Даже если ownCarrierComponent будет Null, то выражение ownCarrierComponent.activeSquadron тоже вернёт Null
    #Также вместо полноценного тернарника можно использовать сокращённую форму
    (var activeSquadron:number = "ownCarrierComponent.activeSquadron ?: ActiveSquadron.NONE" (event "ownCarrierComponent.evStateChanged"))

 

 

 

  • Плюс 1

Рассказать о публикации


Ссылка на публикацию
Гость
Эта тема закрыта для публикации новых ответов.

×