SDK: Plugins - ixray-team/ixray-1.6-stcop GitHub Wiki
Обзор
[!IMPORTANT] Статус: Поддерживается Минимальная версия: 1.3
SDK поддерживает систему плагинов на двух языках:
- Lua
- Python
Плагины нужно поместить в корневую директорию в папку plugins
. Можно создавать подпапки, система ищет плагины рекурсивно.
Lua Плагины
Lua Плагины имеют ограниченную поддержку игрового скриптового API, включая такие базовые классы, как:
- ini_file
- reader
- fvector
- fmatrix
- net_packet
- rtoken_list
- token
- token_list
- Глобальное пространство и базовые библиотеки
Header
Для правильной инициализации плагина нужно задать в заголовке файла следующее:
-- desc: Описание
-- input: [аргумент, Описание], [аргумент, Описание]
desc
- описание функциональна плагина
input
- описание входных аргументов для вызова плагина. Данное поле является опциональным, если же не задавать данную строку или оставить её значение пустой, то в качестве входного параметра будет передан аргументlevel
, который является строкой с указанием директории текущего открытого уровня (так же, как и в случае с Lua плагинами)
Пример плагина
-- desc: Find `gaz66_01`
local ini_scene
function main(level)
ini_scene = ini_file("", 0, 1, 0, level.."scene_object.part")
ini_scene:section_for_each(test_section)
end
function test_section(name)
if ini_scene:line_exist(name, "reference_name") then
local object = ini_scene:r_string(name, "reference_name")
if (object == "statics\\vehicles\\cars\\gaz66_01") then
SemiLog("found gaz66_01!")
end
end
return false
end
Python плагины
В отличии от Lua
системы, плагины на Python
в свою очередь позволяют использовать всё доступное API для этого языка, но в свою очередь не имеют доступа к внутреннему функционалу X-Ray.
Header
Для правильной инициализации плагина нужно задать в заголовке файла следующее:
# desc: Описание
# input: [аргумент, Описание], [аргумент, Описание]
desc
- описание функциональна плагина
input
- описание входных аргументов для вызова плагина. Данное поле является опциональным, если же не задавать данную строку или оставить её значение пустой, то в качестве входного параметра будет передан аргументlevel
, который является строкой с указанием директории текущего открытого уровня (так же, как и в случае с Lua плагинами)
- В качестве описания может быть указан путь из
fs.ltx
, к примеру:[import_dir, $import$]
. В таком случае SDK автоматически сгенерирует аргумент и передаст в плагин
Пример плагина
# desc: Add paddings to trees textures
# input: [path, Textures directory], [paddins, Paddins size]
import os
import numpy as np
import cv2
import argparse
import imageio.v3 as iio
from scipy.ndimage import distance_transform_edt
def add_padding_dds(input_path, output_path, padding_size=10):
"""Добавляет педдинги к текстуре с альфа-каналом."""
# Загружаем DDS-текстуру
img_array = iio.imread(input_path)
# Проверяем, есть ли альфа-канал
if img_array.shape[-1] != 4:
return None # Пропускаем, если нет альфа-канала
# Разделяем каналы
b, g, r, a = cv2.split(img_array)
# Маска прозрачных пикселей
mask = a == 0
# Заполняем прозрачные области ближайшими цветными пикселями
for channel in [b, g, r]:
dist, index = distance_transform_edt(mask, return_indices=True)
channel[mask] = channel[index[0][mask], index[1][mask]]
# Собираем изображение обратно
new_image = cv2.merge((b, g, r, a))
# Сохраняем обратно в DDS (DXT3)
iio.imwrite(output_path, new_image, extension=".dds")
return True # Уведомляем о том, что файл был изменён
def process_folder(folder_path, padding_size=10):
"""Обрабатывает все текстуры в папке."""
for file_name in os.listdir(folder_path):
# Игнорируем bump-карты
if file_name.lower().endswith(".dds") and not file_name.lower().endswith(("_bump.dds", "_bump#.dds")):
input_path = os.path.join(folder_path, file_name)
output_path = input_path # Сохраняем с тем же именем
print(f"Обрабатываем: {file_name}")
try:
# Обрабатываем и удаляем файл, если он не был изменён
result = add_padding_dds(input_path, output_path, padding_size)
if result is None:
os.remove(input_path) # Удаляем файл, если он не был изменён
print(f"Файл {file_name} не имеет альфа-канала или не изменился, удалён.")
except Exception as e:
print(f"Ошибка при обработке {file_name}: {e}")
def main():
parser = argparse.ArgumentParser()
parser.add_argument("-path", type=str, required=True, help="Папка")
parser.add_argument("-paddins", type=int, required=True, help="Размер")
args = parser.parse_args()
process_folder(args.path, args.paddins)
if __name__ == "__main__":
main()