Quellcode durchsuchen

Create editor-scripts.md

Niko McLys vor 3 Jahren
Ursprung
Commit
c79e86da57
1 geänderte Dateien mit 201 neuen und 0 gelöschten Zeilen
  1. 201 0
      docs/ru/manuals/editor-scripts.md

+ 201 - 0
docs/ru/manuals/editor-scripts.md

@@ -0,0 +1,201 @@
+---
+title: Скрипты редактора
+brief: Это руководство объясняет, как расширить редактор с помощью Lua
+---
+
+# Скрипты редактора
+
+Вы можете создавать пользовательские пункты меню и хуки жизненного цикла редактора, используя файлы Lua со специальным расширением: `.editor_script`. Используя эту систему, вы можете настраивать редактор для улучшения рабочего процесса разработки.
+
+## Время выполнения скрипта редактора
+
+Сценарии редактора выполняются внутри редактора, в Lua VM, эмулированной Java VM. Все скрипты работают в одном едином окружении, а это означает, что они могут взаимодействовать друг с другом. Вы можете подключать модули Lua, также как и файлы `.script`. Помните версии Lua, которые работают внутри редактора, отличаются, поэтому убедитесь, что ваш общий код совместим. Редактор использует Lua версии 5.2.x, а точнее [luaj](https://github.com/luaj/luaj) runtime, которая в настоящее время является единственным жизнеспособным решением для запуска Lua на JVM. Кроме этого, есть некоторые ограничения:
+- нет пакетов `debug` и `coroutine`;
+- нет `os.execute` - мы предоставляем более удобный и безопасный способ выполнения shell-скриптов в разделе [actions](#actions);
+- нет пакетов `os.tmpname` и `io.tmpfile` - в настоящее время скрипты редактора могут обращаться к файлам только внутри каталога проекта;
+- в настоящее время нет `os.rename`, хотя мы хотим его добавить;
+- нет `os.exit` и `os.setlocale`.
+
+Все расширения редактора, определенные в сценариях редактора, загружаются при открытии проекта. При извлечении библиотек, расширения перезагружаются, поскольку в библиотеках, от которых вы зависите, могут быть новые скрипты редактора. Во время этой перезагрузки изменения в ваших собственных скриптах редактора не учитываются, поскольку вы можете находиться в процессе их изменения. Чтобы перезагрузить и их, нужно выполнить команду Project → Reload Editor Scripts.
+## Анатомия `.editor_script`
+
+Каждый скрипт редактора должен возвращать модуль, подобный этому:
+```lua
+local M = {}
+
+function M.get_commands()
+  -- TODO
+end
+
+return M
+```
+Затем редактор собирает все скрипты редактора, определенные в проекте и библиотеках, загружает их в единую Lua VM и вызывает их при необходимости (подробнее об этом в разделах [commands](#commands) и [lifecycle hooks](#lifecycle-hooks)).
+
+## API редактора
+
+Вы можете взаимодействовать с редактором, используя пакет `editor`, который определяет этот API:
+- `editor.platform` - строка, либо `"x86_64-win32"` для Windows, `"x86_64-darwin"` для macOS, либо `"x86_64-linux"` для Linux.
+- `editor.get(node_id, property)` - получить значение определённого узла внутри редактора. Узлы в редакторе - это различные сущности, такие как файлы скриптов или коллекций, игровые объекты внутри коллекций, json-файлы, загруженные в качестве ресурсов, и т.д. `node_id` - это пользовательские данные, которые передаются в скрипт редактора самим редактором. Также вместо id узла можно передать путь к ресурсу, например `"/main/game.script"`. `property` - это строка. В настоящее время поддерживаются следующие свойства:
+  - `"path"` - путь к файлу из папки проекта для *resources* - сущностей, существующих в виде файлов. Пример возвращаемого значения: `"/main/game.script"`.
+  - `"text"` - текстовое содержимое ресурса, редактируемое как текст (например, файлы скриптов или json). Пример возвращаемого значения: `"function init(self)\nend"`. Обратите внимание, что это не то же самое, что читать файл лучше с помощью `io.open()`, потому что вы можете редактировать файл, не сохраняя его, и эти правки доступны только при обращении к свойству `"text"`.
+  - некоторые свойства отображаются в Properties, которые были выделены в Outline. Поддерживаются такие типы свойств контура:
+    - strings
+    - booleans
+    - numbers
+    - vec2/vec3/vec4
+    - resources
+
+    Обратите внимание, что некоторые из этих свойств могут быть доступны только для чтения, а некоторые могут быть недоступны в различных контекстах, поэтому вы должны использовать `editor.can_get`, прежде чем читать их, и `editor.can_set`, прежде чем заставить редактор установить их. Наведите курсор на имя свойства в Properties, чтобы увидеть всплывающую подсказку с информацией о том, как это свойство именуется в скриптах редактора. Вы можете установить свойства ресурса на nil, установив значение `""`.
+- `editor.can_get(node_id, property)` — проверьте, можете ли вы получить это свойство, чтобы `editor.get()` не выдал ошибку
+- `editor.can_set(node_id, property)` — проверьте, не приведет ли действие `"set"` с этим свойством к ошибке
+
+## Комманды
+
+Если модуль сценария редактора определяет функцию `get_commands`, она будет вызываться при перезагрузке расширения, и возвращенные команды будут доступны для использования внутри редактора в строке меню или в контекстных меню на панелях Assets и Outline. Например:
+```lua
+local M = {}
+
+function M.get_commands()
+  return {
+    {
+      label = "Remove Comments",
+      locations = {"Edit", "Assets"},
+      query = {
+        selection = {type = "resource", cardinality = "one"}
+      },
+      active = function(opts)
+        local path = editor.get(opts.selection, "path")
+        return ends_with(path, ".lua") or ends_with(path, ".script")
+      end,
+      run = function(opts)
+        local text = editor.get(opts.selection, "text")
+        return {
+          {
+            action = "set",
+            node_id = opts.selection,
+            property = "text",
+            value = strip_comments(text)
+          }
+        }
+      end
+    },
+    {
+      label = "Minify JSON"
+      locations = {"Assets"},
+      query = {
+        selection = {type = "resource", cardinality = "one"}
+      },
+      active = function(opts)
+        return ends_with(editor.get(opts.selection, "path"), ".json")
+      end,
+      run = function(opts)
+        local path = editor.get(opts.selection, "path")
+        return {
+          {
+            action = "shell",
+            command = {"./scripts/minify-json.sh", path:sub(2)}
+          }
+        }
+      end
+    }
+  }
+end
+
+return M
+```
+Редактор ожидает, что `get_commands()` вернет массив таблиц, каждая из которых описывает отдельную команду. Описание команды состоит из:
+
+- `label` (обязательно) - текст пункта меню, который будет отображаться пользователю
+- `locations` (обязательно) - массив из `"Edit"`, `"View"`, `"Assets"` или `"Outline"`, описывает место, где эта команда должна быть доступна. `"Edit"` и `"View"` означают строку меню сверху, `"Assets"` означает контекстное меню в панели Assets, а `"Outline"` означает контекстное меню в панели Outline.
+- `query` - способ для команды запросить у редактора необходимую информацию и определить, над какими данными она работает. Для каждого ключа в таблице `query` будет соответствующий ключ в таблице `opts`, который обратные вызовы `active` и `run` получают в качестве аргумента. Поддерживаемые ключи:
+  - `selection` означает, что эта команда действительна, когда есть что-то выбранное, и она действует на это выбранное.
+    - `type` - это тип выбранных узлов, которые интересуют команду, в настоящее время допустимы такие типы:
+      - `"resource"` - в Assets и Outline, ресурс - это выделенный элемент, который имеет соответствующий файл. В строке меню (Edit или View), ресурс - это открытый в данный момент файл;
+      - `"outline"` - то, что может быть показано в контуре. В Outline это выделенный элемент, в строке меню - открытый файл;
+    - `cardinality` определяет, сколько выделенных элементов должно быть. Если `"one"`, выбор, переданный в обратный вызов команды, будет единственным идентификатором узла. Если `"many"`, то выборка, передаваемая в обратный вызов команды, будет массивом из одного или нескольких идентификаторов узлов.
+- `active` - обратный вызов, который выполняется для проверки того, что команда активна, ожидается, что он вернет булево значение. Если `locations` включают `"Assets"` или `"Outline"`, `active` будет вызван при показе контекстного меню. Если местоположения включают `"Edit"` или `"View"`, active будет вызываться при каждом взаимодействии пользователя, например, при наборе текста на клавиатуре или щелчке мышью, поэтому убедитесь, что `active` работает относительно быстро.
+- `run` - обратный вызов, который выполняется, когда пользователь выбирает пункт меню, ожидается, что он вернет массив [actions](#actions).
+
+## Действия
+
+Действие - это таблица, описывающая, что должен сделать редактор. Каждое действие имеет ключ `action`. Действия бывают двух видов: отменяемые и не отменяемые.
+
+### Отменяемые действия
+
+
+Существующие отменяемые действия:
+- `"set"` — установка свойства узла в редакторе на некоторое значение. Пример:
+  ```lua
+  {
+    action = "set",
+    node_id = opts.selection,
+    property = "text",
+    value = "current time is " .. os.date()
+  }
+  ```
+  `"set"` действие требует наличия этих ключей:
+  - `node_id` — идентификатора узла данных пользователя. Также вы можете использовать путь к ресурсу, вместо идентификатора узла, полученного от редактора, например `"/main/game.script"`;
+  - `property` — свойство узла для установки, в настоящее время поддерживается только `"text"`;
+  - `value` — новое значение для свойства. Для свойства `"text"` это должна быть строка.
+
+### Неотменяемые действия
+
+Неотменяемые действие, очищает историю отмены, поэтому, если вы хотите отменить такое действие, вам придется использовать другие средства, например, контроль версий.
+
+Существующие неотменяемые действия:
+- `"shell"` — выполняет сценарий оболочки. Пример:
+  ```lua
+  {
+    action = "shell",
+    command = {
+      "./scripts/minify-json.sh",
+      editor.get(opts.selection, "path"):sub(2) -- trim leading "/"
+    }
+  }
+  ```
+  Действие `"shell"` требует ключ `command`, который представляет собой массив команд и их аргументов. Основное отличие от `os.execute` заключается в том, что поскольку это потенциально опасная операция, редактор покажет диалог подтверждения, спрашивающий пользователя, хочет ли он выполнить эту команду. Он будет помнить каждую команду, которую пользователь уже разрешил.
+
+### Действие при смешивании и побочные эффекты
+
+Вы можете смешивать отменяемые и неотменяемые действия. Действия выполняются последовательно, поэтому в зависимости от порядка действий вы потеряете возможность отменить часть команды.
+
+Вместо того чтобы возвращать действия из функций, которые их ожидают, вы можете просто читать и записывать в файлы напрямую, используя `io.open()`. Это вызовет перезагрузку ресурсов, которая очистит историю отмены.
+
+## Хуки жизненного цикла
+
+Существует специально обработанный файл скрипта редактора: `hooks.editor_script`, расположенный в корне вашего проекта, в том же каталоге, что и `game.project`. Этот и только этот скрипт редактора будет получать события жизненного цикла от редактора. Пример такого файла:
+```lua
+local M = {}
+
+function M.on_build_started(opts)
+  local file = io.open("assets/build.json", "w")
+  file:write("{\"build_time\": \"".. os.date() .."\"}")
+  file:close()
+end
+
+return M
+```
+
+Каждый хук жизненного цикла может возвращать действия или записывать в файлы в директории проекта.
+
+Существующие хуки жизненного цикла, которые могут определять `/hooks.editor_script`:
+- `on_build_started(opts)` — выполняется, когда игра собирается для запуска локально или на удаленной цели. Ваши изменения, будь то возвращенные действия или обновленное содержимое файлов, появятся в собранной игре. Вызов ошибки из этого хука прервет сборку. `opts` - это таблица, содержащая следующие ключи:
+  - `platform` — строка в формате `%arch%-%os%`, описывающая, для какой платформы он создан, в настоящее время всегда то же значение, что и в `editor.platform`.
+- `on_build_finished(opts)` — выполняется, когда сборка закончена успешно или нет `opts` представляет собой таблицу со следующими ключами:
+  - `platform` — также как и в `on_build_started`
+  - `success` — успешна ли сборка `true` или `false`
+- `on_bundle_started(opts)` — выполняется, при создании пакета или сборки HTML5-версии игры. Как и в случае с `on_build_started`, изменения, вызванные этим хуком, появятся в пакете, а ошибки прервут упаковывание. `opts` будет иметь такие ключи:
+  - `output_directory` — путь к файлу, указывающий на каталог с выводом пакета, например `"/path/to/project/build/default/__htmlLaunchDir"`
+  - `platform` — платформа, на которой игра упаковывается. Список возможных вариантов платформы см. в [Bob manual](/manuals/bob).
+  - `variant` — вариант упаковывания `"debug"`, `"release"` или `"headless"`
+- `on_bundle_finished(opts)` — выполняется, когда упаковывание завершается, независимо от того, успешно или нет. `opts` - это таблица с теми же данными, что и `opts` в `on_bundle_started`, плюс ключ `success`, указывающий на успешность сборки.
+- `on_target_launched(opts)` — выполняется, когда пользователь запускает игру и она успешно запускается. `opts` содержит ключ `url`, указывающий на запущенный сервис движка, например, `"http://127.0.0.1:35405"`
+- `on_target_terminated(opts)` — выполняется при закрытии запущенной игры, имеет те же опции, что и `on_target_launched`
+
+Обратите внимание, что хуки жизненного цикла в настоящее время являются функцией только для редактора, и они не выполняются Бобом при упаковывании из командной строки.
+
+## Скрипты редактора в библиотеках
+
+Вы можете опубликовать библиотеки для использования другими людьми, содержащие команды, и они будут автоматически подхвачены редактором. Хуки, с другой стороны, не могут быть подхвачены автоматически, так как они должны быть определены в файле, который находится в корневой папке проекта, а библиотеки раскрывают только вложенные папки. Это сделано для большего контроля над процессом сборки: вы по-прежнему можете создавать хуки жизненного цикла как простые функции в файлах `.lua`, чтобы пользователи вашей библиотеки могли требовать и использовать их в своих проектах `/hooks.editor_script`.
+
+Также обратите внимание, что хотя зависимости отображаются в Assets, они не существуют как файлы (это записи в zip-архиве), поэтому в настоящее время нет простого способа выполнить сценарий оболочки, который вы предоставляете в зависимости. Если вам это необходимо, вам придется извлечь предоставленные сценарии, получив их текст с помощью `editor.get()` и записав их куда-нибудь с помощью `file:write()`, например, в папку `build/editor-scripts/your-extension-name`.