Исходник easy-dialog - легкое взаимодействие с локальными диалогами

chromiusj

fullstack eblan
Автор темы
Модератор
5,819
4,130
привет

Что это?
easy-dialog — это небольшая библиотека для MoonLoader, которая кардинально упрощает создание сложных, многоуровневых и интерактивных локальных диалогов. Библиотека была вдохновлена данным репозиторием. Библиотека берет на себя всю рутинную работу по управлению состоянием, пагинацией и анимацией, позволяя писать чистый, читаемый и легко поддерживаемый код. Особенно подойдет для тех, кому нет смысла подключать всякие имгуи, мимгуи,апмимгуи,даунмимгуи и т.д.

Основные возможности:
1. Каждый диалог — это объект.
2. Можно создавать диалоги, вызывая методы по цепочке.
3. Можно передать большой список, и библиотека сама разобьет его на страницы с кнопками навигации.
4. Легко создавать "полу-анимированные" диалоги с таймерами, прогресс-барами и другими эффектами с помощью коллбэка onUpdate.
5. Встроенные функции back() и home() для простого перемещения по сложным меню.
6. Быстрое создание стандартных диалогов (alert, confirm, prompt).
Зависимости:
- MoonLoader v.026+
- SAMPFUNCS v5.4.1+
Инициализация:
Lua:
easy_dialog.init()
Создание диалога:
Lua:
local myDialog = easy_dialog.Dialog.new()
Пояснение: Создает новый пустой объект диалога. Дальше к нему применяются методы-конструкторы.
Методы-конструкторы:
Эти методы вызываются по цепочке для настройки объекта диалога.
Lua:
:setCaption(string) - Устанавливает заголовок.
:setStyle(string) - Устанавливает стиль ('msgbox', 'list', 'input', 'password', 'tablist', 'tablist_headers').
:setButtons(string, string) - Устанавливает текст для левой и правой кнопок.
:setContent(string) - Устанавливает основной текст для простых диалогов ('msgbox', 'input').
:setItems(table) - Устанавливает список элементов. Включает пагинацию.
Пример: :setItems({"Элемент 1", "Элемент 2"})
Пример для tablist: :setItems({ {"Строка1 Кол1", "Строка1 Кол2"}, {"Строка2 Кол1", "Строка2 Кол2"} })
Lua:
:setHeaders(table) - Устанавливает заголовки для стиля tablist_headers.
:setItemsPerPage(number) - Устанавливает количество элементов на одной странице для пагинации.
Обработка событий (Callbacks):
Lua:
:setOnResponse(function(self, button, absolute_index, input_text)) - Главный обработчик. Вызывается, когда пользователь отвечает на диалог.
button: 1 (левая кнопка) или 0 (правая/Esc).
absolute_index: Абсолютный индекс выбранного элемента в исходном списке (начиная с 0), даже при пагинации. Для input диалогов равен -1.
input_text: Текст выбранной строки или текст, введенный пользователем.
:setOnUpdate(function(self, deltaTime)) - Вызывается каждый кадр, пока диалог активен. Идеально для анимации.
:setOnShow(function(self)) - Вызывается один раз перед первым показом диалога.
Управление диалогом
Lua:
myDialog() или easy_dialog.show(myDialog) - Показывает диалог и добавляет его в навигацию.
myDialog:update() - Мгновенно перерисовывает диалог с новым контентом (для анимации).
myDialog:close(button_id) - Программно закрывает диалог, имитируя нажатие кнопки.
easy_dialog.back() - Вернуться на предыдущий диалог в навигации.
easy_dialog.home() - Вернуться в самый первый показанный диалог.
Готовые шаблоны:
Lua:
easy_dialog.alert(caption, text, onOK) - Простое сообщение с одной кнопкой "OK".
easy_dialog.confirm(caption, text, onConfirm) - Диалог подтверждения "OK/Отмена". Коллбэк onConfirm получает true или false.
easy_dialog.prompt(caption, text, onInput) - Диалог ввода текста. Коллбэк onInput получает введенный текст.
Примеры работоспособности:
Lua:
local easy_dialog = require 'lib.easy-dialog'
local Dialog = easy_dialog.Dialog
local inicfg = require 'inicfg'

local font_flag = require('moonloader').font_flag
local INI_FILE_NAME = 'hud_settings'

local defaultConfig = {
  health_bar = { x = 100, y = 400, size = 1, text = "{FF0000}HP: 100" },
  armour_bar = { x = 200, y = 400, size = 1, text = "{CCCCCC}ARM: 100" },
  money_text = { x = 300, y = 400, size = 2, text = "{32CD32}MONEY: $50000" },
}

local hudConfig = inicfg.load(defaultConfig, INI_FILE_NAME)
local font_small = renderCreateFont('Arial', 8, font_flag.BOLD + font_flag.SHADOW)
local font_medium = renderCreateFont('Arial', 10, font_flag.BOLD + font_flag.SHADOW)
local font_large = renderCreateFont('Arial', 12, font_flag.BOLD + font_flag.SHADOW)
local fonts = { font_small, font_medium, font_large }

local function saveConfig()
  inicfg.save(hudConfig, INI_FILE_NAME)
  sampAddChatMessage('{33AA33}[HUD] Настройки сохранены.', -1)
end

local function createSettingDialog(elementKey, elementName)
  return Dialog.new()
    :setCaption("Настройка: " .. elementName)
    :setStyle('list')
    :setButtons("Выбрать", "Назад")
    :setItems({
      "Изменить позицию (X, Y)",
      "Изменить размер шрифта"
    })
    :setOnResponse(function(self, button, index)
      if button == 1 then
        if index == 0 then
          easy_dialog.prompt("Новая позиция X", "Введите новую координату X для '" .. elementName .. "':", function(inputX)
            local x = tonumber(inputX)
            if x then
              easy_dialog.prompt("Новая позиция Y", "Введите новую координату Y для '" .. elementName .. "':", function(inputY)
                local y = tonumber(inputY)
                if y then
                  hudConfig[elementKey].x = x
                  hudConfig[elementKey].y = y
                  saveConfig()
                  easy_dialog.back()
                else sampAddChatMessage("{FF0000}Некорректное значение Y.", -1) end
              end)
            else sampAddChatMessage("{FF0000}Некорректное значение X.", -1) end
          end)
        elseif index == 1 then
          local sizeDialog = Dialog.new()
            :setCaption("Выбор размера"):setStyle('list'):setButtons("Установить", "Отмена")
            :setItems({"Маленький (размер 0)", "Стандартный (размер 1)", "Большой (размер 2)"})
            :setOnResponse(function(s, b, list_index)
              if b == 1 then
                hudConfig[elementKey].size = list_index
                saveConfig()
                easy_dialog.back()
              end
            end)
          easy_dialog.show(sizeDialog, true)
        end
      else
        easy_dialog.back()
      end
    end)
end

local mainMenu = Dialog.new()
  :setCaption("Настройки HUD")
  :setStyle('list')
  :setButtons("Выбрать", "Закрыть")
  :setItems({
    "Положение полосы здоровья",
    "Положение полосы брони",
    "Положение текста денег",
    "{FF6347}Сбросить все настройки"
  })
  :setOnResponse(function(self, button, index)
    if button == 1 then
      if index == 0 then
        easy_dialog.show(createSettingDialog('health_bar', 'Полоса здоровья'))
      elseif index == 1 then
        easy_dialog.show(createSettingDialog('armour_bar', 'Полоса брони'))
      elseif index == 2 then
        easy_dialog.show(createSettingDialog('money_text', 'Текст денег'))
      elseif index == 3 then
        easy_dialog.confirm("Подтверждение", "Вы уверены, что хотите сбросить все настройки HUD к значениям по умолчанию?", function(ok)
          if ok then
            hudConfig = defaultConfig
            saveConfig()
            sampAddChatMessage('{FFA500}Настройки сброшены!', -1)
          end
        end)
      end
    end
  end)

function main()
  if not isSampfuncsLoaded() then print("easy-dialog: SAMPFUNCS is not loaded.") return end
  easy_dialog.init()

  sampRegisterChatCommand("hudsettings", function()
    mainMenu()
  end)

  sampAddChatMessage("Система настройки HUD загружена! Введите {FFFF00}/hudsettings{FFFFFF}.", 0x00BFFF)

  while true do
    wait(0)
    for _, elementData in pairs(hudConfig) do
      local currentFont = fonts[elementData.size + 1] or font_medium
      renderFontDrawText(currentFont, elementData.text, elementData.x, elementData.y, 0xFFFFFFFF)
    end
  end
end
Lua:
local easy_dialog = require 'lib.easy-dialog'
local Dialog = easy_dialog.Dialog

function main()
  while not isSampAvailable() do wait(100) end
  easy_dialog.init()
  if not isSampfuncsLoaded() then return end

  local doxLines = {
    "Номер: 3838339333",
    "Страна: Хуестан",
    "Регион: Мамкиных подсосов",
    "Оператор: Зародыш",
    "",
    "Возможные имена:",
    "Шлюха",
    "",
    "Возможные адреса:",
    "Россия, Санкт-Петербург",
    "",
    " Дата рождения: ещё не родился",
    "",
    " Интересовались: 63 человек",
    " Репутация: (99993 +) (468 -)",
    " Социальная метка:  Деффер (3)",
    " Комментариев: 748"
  }

  local animationStage = 0
  local stageTimer = 0

  local doxDialog = Dialog.new()
    :setCaption("Поиск информации")
    :setStyle('msgbox')
    :setButtons("Закрыть", "")
    :setOnShow(function(self)
      animationStage = 0
      stageTimer = 0
      self:setContent("Выполняется докс...")
    end)
    :setOnUpdate(function(self, deltaTime)
      if animationStage == -1 then return end
      stageTimer = stageTimer + deltaTime
      if animationStage == 0 then
        if stageTimer > 2.0 then
          animationStage = 1
          stageTimer = 0
          self:setContent("")
          self:update()
        end
      elseif animationStage > 0 then
        if stageTimer > 0.15 then
          if animationStage > #doxLines then
            animationStage = -1
            return
          end
          local currentTextTable = {}
          for i = 1, animationStage do
            table.insert(currentTextTable, doxLines[i])
          end
          local newContent = table.concat(currentTextTable, "\n")
          self:setContent(newContent)
          self:update()
          animationStage = animationStage + 1
          stageTimer = 0
        end
      end
    end)
    :setOnResponse(function(self)
      animationStage = -1
    end)

  sampRegisterChatCommand("dox", function()
    doxDialog()
  end)

  wait(-1)
end
Untitled.mp4.gif
 

Вложения

  • easy-dialog.lua
    10.7 KB · Просмотры: 4