Compare commits
36 commits
file_hook_
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
39383b9fb1 | ||
|
a11efd275d | ||
|
745542b921 | ||
|
124002bb1f | ||
|
c617fc69b0 | ||
|
1a5b806f90 | ||
|
b13ef309af | ||
|
836d8e2f88 | ||
|
cdac4841db | ||
|
f1cf3ad7db | ||
|
088c0997f8 | ||
|
fcfd5477dd | ||
|
7075152aae | ||
|
c83ef8f911 | ||
|
70b3492d35 | ||
|
9633b29fed | ||
|
3b387c294d | ||
|
c87b0fd9c0 | ||
|
068cd94de3 | ||
|
de9468c6ab | ||
|
293ca07904 | ||
|
c1e05b5425 | ||
|
76e6d748b6 | ||
|
3182e06c25 | ||
|
99799a4a10 | ||
|
14242acb54 | ||
|
fea449b52f | ||
|
bacd49f221 | ||
|
24502d9957 | ||
|
87ba024f1d | ||
|
d1502daed9 | ||
|
7af8c22a8c | ||
|
ae1564f973 | ||
|
943313515f | ||
|
d83bf6d86c | ||
|
66360e3438 |
28 changed files with 3189 additions and 636 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,4 +1,6 @@
|
||||||
.temp
|
.temp
|
||||||
.vscode
|
.vscode
|
||||||
|
**/*.zip
|
||||||
vmf/bundleV1
|
vmf/bundleV1
|
||||||
vmf/bundleV2
|
vmf/bundleV2
|
||||||
|
node_modules
|
|
@ -1,9 +1,13 @@
|
||||||
# DMF contributors (sorted alphabetically)
|
# DMF contributors (sorted alphabetically)
|
||||||
Contribute to DMF -- add your name here!
|
Contribute to DMF -- add your name here!
|
||||||
|
+ [alxl](https://github.com/ItsAlxl)
|
||||||
+ [Aussiemon](https://github.com/Aussiemon)
|
+ [Aussiemon](https://github.com/Aussiemon)
|
||||||
|
+ [deluxghost](https://github.com/deluxghost)
|
||||||
|
+ [raindish](https://github.com/danreeves)
|
||||||
+ [Fracticality](https://github.com/fracticality)
|
+ [Fracticality](https://github.com/fracticality)
|
||||||
+ [grasmann](https://github.com/grasmann)
|
+ [grasmann](https://github.com/grasmann)
|
||||||
+ [philipdestroyer](https://github.com/philippedavid)
|
+ [philipdestroyer](https://github.com/philippedavid)
|
||||||
|
+ [ronvoluted](https://github.com/ronvoluted)
|
||||||
+ [SirAiedail](https://github.com/SirAiedail)
|
+ [SirAiedail](https://github.com/SirAiedail)
|
||||||
|
|
||||||
# VMF contributors (sorted alphabetically)
|
# VMF contributors (sorted alphabetically)
|
||||||
|
|
51
README.MD
51
README.MD
|
@ -1,13 +1,10 @@
|
||||||
<p align="center">
|
<div align="center">
|
||||||
<a href="#welcome-to-the-darktide-mod-framework-vmf-repository">
|
<picture>
|
||||||
<img
|
<source media="(prefers-color-scheme: dark)" srcset="./assets/dmf_logo_white.png">
|
||||||
alt="Darktide Mod Framework"
|
<source media="(prefers-color-scheme: light)" srcset="./assets/dmf_logo_black.png">
|
||||||
src="./assets/dmf_logo_black.png"
|
<img alt="Darktide Mod Framework" width="600" src="./assets/dmf_logo_black.png">
|
||||||
width="600"
|
</picture>
|
||||||
/>
|
</div>
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
## Welcome to the Darktide Mod Framework (DMF) Repository!
|
## Welcome to the Darktide Mod Framework (DMF) Repository!
|
||||||
|
|
||||||
|
@ -22,36 +19,6 @@ Mods created for the project may utilize:
|
||||||
* Rewritten, lightweight mod functions
|
* Rewritten, lightweight mod functions
|
||||||
* An on-event call system
|
* An on-event call system
|
||||||
|
|
||||||
The Darktide Mod Framework originally started in Warhammer End Times: Vermintide as an unofficial modding platform. In the time since, DMF has been rewritten and redesigned with contributions from many unique members of the community; culminating in this unified project.
|
The Darktide Mod Framework is a fork of the Vermintide Mod Framework that originally started in Warhammer End Times: Vermintide as an unofficial modding platform. In the time since, the framework has been rewritten and redesigned with contributions from many unique members of the community; culminating in this unified project.
|
||||||
|
|
||||||
For more information, check out **[the framework's wiki pages](https://github.com/Darktide-Mod-Framework/Darktide-Mod-Framework/wiki)**.
|
For more information, check out **[the framework's wiki pages](http://dmf-docs.darkti.de)**.
|
||||||
|
|
||||||
|
|
||||||
## Building the Framework
|
|
||||||
|
|
||||||
### Prerequisites:
|
|
||||||
|
|
||||||
- To start, you should be subscribed to the VMF Beta in Steam Workshop. (**[Warhammer End Times - Vermintide](https://steamcommunity.com/sharedfiles/filedetails/?id=1500136933)** or **[Warhammer: Vermintide 2](https://steamcommunity.com/sharedfiles/filedetails/?id=1500112422)**, depending on which version you want to compile)
|
|
||||||
- You should also install **[Vermintide Mod Builder (VMB)](https://github.com/Vermintide-Mod-Framework/Vermintide-Mod-Framework/wiki/Get-Vermintide-Mod-Builder)**.
|
|
||||||
|
|
||||||
|
|
||||||
### Building Steps:
|
|
||||||
|
|
||||||
1. Navigate to your VMB directory. Let's assume it's unpacked into a folder named `vermintide-mod-builder`.
|
|
||||||
2. Create a folder inside `vermintide-mod-builder` (we'll call it `vermintide-mod-framework`) and **[clone](https://git-scm.com/docs/git-clone)** in the VMF repository's contents.
|
|
||||||
3. Open a console/Command Prompt/PowerShell window inside your `vermintide-mod-builder` directory and use the following VMB command: `vmb build vmf -f vermintide-mod-framework -g [1|2]`, where the number after `-g` indicates the target Vermintide game.
|
|
||||||
|
|
||||||
|
|
||||||
You can find more VMB mod-building information in the **[Vermintide Mod Builder documentation](https://github.com/Vermintide-Mod-Framework/Vermintide-Mod-Builder/blob/master/README.md)**.
|
|
||||||
|
|
||||||
## Steam Workshop Links
|
|
||||||
|
|
||||||
Beta builds:
|
|
||||||
|
|
||||||
- [Warhammer End Times - Vermintide](https://steamcommunity.com/sharedfiles/filedetails/?id=1500136933)
|
|
||||||
- [Warhammer: Vermintide 2](https://steamcommunity.com/sharedfiles/filedetails/?id=1500112422)
|
|
||||||
|
|
||||||
Stable builds:
|
|
||||||
|
|
||||||
- [Warhammer End Times - Vermintide](https://steamcommunity.com/sharedfiles/filedetails/?id=1289946781)
|
|
||||||
- [Warhammer: Vermintide 2](https://steamcommunity.com/sharedfiles/filedetails/?id=1369573612)
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 193 KiB After Width: | Height: | Size: 146 KiB |
BIN
assets/dmf_logo_white.png
Normal file
BIN
assets/dmf_logo_white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 147 KiB |
|
@ -3,75 +3,108 @@ return {
|
||||||
en = "Mod Options",
|
en = "Mod Options",
|
||||||
es = "Configuración de mods",
|
es = "Configuración de mods",
|
||||||
ru = "Настройки модов",
|
ru = "Настройки модов",
|
||||||
|
["zh-cn"] = "模组选项",
|
||||||
|
ja = "Modオプション",
|
||||||
},
|
},
|
||||||
open_dmf_options = {
|
open_dmf_options = {
|
||||||
en = "Open Options Menu",
|
en = "Open Options Menu",
|
||||||
es = "Abrir el menu de configuración",
|
es = "Abrir el menu de configuración",
|
||||||
ru = "Открыть меню настроек",
|
ru = "Открыть меню настроек",
|
||||||
|
["zh-cn"] = "打开选项菜单",
|
||||||
|
ja = "オプションメニューを開く",
|
||||||
},
|
},
|
||||||
open_dmf_options_description = {
|
open_dmf_options_description = {
|
||||||
en = "Keybind for opening and closing mods options menu.",
|
en = "Keybind for opening and closing mods options menu.",
|
||||||
es = "Atajo para abrir/cerrar el menu de configuración de mods.",
|
es = "Atajo para abrir/cerrar el menu de configuración de mods.",
|
||||||
ru = "Клавиша/сочетание клавиш для открытия и закрытия меню настроек модов.",
|
ru = "Клавиша/сочетание клавиш для открытия и закрытия меню настроек модов.",
|
||||||
|
["zh-cn"] = "打开关闭模组选项菜单的按键绑定。",
|
||||||
|
ja = "オプションメニューを開閉するキーバインド",
|
||||||
},
|
},
|
||||||
dmf_options_scrolling_speed = {
|
dmf_options_scrolling_speed = {
|
||||||
en = "Options Menu Scrolling Speed",
|
en = "Options Menu Scrolling Speed",
|
||||||
es = "Velocidad de desplazamiento en el menu",
|
es = "Velocidad de desplazamiento en el menu",
|
||||||
ru = "Скорость прокрутки меню",
|
ru = "Скорость прокрутки меню",
|
||||||
|
["zh-cn"] = "选项菜单滚动速度",
|
||||||
|
ja = "オプションメニューのスクロール速度",
|
||||||
},
|
},
|
||||||
dmf_first_run_notification = {
|
dmf_first_run_notification = {
|
||||||
en = "Welcome to the Darktide Mod Framework. Mod options have been added to the Options Menu.",
|
en = "Welcome to the Darktide Mod Framework. Mod options have been added to the Options Menu.",
|
||||||
es = "Bienvenidos a el Mod Framework de Darktide. Hemos agregado las opciones de Mod a el menu de opciones.",
|
es = "Bienvenidos a el Mod Framework de Darktide. Hemos agregado las opciones de Mod a el menu de opciones.",
|
||||||
de = "Willkommen beim Darktide Mod Framework. Ein Button für Mod-Optionen wurde dem Hauptmenu hinzugefügt.",
|
de = "Willkommen beim Darktide Mod Framework. Ein Button für Mod-Optionen wurde dem Hauptmenu hinzugefügt.",
|
||||||
|
["zh-cn"] = "欢迎使用 Darktide Mod Framework。模组选项已添加到选项菜单。",
|
||||||
|
ru = "Добро пожаловать в Darktide Mod Framework. Параметры мода были добавлены в меню параметров.",
|
||||||
|
ja = "Darktide Mod Frameworkのご利用ありがとうございます。Modオプションがオプションメニューに追加されました。",
|
||||||
},
|
},
|
||||||
percent = {
|
percent = {
|
||||||
en = "%%",
|
en = "%%",
|
||||||
},
|
},
|
||||||
toggle_mod = {
|
toggle_mods = {
|
||||||
en = "Toggle Mod",
|
en = "Toggle Mods",
|
||||||
|
["zh-cn"] = "开启关闭模组",
|
||||||
|
ru = "Включение/выключение модов",
|
||||||
|
ja = "Modのオン/オフ",
|
||||||
},
|
},
|
||||||
toggle_mod_description = {
|
toggle_mods_description = {
|
||||||
en = "Enable or disable the mod",
|
en = "Enable or disable your mods.",
|
||||||
|
["zh-cn"] = "启用或禁用安装的模组。",
|
||||||
|
ru = "Включите или отключите ваши моды.",
|
||||||
|
ja = "Modを有効化/無効化します。",
|
||||||
},
|
},
|
||||||
ui_scaling = {
|
ui_scaling = {
|
||||||
en = "UI Scaling for FHD+ Resolutions",
|
en = "UI Scaling for FHD+ Resolutions",
|
||||||
es = "Reescalado de la interfaz para resoluciones Full HD+",
|
es = "Reescalado de la interfaz para resoluciones Full HD+",
|
||||||
ru = "Нормализация масштаба UI для FHD+ разрешений",
|
ru = "Нормализация масштаба интерфейса для FHD+ разрешений",
|
||||||
|
["zh-cn"] = "高分辨率 UI 缩放",
|
||||||
|
ja = "解像度FHD以上でのUIスケーリング",
|
||||||
},
|
},
|
||||||
ui_scaling_description = {
|
ui_scaling_description = {
|
||||||
en = "Automatically scale UI when resolution exceeds 1080p.",
|
en = "Automatically scale UI when resolution exceeds 1080p.",
|
||||||
es = "Redimensionar automáticamente la interfaz cuando la resolución exceda 1080p.",
|
es = "Redimensionar automáticamente la interfaz cuando la resolución exceda 1080p.",
|
||||||
ru = "Нормализует масштаб элементов интерфейса, если разрешений экрана превышает 1080p.",
|
ru = "Нормализует масштаб элементов интерфейса, если разрешений экрана превышает 1080p.",
|
||||||
|
["zh-cn"] = "分辨率超过 1080p 时自动缩放 UI",
|
||||||
|
ja = "1080pを超える解像度でUIの大きさを自動調節します。",
|
||||||
},
|
},
|
||||||
developer_mode = {
|
developer_mode = {
|
||||||
en = "Developer Mode",
|
en = "Developer Mode",
|
||||||
es = "Modo de desarrollo",
|
es = "Modo de desarrollo",
|
||||||
ru = "Режим разработчика",
|
ru = "Режим разработчика",
|
||||||
|
["zh-cn"] = "开发者模式",
|
||||||
|
ja = "開発者モード",
|
||||||
},
|
},
|
||||||
developer_mode_description = {
|
developer_mode_description = {
|
||||||
en = "Allows you to reload DMF and mods (CTRL+SHIFT+R), gives you access to some debug features.",
|
en = "Allows you to reload DMF and mods (CTRL+SHIFT+R), gives you access to some debug features.",
|
||||||
es = "Permite recargar los mods (CTRL+SHIFT+R) y configurar herramientas de depuración.",
|
es = "Permite recargar los mods (CTRL+SHIFT+R) y configurar herramientas de depuración.",
|
||||||
ru = "Позволяет перезагружать DMF и моды (CTRL+SHIFT+R), даёт доступ к инструментам отладки.",
|
ru = "Позволяет перезагружать DMF и моды (CTRL+SHIFT+R), даёт доступ к инструментам отладки.",
|
||||||
|
["zh-cn"] = "允许重新加载 DMF 和模组(CTRL+SHIFT+R),并启用一些调试功能。",
|
||||||
|
ja = "DMFとModのリロード (CTRL+SHIFT+R) や、いくつかのデバッグ機能へのアクセスを可能にします。",
|
||||||
},
|
},
|
||||||
show_developer_console = {
|
show_developer_console = {
|
||||||
en = "Show Developer Console",
|
en = "Show Developer Console",
|
||||||
es = "Mostrar el registro (log) a tiempo real",
|
es = "Mostrar el registro (log) a tiempo real",
|
||||||
ru = "Консоль разработчика",
|
ru = "Консоль разработчика",
|
||||||
|
["zh-cn"] = "显示开发者控制台",
|
||||||
|
ja = "開発者コンソールの表示",
|
||||||
},
|
},
|
||||||
show_developer_console_description = {
|
show_developer_console_description = {
|
||||||
en = "Opens up the new window showing game log in real time.",
|
en = "Opens up the new window showing game log in real time.",
|
||||||
es = "Abre una ventana que muestra el registro (log) del juego en tiempo real.",
|
es = "Abre una ventana que muestra el registro (log) del juego en tiempo real.",
|
||||||
ru = "Открывает новое окно, в которое в реальном времени выводится игровой лог.",
|
ru = "Открывает новое окно, в которое в реальном времени выводится игровой лог.",
|
||||||
|
["zh-cn"] = "在一个新窗口中显示游戏实时日志。",
|
||||||
|
ja = "ゲームのログをリアルタイムで表示する新たなウィンドウを開きます。",
|
||||||
},
|
},
|
||||||
toggle_developer_console = {
|
toggle_developer_console = {
|
||||||
en = "Toggle Developer Console",
|
en = "Toggle Developer Console",
|
||||||
es = "Abrir el registro (log) a tiempo real",
|
es = "Abrir el registro (log) a tiempo real",
|
||||||
ru = "Открыть/закрыть консоль разработчика",
|
ru = "Открыть/закрыть консоль разработчика",
|
||||||
|
["zh-cn"] = "开关开发者控制台",
|
||||||
|
ja = "開発者コンソールの表示/非表示",
|
||||||
},
|
},
|
||||||
show_network_debug_info = {
|
show_network_debug_info = {
|
||||||
en = "Log Network Calls",
|
en = "Log Network Calls",
|
||||||
es = "Depurar las llamadas de red",
|
es = "Depurar las llamadas de red",
|
||||||
ru = "Логирование сетевых вызовов",
|
ru = "Логирование сетевых вызовов",
|
||||||
|
["zh-cn"] = "记录网络调用日志",
|
||||||
|
ja = "ネットワーク呼び出しの記録",
|
||||||
},
|
},
|
||||||
show_network_debug_info_description = {
|
show_network_debug_info_description = {
|
||||||
en = "Log all the DMF network calls and all the data transfered with them.\n\n" ..
|
en = "Log all the DMF network calls and all the data transfered with them.\n\n" ..
|
||||||
|
@ -80,11 +113,17 @@ return {
|
||||||
"Esta información se registra en el nivel 'info'.",
|
"Esta información se registra en el nivel 'info'.",
|
||||||
ru = "Логирование всех сетевых вызовов DMF и передаваемых с ними данных.\n\n" ..
|
ru = "Логирование всех сетевых вызовов DMF и передаваемых с ними данных.\n\n" ..
|
||||||
"Для логирования используется метод 'info'.",
|
"Для логирования используется метод 'info'.",
|
||||||
|
["zh-cn"] = "记录所有 DMF 网络调用及其所传输数据的日志。\n\n" ..
|
||||||
|
"记录日志时会使用 'info' 方法。",
|
||||||
|
ja = "すべてのDMFのネットワーク呼び出しと通信データをログに記録します。\n\n" ..
|
||||||
|
"記録には 'info' メソッドが使用されます。",
|
||||||
},
|
},
|
||||||
log_ui_renderers_info = {
|
log_ui_renderers_info = {
|
||||||
en = "Log UI Renderers Creation Info",
|
en = "Log UI Renderers Creation Info",
|
||||||
es = "Depurar la renderización de la interfaz de usuario",
|
es = "Depurar la renderización de la interfaz de usuario",
|
||||||
ru = "Логирование информации при создании UI Renderer",
|
ru = "Логирование информации при создании UI Renderer",
|
||||||
|
["zh-cn"] = "记录 UI 渲染器创建信息",
|
||||||
|
ja = "UIレンダラー生成情報の記録",
|
||||||
},
|
},
|
||||||
log_ui_renderers_info_description = {
|
log_ui_renderers_info_description = {
|
||||||
en = "Log the UI Renderer's creator name and all the materials passed as the arguments.\n\n" ..
|
en = "Log the UI Renderer's creator name and all the materials passed as the arguments.\n\n" ..
|
||||||
|
@ -93,86 +132,131 @@ return {
|
||||||
"Esta información se registra en el nivel 'info'.",
|
"Esta información se registra en el nivel 'info'.",
|
||||||
ru = "Логирование имени создателя UI Renderer'а и всех материалов, переданных в качестве аргументов.\n\n" ..
|
ru = "Логирование имени создателя UI Renderer'а и всех материалов, переданных в качестве аргументов.\n\n" ..
|
||||||
"Для логирования используется метод 'info'.",
|
"Для логирования используется метод 'info'.",
|
||||||
|
["zh-cn"] = "记录 UI 渲染器的创建者名称以及作为参数传入的所有材质。\n\n" ..
|
||||||
|
"记录日志时会使用 'info' 方法。",
|
||||||
|
ja = "UIレンダラー生成元の名称と、引数として渡されたすべてのマテリアルをログに記録します。\n\n" ..
|
||||||
|
"記録には 'info' メソッドが使用されます。",
|
||||||
},
|
},
|
||||||
logging_mode = {
|
logging_mode = {
|
||||||
en = "Logging Settings",
|
en = "Logging Settings",
|
||||||
es = "Opciones de logging",
|
es = "Opciones de logging",
|
||||||
ru = "Настройки логирования",
|
ru = "Настройки логирования",
|
||||||
|
["zh-cn"] = "日志设置",
|
||||||
|
ja = "ログの設定",
|
||||||
},
|
},
|
||||||
settings_default = {
|
settings_default = {
|
||||||
en = "Default",
|
en = "Default",
|
||||||
es = "Valor por defecto",
|
es = "Valor por defecto",
|
||||||
ru = "Стандартные",
|
ru = "Стандартные",
|
||||||
|
["zh-cn"] = "默认",
|
||||||
|
ja = "デフォルト",
|
||||||
},
|
},
|
||||||
settings_custom = {
|
settings_custom = {
|
||||||
en = "Custom",
|
en = "Custom",
|
||||||
es = "Personalizado",
|
es = "Personalizado",
|
||||||
ru = "Пользовательские",
|
ru = "Пользовательские",
|
||||||
|
["zh-cn"] = "自定义",
|
||||||
|
ja = "カスタム",
|
||||||
},
|
},
|
||||||
output_mode_notification = {
|
output_mode_notification = {
|
||||||
en = "'Notification' Output",
|
en = "'Notification' Output",
|
||||||
|
["zh-cn"] = "'Notification' 通知输出",
|
||||||
|
ru = "Вывод 'Notification'",
|
||||||
|
ja = "'Notification' の出力",
|
||||||
},
|
},
|
||||||
output_mode_echo = {
|
output_mode_echo = {
|
||||||
en = "'Echo' Output",
|
en = "'Echo' Output",
|
||||||
es = "Mensajes de 'Echo'",
|
es = "Mensajes de 'Echo'",
|
||||||
ru = "Вывод 'Echo'",
|
ru = "Вывод 'Echo'",
|
||||||
|
["zh-cn"] = "'Echo' 回显输出",
|
||||||
|
ja = "'Echo' の出力",
|
||||||
},
|
},
|
||||||
output_mode_error = {
|
output_mode_error = {
|
||||||
en = "'Error' Output",
|
en = "'Error' Output",
|
||||||
es = "Mensajes de 'Error'",
|
es = "Mensajes de 'Error'",
|
||||||
ru = "Вывод 'Error'",
|
ru = "Вывод 'Error'",
|
||||||
|
["zh-cn"] = "'Error' 错误输出",
|
||||||
|
ja = "'Error' の出力",
|
||||||
},
|
},
|
||||||
output_mode_warning = {
|
output_mode_warning = {
|
||||||
en = "'Warning' Output",
|
en = "'Warning' Output",
|
||||||
es = "Mensajes de 'Warning'",
|
es = "Mensajes de 'Warning'",
|
||||||
ru = "Вывод 'Warning'",
|
ru = "Вывод 'Warning'",
|
||||||
|
["zh-cn"] = "'Warning' 警告输出",
|
||||||
|
ja = "'Warning' の出力",
|
||||||
},
|
},
|
||||||
output_mode_info = {
|
output_mode_info = {
|
||||||
en = "'Info' Output",
|
en = "'Info' Output",
|
||||||
es = "Mensajes de 'Info'",
|
es = "Mensajes de 'Info'",
|
||||||
ru = "Вывод 'Info'",
|
ru = "Вывод 'Info'",
|
||||||
|
["zh-cn"] = "'Info' 信息输出",
|
||||||
|
ja = "'Info' の出力",
|
||||||
},
|
},
|
||||||
output_mode_debug = {
|
output_mode_debug = {
|
||||||
en = "'Debug' Output",
|
en = "'Debug' Output",
|
||||||
es = "Mensajes de 'Debug'",
|
es = "Mensajes de 'Debug'",
|
||||||
ru = "Вывод 'Debug'",
|
ru = "Вывод 'Debug'",
|
||||||
|
["zh-cn"] = "'Debug' 调试输出",
|
||||||
|
ja = "'Debug' の出力",
|
||||||
},
|
},
|
||||||
output_disabled = {
|
output_disabled = {
|
||||||
en = "Disabled",
|
en = "Disabled",
|
||||||
es = "Desactivado",
|
es = "Desactivado",
|
||||||
ru = "Выключен",
|
ru = "Выключен",
|
||||||
|
["zh-cn"] = "禁用",
|
||||||
|
ja = "無効",
|
||||||
},
|
},
|
||||||
output_log = {
|
output_log = {
|
||||||
en = "Log",
|
en = "Log",
|
||||||
es = "Registro (log)",
|
es = "Registro (log)",
|
||||||
ru = "Лог",
|
ru = "Лог",
|
||||||
|
["zh-cn"] = "日志",
|
||||||
|
ja = "ログ",
|
||||||
},
|
},
|
||||||
output_chat = {
|
output_chat = {
|
||||||
en = "Chat",
|
en = "Chat",
|
||||||
es = "Chat",
|
es = "Chat",
|
||||||
ru = "Чат",
|
ru = "Чат",
|
||||||
|
["zh-cn"] = "聊天",
|
||||||
|
ja = "チャット",
|
||||||
},
|
},
|
||||||
output_notification = {
|
output_notification = {
|
||||||
en = "Notification",
|
en = "Notification",
|
||||||
|
["zh-cn"] = "通知",
|
||||||
|
ru = "Уведомление",
|
||||||
|
ja = "通知",
|
||||||
},
|
},
|
||||||
output_log_and_chat = {
|
output_log_and_chat = {
|
||||||
en = "Log & Chat",
|
en = "Log & Chat",
|
||||||
es = "Registro (log) y chat",
|
es = "Registro (log) y chat",
|
||||||
ru = "Лог и чат",
|
ru = "Лог и чат",
|
||||||
|
["zh-cn"] = "日志与聊天",
|
||||||
|
ja = "ログとチャット",
|
||||||
},
|
},
|
||||||
output_all = {
|
output_all = {
|
||||||
en = "All",
|
en = "All",
|
||||||
|
["zh-cn"] = "全部",
|
||||||
|
ru = "Все",
|
||||||
|
ja = "すべて",
|
||||||
},
|
},
|
||||||
output_log_and_notification = {
|
output_log_and_notification = {
|
||||||
en = "Log & Notification",
|
en = "Log & Notification",
|
||||||
|
["zh-cn"] = "日志与通知",
|
||||||
|
ru = "Лог и Уведомление",
|
||||||
|
ja = "ログと通知",
|
||||||
},
|
},
|
||||||
output_chat_and_notification = {
|
output_chat_and_notification = {
|
||||||
en = "Chat & Notification",
|
en = "Chat & Notification",
|
||||||
|
["zh-cn"] = "聊天与通知",
|
||||||
|
ru = "Чат и Уведомление",
|
||||||
|
ja = "チャットと通知",
|
||||||
},
|
},
|
||||||
chat_history_enable = {
|
chat_history_enable = {
|
||||||
en = "Chat Input History",
|
en = "Chat Input History",
|
||||||
es = "Historial de chat",
|
es = "Historial de chat",
|
||||||
ru = "История ввода чата",
|
ru = "История ввода чата",
|
||||||
|
["zh-cn"] = "聊天输入历史记录",
|
||||||
|
ja = "チャット入力の履歴",
|
||||||
},
|
},
|
||||||
chat_history_enable_description = {
|
chat_history_enable_description = {
|
||||||
en = "Saves all the messages and commands you typed in the chat window.\n\n" ..
|
en = "Saves all the messages and commands you typed in the chat window.\n\n" ..
|
||||||
|
@ -181,21 +265,31 @@ return {
|
||||||
"Puedes navegar por tu historial de comandos abriendo el chat y usando las flechas del teclado.",
|
"Puedes navegar por tu historial de comandos abriendo el chat y usando las flechas del teclado.",
|
||||||
ru = "Сохраняет все сообщения и команды, введённые в чате.\n\n" ..
|
ru = "Сохраняет все сообщения и команды, введённые в чате.\n\n" ..
|
||||||
"Чтобы пролистывать историю ввода, откройте чат и используйте клавиши \"стрелка вверх\" и \"стрелка вниз\".",
|
"Чтобы пролистывать историю ввода, откройте чат и используйте клавиши \"стрелка вверх\" и \"стрелка вниз\".",
|
||||||
|
["zh-cn"] = "保存所有你在聊天窗口内输入过的消息和命令。\n\n" ..
|
||||||
|
"你可以打开聊天窗口,按“上下方向键”浏览输入历史记录。",
|
||||||
|
ja = "チャット欄に記入したすべてのメッセージとコマンドを保存します。\n\n" ..
|
||||||
|
"入力履歴はチャットを開いて「上矢印」と「下矢印」キーで表示できます。",
|
||||||
},
|
},
|
||||||
chat_history_save = {
|
chat_history_save = {
|
||||||
en = "Save Input History Between Game Sessions",
|
en = "Save Input History Between Game Sessions",
|
||||||
es = "Guardar la entrada",
|
es = "Guardar la entrada",
|
||||||
ru = "Сохранять историю ввода между сеансами игры",
|
ru = "Сохранять историю ввода между сеансами игры",
|
||||||
|
["zh-cn"] = "重启游戏仍保留输入历史",
|
||||||
|
ja = "ゲームセッション間での入力履歴の保存",
|
||||||
},
|
},
|
||||||
chat_history_save_description = {
|
chat_history_save_description = {
|
||||||
en = "Your chat input history will be saved even after reloading your game (or just DMF).",
|
en = "Your chat input history will be saved even after reloading your game (or just DMF).",
|
||||||
es = "El texto que introduzcas en el chat se guardara incluso al recargar el juego (o solo DMF)",
|
es = "El texto que introduzcas en el chat se guardara incluso al recargar el juego (o solo DMF)",
|
||||||
ru = "Когда игрок выключает игру (или перезагружает DMF), DMF cохраняет историю ввода в файл настроек, чтобы загрузить её при следующем запуске игры.",
|
ru = "Когда игрок выключает игру (или перезагружает DMF), DMF cохраняет историю ввода в файл настроек, чтобы загрузить её при следующем запуске игры.",
|
||||||
|
["zh-cn"] = "即使重新启动游戏(或者重新加载 DMF),仍然保存聊天输入历史记录。",
|
||||||
|
ja = "ゲームの再起動 (またはDMFのリロード) 後もチャットの入力履歴が保持されます。",
|
||||||
},
|
},
|
||||||
chat_history_buffer_size = {
|
chat_history_buffer_size = {
|
||||||
en = "Input History Buffer Size",
|
en = "Input History Buffer Size",
|
||||||
es = "Número de comandos antiguos guardados",
|
es = "Número de comandos antiguos guardados",
|
||||||
ru = "Размер буфера истории ввода",
|
ru = "Размер буфера истории ввода",
|
||||||
|
["zh-cn"] = "输入历史记录大小",
|
||||||
|
ja = "入力履歴のバッファサイズ",
|
||||||
},
|
},
|
||||||
chat_history_buffer_size_description = {
|
chat_history_buffer_size_description = {
|
||||||
en = "Maximum number of saved entries.\n\n" ..
|
en = "Maximum number of saved entries.\n\n" ..
|
||||||
|
@ -204,16 +298,24 @@ return {
|
||||||
"ATENCIÓN: Cambiar esta preferencia borra el historial del chat.",
|
"ATENCIÓN: Cambiar esta preferencia borra el historial del chat.",
|
||||||
ru = "Максимальное количество сохраняемых записей.\n\n" ..
|
ru = "Максимальное количество сохраняемых записей.\n\n" ..
|
||||||
"ВНИМАНИЕ: изменение этой настройки очистит вашу историю ввода.",
|
"ВНИМАНИЕ: изменение этой настройки очистит вашу историю ввода.",
|
||||||
|
["zh-cn"] = "最大保存记录条数。\n\n" ..
|
||||||
|
"警告:更改此设置会删除所有聊天历史记录。",
|
||||||
|
ja = "履歴の最大保存数。\n\n" ..
|
||||||
|
"警告:この設定を変更するとチャット履歴が消去されます。",
|
||||||
},
|
},
|
||||||
chat_history_remove_dups = {
|
chat_history_remove_dups = {
|
||||||
en = "Remove Duplicate Entries",
|
en = "Remove Duplicate Entries",
|
||||||
es = "Eliminar lineas repetidas",
|
es = "Eliminar lineas repetidas",
|
||||||
ru = "Удалять повторяющиеся записи",
|
ru = "Удалять повторяющиеся записи",
|
||||||
|
["zh-cn"] = "删除重复记录",
|
||||||
|
ja = "重複する履歴の削除",
|
||||||
},
|
},
|
||||||
chat_history_remove_dups_mode = {
|
chat_history_remove_dups_mode = {
|
||||||
en = "Removal Mode",
|
en = "Removal Mode",
|
||||||
es = "Modo de eliminación de repetidos",
|
es = "Modo de eliminación de repetidos",
|
||||||
ru = "Режим удаления",
|
ru = "Режим удаления",
|
||||||
|
["zh-cn"] = "删除模式",
|
||||||
|
ja = "削除方式",
|
||||||
},
|
},
|
||||||
chat_history_remove_dups_mode_description = {
|
chat_history_remove_dups_mode_description = {
|
||||||
en = "Which duplicate entries should be removed.\n\n" ..
|
en = "Which duplicate entries should be removed.\n\n" ..
|
||||||
|
@ -225,21 +327,33 @@ return {
|
||||||
ru = "Повторяющиеся записи, которые будут удалены.\n\n" ..
|
ru = "Повторяющиеся записи, которые будут удалены.\n\n" ..
|
||||||
"-- ПОСЛЕДНИЕ --\nПредпоследняя запись будет удалена, если она совпадает с последней.\n\n" ..
|
"-- ПОСЛЕДНИЕ --\nПредпоследняя запись будет удалена, если она совпадает с последней.\n\n" ..
|
||||||
"-- ВСЕ --\nВсе записи, совпадающие с последней записью, будут удалены.",
|
"-- ВСЕ --\nВсе записи, совпадающие с последней записью, будут удалены.",
|
||||||
|
["zh-cn"] = "应该删除哪些重复记录。\n\n" ..
|
||||||
|
"-- 最新 --\n如果和最新一条匹配,则删除上一条记录。\n\n" ..
|
||||||
|
"-- 所有 --\n如果和最新一条匹配,则删除所有匹配的记录。",
|
||||||
|
ja = "重複した際にどの履歴を削除するか。\n\n" ..
|
||||||
|
"-- 直前 --\n直前の履歴が重複する場合、それを削除します。\n\n" ..
|
||||||
|
"-- すべて --\n重複するすべての履歴を削除します。",
|
||||||
},
|
},
|
||||||
settings_last = {
|
settings_last = {
|
||||||
en = "Last",
|
en = "Last",
|
||||||
es = "Última",
|
es = "Última",
|
||||||
ru = "Последние",
|
ru = "Последние",
|
||||||
|
["zh-cn"] = "最新",
|
||||||
|
ja = "直前",
|
||||||
},
|
},
|
||||||
settings_all = {
|
settings_all = {
|
||||||
en = "All",
|
en = "All",
|
||||||
es = "Todas",
|
es = "Todas",
|
||||||
ru = "Все",
|
ru = "Все",
|
||||||
|
["zh-cn"] = "所有",
|
||||||
|
ja = "すべて",
|
||||||
},
|
},
|
||||||
chat_history_commands_only = {
|
chat_history_commands_only = {
|
||||||
en = "Save only executed commands",
|
en = "Save only executed commands",
|
||||||
es = "Salvar unicamente los comandos ejecutados",
|
es = "Salvar unicamente los comandos ejecutados",
|
||||||
ru = "Сохранять только выполненные команды",
|
ru = "Сохранять только выполненные команды",
|
||||||
|
["zh-cn"] = "只保存执行的命令",
|
||||||
|
ja = "実行したコマンドのみを保存",
|
||||||
},
|
},
|
||||||
chat_history_commands_only_description = {
|
chat_history_commands_only_description = {
|
||||||
en = "Only successfully executed commands will be saved in the chat history.\n\n" ..
|
en = "Only successfully executed commands will be saved in the chat history.\n\n" ..
|
||||||
|
@ -248,28 +362,50 @@ return {
|
||||||
"ATENCIÓN: Cambiar esta preferencia borra el historial del chat.",
|
"ATENCIÓN: Cambiar esta preferencia borra el historial del chat.",
|
||||||
ru = "Только успешно выполненные команды будут сохранены в истории ввода.\n\n" ..
|
ru = "Только успешно выполненные команды будут сохранены в истории ввода.\n\n" ..
|
||||||
"ВНИМАНИЕ: изменение этой настройки очистит вашу историю ввода.",
|
"ВНИМАНИЕ: изменение этой настройки очистит вашу историю ввода.",
|
||||||
|
["zh-cn"] = "只有成功执行的命令才会保存在聊天历史记录里。\n\n" ..
|
||||||
|
"警告:更改此设置会删除所有聊天历史记录。",
|
||||||
|
ja = "実行できたコマンドのみをチャット履歴に保存します。\n\n" ..
|
||||||
|
"警告:この設定を変更するとチャット履歴が消去されます。",
|
||||||
},
|
},
|
||||||
|
|
||||||
chat_command_not_recognized = {
|
chat_command_not_recognized = {
|
||||||
en = "Command not recognized",
|
en = "Command not recognized",
|
||||||
|
["zh-cn"] = "无法识别的命令",
|
||||||
|
ru = "Команда не распознана",
|
||||||
|
ja = "不明なコマンド",
|
||||||
},
|
},
|
||||||
clean_chat_history = {
|
clean_chat_history = {
|
||||||
en = "cleans chat input history",
|
en = "cleans chat input history",
|
||||||
es = "Borra el historial de usuario",
|
es = "Borra el historial de usuario",
|
||||||
ru = "очищает историю ввода",
|
ru = "очищает историю ввода",
|
||||||
|
["zh-cn"] = "清除聊天输入历史记录",
|
||||||
|
ja = "チャット入力履歴の消去",
|
||||||
},
|
},
|
||||||
clean_chat_notifications = {
|
clean_chat_notifications = {
|
||||||
en = "cleans chat notification alerts"
|
en = "cleans chat notification alerts",
|
||||||
|
["zh-cn"] = "清除聊天通知警告",
|
||||||
|
ru = "очищает предупреждения об уведомлениях чата",
|
||||||
|
ja = "チャット通知警告の消去",
|
||||||
},
|
},
|
||||||
dev_console_opened = {
|
dev_console_opened = {
|
||||||
en = "Developer console opened.",
|
en = "Developer console opened.",
|
||||||
es = "Abierto la consola de desarrollo.",
|
es = "Abierto la consola de desarrollo.",
|
||||||
ru = "Консоль разработчика открыта.",
|
ru = "Консоль разработчика открыта.",
|
||||||
|
["zh-cn"] = "已打开开发者控制台。",
|
||||||
|
ja = "開発者コンソールを開きました。",
|
||||||
},
|
},
|
||||||
dev_console_closed = {
|
dev_console_closed = {
|
||||||
en = "Developer console closed.",
|
en = "Developer console closed.",
|
||||||
es = "Cerrado la consola de desarrollo.",
|
es = "Cerrado la consola de desarrollo.",
|
||||||
ru = "Консоль разработчика закрыта.",
|
ru = "Консоль разработчика закрыта.",
|
||||||
|
["zh-cn"] = "已关闭开发者控制台。",
|
||||||
|
ja = "開発者コンソールを閉じました。",
|
||||||
|
},
|
||||||
|
dev_console_close_warning = {
|
||||||
|
en = "The developer console is disabled, but must be closed manually.",
|
||||||
|
["zh-cn"] = "开发者控制台已禁用,但必须手动关闭。",
|
||||||
|
ru = "Консоль разработчика отключена, но ее необходимо закрыть вручную.",
|
||||||
|
ja = "開発者コンソールが無効になっていますが、手動で閉じる必要があります。",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
@ -278,116 +414,197 @@ return {
|
||||||
mutator_no_description_provided = {
|
mutator_no_description_provided = {
|
||||||
en = "No description provided.",
|
en = "No description provided.",
|
||||||
es = "No se proporcionó una descripción.",
|
es = "No se proporcionó una descripción.",
|
||||||
|
["zh-cn"] = "未提供描述。",
|
||||||
|
ru = "Описание не предоставлено.",
|
||||||
|
ja = "説明がありません。",
|
||||||
},
|
},
|
||||||
|
|
||||||
-- Difficulties' names
|
-- Difficulties' names
|
||||||
lowest = {
|
lowest = {
|
||||||
en = "Sedition"
|
en = "Sedition",
|
||||||
|
["zh-cn"] = "煽动",
|
||||||
|
ru = "Мятеж",
|
||||||
|
ja = "反乱",
|
||||||
},
|
},
|
||||||
low = {
|
low = {
|
||||||
en = "Uprising"
|
en = "Uprising",
|
||||||
|
["zh-cn"] = "暴乱",
|
||||||
|
ru = "Восстание",
|
||||||
|
ja = "アップライジング",
|
||||||
},
|
},
|
||||||
medium = {
|
medium = {
|
||||||
en = "Malice"
|
en = "Malice",
|
||||||
|
["zh-cn"] = "憎恶",
|
||||||
|
ru = "Злоба",
|
||||||
|
ja = "悪意",
|
||||||
},
|
},
|
||||||
high = {
|
high = {
|
||||||
en = "Heresy"
|
en = "Heresy",
|
||||||
|
["zh-cn"] = "异端",
|
||||||
|
ru = "Ересь",
|
||||||
|
ja = "異端",
|
||||||
},
|
},
|
||||||
highest = {
|
highest = {
|
||||||
en = "Damnation"
|
en = "Damnation",
|
||||||
|
["zh-cn"] = "诅咒",
|
||||||
|
ru = "Проклятие",
|
||||||
|
ja = "破滅",
|
||||||
},
|
},
|
||||||
|
|
||||||
-- Chat messages
|
-- Chat messages
|
||||||
broadcast_enabled_mutators = {
|
broadcast_enabled_mutators = {
|
||||||
en = "ENABLED MUTATORS",
|
en = "ENABLED MUTATORS",
|
||||||
es = "MUTACIONES ACTIVADAS",
|
es = "MUTACIONES ACTIVADAS",
|
||||||
|
["zh-cn"] = "启用突变器",
|
||||||
|
ru = "МУТАТОРЫ ВКЛЮЧЕНЫ",
|
||||||
|
ja = "ミューテーターが有効化されました",
|
||||||
},
|
},
|
||||||
broadcast_all_disabled = {
|
broadcast_all_disabled = {
|
||||||
en = "ALL MUTATORS DISABLED",
|
en = "ALL MUTATORS DISABLED",
|
||||||
es = "TODAS LAS MUTACIONES DESACTIVADAS",
|
es = "TODAS LAS MUTACIONES DESACTIVADAS",
|
||||||
|
["zh-cn"] = "禁用所有突变器",
|
||||||
|
ru = "ВСЕ МУТАТОРЫ ОТКЛЮЧЕНЫ",
|
||||||
|
ja = "すべてのミューテーターが無効化されました",
|
||||||
},
|
},
|
||||||
broadcast_disabled_mutators = {
|
broadcast_disabled_mutators = {
|
||||||
en = "MUTATORS DISABLED",
|
en = "MUTATORS DISABLED",
|
||||||
es = "MUTACIONES DESACTIVADAS",
|
es = "MUTACIONES DESACTIVADAS",
|
||||||
|
["zh-cn"] = "禁用突变器",
|
||||||
|
ru = "МУТАТОРЫ ОТКЛЮЧЕНЫ",
|
||||||
|
ja = "ミューテーターが無効化されました",
|
||||||
},
|
},
|
||||||
local_disabled_mutators = {
|
local_disabled_mutators = {
|
||||||
en = "Mutators disabled",
|
en = "Mutators disabled",
|
||||||
es = "Mutaciones desactivadas",
|
es = "Mutaciones desactivadas",
|
||||||
|
["zh-cn"] = "突变器已禁用",
|
||||||
|
ru = "Мутаторы отключены",
|
||||||
|
ja = "ミューテーターが無効化されました",
|
||||||
},
|
},
|
||||||
whisper_enabled_mutators = {
|
whisper_enabled_mutators = {
|
||||||
en = "[Automated message] This lobby has the following mutators active",
|
en = "[Automated message] This lobby has the following mutators active",
|
||||||
es = "[Mensaje automático] Esta partida tiene las siguientes mutaciones",
|
es = "[Mensaje automático] Esta partida tiene las siguientes mutaciones",
|
||||||
|
["zh-cn"] = "[自动消息] 此大厅激活了以下突变器",
|
||||||
|
ru = "[Автоматическое сообщение] В этом лобби активны следующие мутаторы",
|
||||||
|
ja = "[自動メッセージ] このロビーでは以下のミューテーターが有効になっています",
|
||||||
},
|
},
|
||||||
|
|
||||||
disabled_reason_not_server = {
|
disabled_reason_not_server = {
|
||||||
en = "because you're no longer the host",
|
en = "because you're no longer the host",
|
||||||
es = "porque ya no eres el anfitrión",
|
es = "porque ya no eres el anfitrión",
|
||||||
|
["zh-cn"] = "因为你不再是主机",
|
||||||
|
ru = "потому что вы больше не хост",
|
||||||
|
ja = "あなたがホストではなくなったため",
|
||||||
},
|
},
|
||||||
disabled_reason_difficulty_change = {
|
disabled_reason_difficulty_change = {
|
||||||
en = "DUE TO CHANGE IN DIFFICULTY",
|
en = "DUE TO CHANGE IN DIFFICULTY",
|
||||||
es = "DEBIDO A UN CAMBIO DE DIFICULTAD",
|
es = "DEBIDO A UN CAMBIO DE DIFICULTAD",
|
||||||
|
["zh-cn"] = "由于难度变更",
|
||||||
|
ru = "ИЗ-ЗА ИЗМЕНЕНИЯ СЛОЖНОСТИ",
|
||||||
|
ja = "難易度が変更されたため",
|
||||||
},
|
},
|
||||||
|
|
||||||
-- Interface
|
-- Interface
|
||||||
mutators_title = {
|
mutators_title = {
|
||||||
en = "Mutators",
|
en = "Mutators",
|
||||||
es = "Mutaciones",
|
es = "Mutaciones",
|
||||||
|
["zh-cn"] = "突变器",
|
||||||
|
ru = "Мутаторы",
|
||||||
|
ja = "ミューテーター",
|
||||||
},
|
},
|
||||||
mutators_banner_description = {
|
mutators_banner_description = {
|
||||||
en = "Enable and disable mutators",
|
en = "Enable and disable mutators",
|
||||||
es = "Activa y desactiva las mutaciones",
|
es = "Activa y desactiva las mutaciones",
|
||||||
|
["zh-cn"] = "启用和禁用突变器",
|
||||||
|
ru = "Включить и отключить мутаторы",
|
||||||
|
ja = "ミューテーターのオン/オフ",
|
||||||
},
|
},
|
||||||
no_mutators = {
|
no_mutators = {
|
||||||
en = "No mutators installed",
|
en = "No mutators installed",
|
||||||
es = "No hay mutaciones instaladas",
|
es = "No hay mutaciones instaladas",
|
||||||
|
["zh-cn"] = "未安装突变器",
|
||||||
|
ru = "Нет установленных мутаторов",
|
||||||
|
ja = "ミューテーターがインストールされていません",
|
||||||
},
|
},
|
||||||
no_mutators_description = {
|
no_mutators_description = {
|
||||||
en = "Subscribe to mods and mutators on the workshop",
|
en = "Subscribe to mods and mutators on the workshop",
|
||||||
es = "Subscribete a mutaciones en el Steam Workshop",
|
es = "Subscribete a mutaciones en el Steam Workshop",
|
||||||
|
["zh-cn"] = "在创意工坊订阅模组和突变器",
|
||||||
|
ru = "Подпишитесь на моды и мутаторы в мастерской Steam",
|
||||||
|
ja = "ワークショップでModやミューテーターをサブスクライブしてください",
|
||||||
},
|
},
|
||||||
|
|
||||||
-- Mutator widgets' tooltips
|
-- Mutator widgets' tooltips
|
||||||
tooltip_incompatible_mutators = {
|
tooltip_incompatible_mutators = {
|
||||||
en = "\n\n-- INCOMPATIBLE WITH MUTATORS --\n",
|
en = "\n\n-- INCOMPATIBLE WITH MUTATORS --\n",
|
||||||
es = "\n\n-- INCOMPATIBLE CON LAS MUTACIONES --\n",
|
es = "\n\n-- INCOMPATIBLE CON LAS MUTACIONES --\n",
|
||||||
|
["zh-cn"] = "\n\n-- 不兼容突变器 --\n",
|
||||||
|
ru = "\n\n-- НЕСОВМЕСТИМО С МУТАТОРАМИ --\n",
|
||||||
|
ja = "\n\n-- ミューテーターと互換性なし --\n",
|
||||||
},
|
},
|
||||||
tooltip_compatible_mutators = {
|
tooltip_compatible_mutators = {
|
||||||
en = "\n\n-- COMPATIBLE ONLY WITH MUTATORS --\n",
|
en = "\n\n-- COMPATIBLE ONLY WITH MUTATORS --\n",
|
||||||
es = "\n\n-- COMPATIBLE CON LAS MUTACIONES --\n",
|
es = "\n\n-- COMPATIBLE CON LAS MUTACIONES --\n",
|
||||||
|
["zh-cn"] = "\n\n-- 仅兼容突变器 --\n",
|
||||||
|
ru = "\n\n-- СОВМЕСТИМО ТОЛЬКО С МУТАТОРАМИ --\n",
|
||||||
|
ja = "\n\n-- ミューテーターとのみ互換性あり",
|
||||||
},
|
},
|
||||||
tooltip_compatible_with_all_mutators = {
|
tooltip_compatible_with_all_mutators = {
|
||||||
en = "\n\n-- COMPATIBLE WITH ALL MUTATORS --",
|
en = "\n\n-- COMPATIBLE WITH ALL MUTATORS --",
|
||||||
es = "\n\n-- COMPATIBLE CON TODAS LAS MUTACIONES --",
|
es = "\n\n-- COMPATIBLE CON TODAS LAS MUTACIONES --",
|
||||||
|
["zh-cn"] = "\n\n-- 兼容所有突变器 --\n",
|
||||||
|
ru = "\n\n-- СОВМЕСТИМО СО ВСЕМИ МУТАТОРАМИ --\n",
|
||||||
|
ja = "\n\n-- すべてのミューテーターと互換性あり --\n",
|
||||||
},
|
},
|
||||||
tooltip_incompatible_with_all_mutators = {
|
tooltip_incompatible_with_all_mutators = {
|
||||||
en = "\n\n-- INCOMPATIBLE WITH ALL MUTATORS --",
|
en = "\n\n-- INCOMPATIBLE WITH ALL MUTATORS --",
|
||||||
es = "\n\n-- INCOMPATIBLE CON TODAS LAS MUTACIONES --",
|
es = "\n\n-- INCOMPATIBLE CON TODAS LAS MUTACIONES --",
|
||||||
|
["zh-cn"] = "\n\n-- 不兼容所有突变器 --\n",
|
||||||
|
ru = "\n\n-- НЕСОВМЕСТИМО СО ВСЕМИ МУТАТОРАМИ --\n",
|
||||||
|
ja = "\n\n-- すべてのミューテーターと互換性なし --\n",
|
||||||
},
|
},
|
||||||
|
|
||||||
tooltip_incompatible_diffs = {
|
tooltip_incompatible_diffs = {
|
||||||
en = "\n\n-- INCOMPATIBLE WITH DIFFICULTIES --\n",
|
en = "\n\n-- INCOMPATIBLE WITH DIFFICULTIES --\n",
|
||||||
es = "\n\n-- INCOMPATIBLE CON LAS DIFICULTADES --\n",
|
es = "\n\n-- INCOMPATIBLE CON LAS DIFICULTADES --\n",
|
||||||
|
["zh-cn"] = "\n\n-- 不兼容难度 --\n",
|
||||||
|
ru = "\n\n-- НЕСОВМЕСТИМО СО СЛОЖНОСТЯМИ --\n",
|
||||||
|
ja = "\n\n-- 難易度と互換性なし --\n",
|
||||||
},
|
},
|
||||||
tooltip_compatible_diffs = {
|
tooltip_compatible_diffs = {
|
||||||
en = "\n\n-- COMPATIBLE ONLY WITH DIFFICULTIES --\n",
|
en = "\n\n-- COMPATIBLE ONLY WITH DIFFICULTIES --\n",
|
||||||
es = "\n\n-- COMPATIBLE CON LAS DIFICULTADES --\n",
|
es = "\n\n-- COMPATIBLE CON LAS DIFICULTADES --\n",
|
||||||
|
["zh-cn"] = "\n\n-- 仅兼容难度 --\n",
|
||||||
|
ru = "\n\n-- СОВМЕСТИМО ТОЛЬКО СО СЛОЖНОСТЯМИ --\n",
|
||||||
|
ja = "\n\n-- 難易度とのみ互換性あり --\n",
|
||||||
},
|
},
|
||||||
tooltip_compatible_with_all_diffs = {
|
tooltip_compatible_with_all_diffs = {
|
||||||
en = "\n\n-- COMPATIBLE WITH ALL DIFFICULTIES --",
|
en = "\n\n-- COMPATIBLE WITH ALL DIFFICULTIES --",
|
||||||
es = "\n\n-- COMPATIBLE CON TODAS LAS DIFICULTADES --",
|
es = "\n\n-- COMPATIBLE CON TODAS LAS DIFICULTADES --",
|
||||||
|
["zh-cn"] = "\n\n-- 兼容所有难度 --\n",
|
||||||
|
ru = "\n\n-- СОВМЕСТИМО СО ВСЕМИ СЛОЖНОСТЯМИ --\n",
|
||||||
|
ja = "\n\n-- すべての難易度と互換性あり --\n",
|
||||||
},
|
},
|
||||||
|
|
||||||
tooltip_conflicts = {
|
tooltip_conflicts = {
|
||||||
en = "\n\n-- CONFLICTS --\n",
|
en = "\n\n-- CONFLICTS --\n",
|
||||||
es = "\n\n-- CONFLICTOS --\n",
|
es = "\n\n-- CONFLICTOS --\n",
|
||||||
|
["zh-cn"] = "\n\n-- 冲突 --\n",
|
||||||
|
ru = "\n\n-- КОНФЛИКТЫ --\n",
|
||||||
|
ja = "\n\n-- 競合 --\n",
|
||||||
},
|
},
|
||||||
|
|
||||||
tooltip_append_mutator = {
|
tooltip_append_mutator = {
|
||||||
en = " (mutator)",
|
en = " (mutator)",
|
||||||
es = " (mutacion)",
|
es = " (mutacion)",
|
||||||
|
["zh-cn"] = "(突变)",
|
||||||
|
ru = " (мутатор)",
|
||||||
|
ja = " (ミューテーター)",
|
||||||
},
|
},
|
||||||
tooltip_append_difficulty = {
|
tooltip_append_difficulty = {
|
||||||
en = " (difficulty)",
|
en = " (difficulty)",
|
||||||
es = " (dificultad)",
|
es = " (dificultad)",
|
||||||
|
["zh-cn"] = "(难度)",
|
||||||
|
ru = " (сложность)",
|
||||||
|
ja = " (難易度)",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,9 @@ if not _io.initialized then
|
||||||
_io = dmf.deepcopy(Mods.lua.io)
|
_io = dmf.deepcopy(Mods.lua.io)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Local backup of the loadstring function
|
||||||
|
local _loadstring = Mods.lua.loadstring
|
||||||
|
|
||||||
local _mod_directory = "./../mods"
|
local _mod_directory = "./../mods"
|
||||||
|
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
|
@ -62,7 +65,7 @@ local function read_or_execute(file_path, args, return_type)
|
||||||
|
|
||||||
-- Either execute the data or leave it unmodified
|
-- Either execute the data or leave it unmodified
|
||||||
if return_type == "exec_result" or return_type == "exec_boolean" then
|
if return_type == "exec_result" or return_type == "exec_boolean" then
|
||||||
local func = loadstring(result, file_path)
|
local func = _loadstring(result, file_path)
|
||||||
result = func(args)
|
result = func(args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,197 +2,27 @@ local dmf = get_mod("DMF")
|
||||||
|
|
||||||
local InputUtils = require("scripts/managers/input/input_utils")
|
local InputUtils = require("scripts/managers/input/input_utils")
|
||||||
|
|
||||||
local PRIMARY_BINDABLE_KEYS = {
|
local MODIFIER_KEYS = {
|
||||||
["keyboard"] = {
|
["keyboard_left shift"] = {160, "shift", "keyboard", 161},
|
||||||
[8] = {"Backspace", "backspace"},
|
["keyboard_right shift"] = {160, "shift", "keyboard", 161},
|
||||||
[9] = {"Tab", "tab"},
|
["keyboard_shift"] = {160, "shift", "keyboard", 161},
|
||||||
[13] = {"Enter", "enter"},
|
["keyboard_left ctrl"] = {162, "ctrl", "keyboard", 163},
|
||||||
[20] = {"Caps Lock", "caps lock"},
|
["keyboard_right ctrl"] = {162, "ctrl", "keyboard", 163},
|
||||||
[32] = {"Space", "space"},
|
["keyboard_ctrl"] = {162, "ctrl", "keyboard", 163},
|
||||||
[33] = {"Page Up", "page up"},
|
["keyboard_left alt"] = {164, "alt", "keyboard", 165},
|
||||||
[34] = {"Page Down", "page down"},
|
["keyboard_right alt"] = {164, "alt", "keyboard", 165},
|
||||||
[35] = {"End", "end"},
|
["keyboard_alt"] = {164, "alt", "keyboard", 165},
|
||||||
[36] = {"Home", "home"},
|
|
||||||
[37] = {"Left", "left"},
|
|
||||||
[38] = {"Up", "up"},
|
|
||||||
[39] = {"Right", "right"},
|
|
||||||
[40] = {"Down", "down"},
|
|
||||||
[45] = {"Insert", "insert"},
|
|
||||||
[46] = {"Delete", "delete"},
|
|
||||||
[48] = {"0", "0"},
|
|
||||||
[49] = {"1", "1"},
|
|
||||||
[50] = {"2", "2"},
|
|
||||||
[51] = {"3", "3"},
|
|
||||||
[52] = {"4", "4"},
|
|
||||||
[53] = {"5", "5"},
|
|
||||||
[54] = {"6", "6"},
|
|
||||||
[55] = {"7", "7"},
|
|
||||||
[56] = {"8", "8"},
|
|
||||||
[57] = {"9", "9"},
|
|
||||||
[65] = {"A", "a"},
|
|
||||||
[66] = {"B", "b"},
|
|
||||||
[67] = {"C", "c"},
|
|
||||||
[68] = {"D", "d"},
|
|
||||||
[69] = {"E", "e"},
|
|
||||||
[70] = {"F", "f"},
|
|
||||||
[71] = {"G", "g"},
|
|
||||||
[72] = {"H", "h"},
|
|
||||||
[73] = {"I", "i"},
|
|
||||||
[74] = {"J", "j"},
|
|
||||||
[75] = {"K", "k"},
|
|
||||||
[76] = {"L", "l"},
|
|
||||||
[77] = {"M", "m"},
|
|
||||||
[78] = {"N", "n"},
|
|
||||||
[79] = {"O", "o"},
|
|
||||||
[80] = {"P", "p"},
|
|
||||||
[81] = {"Q", "q"},
|
|
||||||
[82] = {"R", "r"},
|
|
||||||
[83] = {"S", "s"},
|
|
||||||
[84] = {"T", "t"},
|
|
||||||
[85] = {"U", "u"},
|
|
||||||
[86] = {"V", "v"},
|
|
||||||
[87] = {"W", "w"},
|
|
||||||
[88] = {"X", "x"},
|
|
||||||
[89] = {"Y", "y"},
|
|
||||||
[90] = {"Z", "z"},
|
|
||||||
[91] = {"Win", "win"},
|
|
||||||
[92] = {"RWin", "right win"},
|
|
||||||
[96] = {"Num 0", "numpad 0"},
|
|
||||||
[97] = {"Num 1", "numpad 1"},
|
|
||||||
[98] = {"Num 2", "numpad 2"},
|
|
||||||
[99] = {"Num 3", "numpad 3"},
|
|
||||||
[100] = {"Num 4", "numpad 4"},
|
|
||||||
[101] = {"Num 5", "numpad 5"},
|
|
||||||
[102] = {"Num 6", "numpad 6"},
|
|
||||||
[103] = {"Num 7", "numpad 7"},
|
|
||||||
[104] = {"Num 8", "numpad 8"},
|
|
||||||
[105] = {"Num 9", "numpad 9"},
|
|
||||||
[106] = {"Num *", "numpad *"},
|
|
||||||
[107] = {"Num +", "numpad +"},
|
|
||||||
[109] = {"Num -", "numpad -"},
|
|
||||||
[110] = {"Num .", "numpad ."},
|
|
||||||
[111] = {"Num /", "numpad /"},
|
|
||||||
[112] = {"F1", "f1"},
|
|
||||||
[113] = {"F2", "f2"},
|
|
||||||
[114] = {"F3", "f3"},
|
|
||||||
[115] = {"F4", "f4"},
|
|
||||||
[116] = {"F5", "f5"},
|
|
||||||
[117] = {"F6", "f6"},
|
|
||||||
[118] = {"F7", "f7"},
|
|
||||||
[119] = {"F8", "f8"},
|
|
||||||
[120] = {"F9", "f9"},
|
|
||||||
[121] = {"F10", "f10"},
|
|
||||||
[122] = {"F11", "f11"},
|
|
||||||
[123] = {"F12", "f12"},
|
|
||||||
[144] = {"Num Lock", "num lock"},
|
|
||||||
[145] = {"Scroll Lock", "scroll lock"},
|
|
||||||
[166] = {"Browser Back", "browser back"},
|
|
||||||
[167] = {"Browser Forward", "browser forward"},
|
|
||||||
[168] = {"Browser Refresh", "browser refresh"},
|
|
||||||
[169] = {"Browser Stop", "browser stop"},
|
|
||||||
[170] = {"Browser Search", "browser search"},
|
|
||||||
[171] = {"Browser Favorites", "browser favorites"},
|
|
||||||
[172] = {"Browser Home", "browser home"},
|
|
||||||
[173] = {"Volume Mute", "volume mute"},
|
|
||||||
[174] = {"Volume Down", "volume down"},
|
|
||||||
[175] = {"Volume Up", "volume up"},
|
|
||||||
[176] = {"Next Track", "next track"},
|
|
||||||
[177] = {"Previous Track", "previous track"},
|
|
||||||
[178] = {"Stop", "stop"},
|
|
||||||
[179] = {"Play/Pause", "play pause"},
|
|
||||||
[180] = {"Mail", "mail"},
|
|
||||||
[181] = {"Media", "media"},
|
|
||||||
[182] = {"Start Application 1", "start app 1"},
|
|
||||||
[183] = {"Start Application 2", "start app 2"},
|
|
||||||
[186] = {";", ";"},
|
|
||||||
[187] = {"=", "="},
|
|
||||||
[188] = {",", ","},
|
|
||||||
[189] = {"-", "-"},
|
|
||||||
[190] = {".", "."},
|
|
||||||
[191] = {"/", "/"},
|
|
||||||
[192] = {"`", "`"},
|
|
||||||
[219] = {"[", "["},
|
|
||||||
[220] = {"\\", "\\"},
|
|
||||||
[221] = {"]", "]"},
|
|
||||||
[222] = {"'", "'"},
|
|
||||||
--?[226] = {"\", "oem_102 (> <)"},
|
|
||||||
[256] = {"Num Enter", "numpad enter"}
|
|
||||||
},
|
|
||||||
["mouse"] = {
|
|
||||||
[0] = {"Mouse Left", "mouse left"},
|
|
||||||
[1] = {"Mouse Right", "mouse right"},
|
|
||||||
[2] = {"Mouse Middle", "mouse middle"},
|
|
||||||
[3] = {"Mouse Extra 1", "mouse extra 1"},
|
|
||||||
[4] = {"Mouse Extra 2", "mouse extra 2"},
|
|
||||||
[10] = {"Mouse Wheel Up", "mouse wheel up"},
|
|
||||||
[11] = {"Mouse Wheel Down", "mouse wheel down"},
|
|
||||||
[12] = {"Mouse Wheel Left", "mouse wheel left"},
|
|
||||||
[13] = {"Mouse Wheel Right", "mouse wheel right"}
|
|
||||||
},
|
|
||||||
--[[ -- will work on this if it will be needed
|
|
||||||
["gamepad"] = {
|
|
||||||
[0] = {"", "d_up"},
|
|
||||||
[1] = {"", "d_down"},
|
|
||||||
[2] = {"", "d_left"},
|
|
||||||
[3] = {"", "d_right"},
|
|
||||||
[4] = {"", "start"},
|
|
||||||
[5] = {"", "back"},
|
|
||||||
[6] = {"", "left_thumb"},
|
|
||||||
[7] = {"", "right_thumb"},
|
|
||||||
[8] = {"", "left_shoulder"},
|
|
||||||
[9] = {"", "right_shoulder"},
|
|
||||||
[10] = {"", "left_trigger"},
|
|
||||||
[11] = {"", "right_trigger"},
|
|
||||||
[12] = {"", "a"},
|
|
||||||
[13] = {"", "b"},
|
|
||||||
[14] = {"", "x"},
|
|
||||||
[15] = {"", "y"},
|
|
||||||
}]]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
local OTHER_KEYS = {
|
-- Both are treated equally in keybinds, but these global keys aren't localized
|
||||||
-- modifier keys
|
local MODIFIER_KEYS_LOC_ALIAS = {
|
||||||
["left shift"] = {160, "Shift", "keyboard", 161},
|
keyboard_ctrl = "keyboard_left ctrl",
|
||||||
["right shift"] = {160, "Shift", "keyboard", 161},
|
keyboard_alt = "keyboard_left alt",
|
||||||
["shift"] = {160, "Shift", "keyboard", 161},
|
keyboard_shift = "keyboard_left shift",
|
||||||
["left ctrl"] = {162, "Ctrl", "keyboard", 163},
|
|
||||||
["right ctrl"] = {162, "Ctrl", "keyboard", 163},
|
|
||||||
["ctrl"] = {162, "Ctrl", "keyboard", 163},
|
|
||||||
["left alt"] = {164, "Alt", "keyboard", 165},
|
|
||||||
["right alt"] = {164, "Alt", "keyboard", 165},
|
|
||||||
["alt"] = {164, "Alt", "keyboard", 165},
|
|
||||||
-- hack for 'dmf.build_keybind_string' function
|
|
||||||
["no_button"] = {-1, ""}
|
|
||||||
}
|
|
||||||
|
|
||||||
local KEYS_INFO = {}
|
|
||||||
|
|
||||||
-- Populate KEYS_INFO: Index, readable name, device name
|
|
||||||
for input_device_name, input_device_keys in pairs(PRIMARY_BINDABLE_KEYS) do
|
|
||||||
for key_index, key_info in pairs(input_device_keys) do
|
|
||||||
KEYS_INFO[key_info[2]] = {key_index, key_info[1], input_device_name}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for key_id, key_data in pairs(OTHER_KEYS) do
|
|
||||||
KEYS_INFO[key_id] = key_data
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Can't use 'Device.released' because it will break keybinds if button is released when game window is not active.
|
|
||||||
local CHECK_INPUT_FUNCTIONS = {
|
|
||||||
keyboard = {
|
|
||||||
PRESSED = function(key_id) return Keyboard.pressed(KEYS_INFO[key_id][1]) end,
|
|
||||||
RELEASED = function(key_id) return Keyboard.button(KEYS_INFO[key_id][1]) == 0 end
|
|
||||||
},
|
|
||||||
mouse = {
|
|
||||||
PRESSED = function(key_id) return Mouse.pressed(KEYS_INFO[key_id][1]) end,
|
|
||||||
RELEASED = function(key_id) return Mouse.button(KEYS_INFO[key_id][1]) == 0 end
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
local _raw_keybinds_data = {}
|
local _raw_keybinds_data = {}
|
||||||
local _keybinds = {}
|
local _keybinds = {}
|
||||||
local _pressed_key
|
|
||||||
|
|
||||||
local ERRORS = {
|
local ERRORS = {
|
||||||
PREFIX = {
|
PREFIX = {
|
||||||
|
@ -203,12 +33,17 @@ local ERRORS = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local SUPPORTED_DEVICES = {
|
||||||
|
"keyboard",
|
||||||
|
"mouse",
|
||||||
|
}
|
||||||
|
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
-- ##### Local functions ###############################################################################################
|
-- ##### Local functions ###############################################################################################
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
|
|
||||||
|
-- @TODO: Link this input service to the player's input service and find some way to see if it's blocked
|
||||||
local function is_dmf_input_service_active()
|
local function is_dmf_input_service_active()
|
||||||
-- @TODO: Implement check for active DMF input service
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -239,115 +74,261 @@ local function perform_keybind_action(data, is_pressed)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- #####################################################################################################################
|
||||||
|
-- ##### Input service functions #######################################################################################
|
||||||
|
-- #####################################################################################################################
|
||||||
|
|
||||||
|
local function is_modifier_pressed(modifier)
|
||||||
|
return (Keyboard.button(MODIFIER_KEYS[modifier][1]) + Keyboard.button(MODIFIER_KEYS[modifier][4])) > 0
|
||||||
|
end
|
||||||
|
|
||||||
|
local function default_boolean()
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local function default_vector3()
|
||||||
|
return Vector3(0, 0, 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function default_float()
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
local function boolean_combine(value_one, value_two)
|
||||||
|
return value_one or value_two
|
||||||
|
end
|
||||||
|
|
||||||
|
local function vector3_combine(value_one, value_two)
|
||||||
|
if Vector3.length(value_two) < Vector3.length(value_one) then
|
||||||
|
return value_one
|
||||||
|
else
|
||||||
|
return value_two
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function float_combine(value_one, value_two)
|
||||||
|
return math.max(value_one, value_two)
|
||||||
|
end
|
||||||
|
|
||||||
|
local ACTION_TYPES = {
|
||||||
|
pressed = {
|
||||||
|
device_func = "pressed",
|
||||||
|
type = "boolean",
|
||||||
|
default_device_func = default_boolean,
|
||||||
|
combine_func = boolean_combine
|
||||||
|
},
|
||||||
|
held = {
|
||||||
|
device_func = "held",
|
||||||
|
type = "boolean",
|
||||||
|
default_device_func = default_boolean,
|
||||||
|
combine_func = boolean_combine
|
||||||
|
},
|
||||||
|
released = {
|
||||||
|
device_func = "released",
|
||||||
|
type = "boolean",
|
||||||
|
default_device_func = default_boolean,
|
||||||
|
combine_func = boolean_combine
|
||||||
|
},
|
||||||
|
axis = {
|
||||||
|
device_func = "axis",
|
||||||
|
type = "vector3",
|
||||||
|
default_device_func = default_vector3,
|
||||||
|
combine_func = vector3_combine
|
||||||
|
},
|
||||||
|
button = {
|
||||||
|
device_func = "button",
|
||||||
|
type = "float",
|
||||||
|
default_device_func = default_float,
|
||||||
|
combine_func = float_combine
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
local function _enabler_func(cb, action_type, enablers)
|
||||||
|
for _, enabler in ipairs(enablers) do
|
||||||
|
if not enabler.device:held(enabler.index) then
|
||||||
|
return ACTION_TYPES[action_type].default_device_func()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return cb()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function _disabler_func(cb, action_type, disablers)
|
||||||
|
for _, disabler in ipairs(disablers) do
|
||||||
|
if disabler.device:held(disabler.index) then
|
||||||
|
return ACTION_TYPES[action_type].default_device_func()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return cb()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function get_corresponding_device(key_id)
|
||||||
|
for _, device_type in pairs(SUPPORTED_DEVICES) do
|
||||||
|
|
||||||
|
local device = Managers.input:_find_active_device(device_type)
|
||||||
|
if device then
|
||||||
|
|
||||||
|
local index = device:button_index(key_id)
|
||||||
|
if index then
|
||||||
|
return {
|
||||||
|
device = device,
|
||||||
|
index = index,
|
||||||
|
key_id = key_id,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
index = device:axis_index(key_id)
|
||||||
|
if index then
|
||||||
|
return {
|
||||||
|
device = device,
|
||||||
|
index = index,
|
||||||
|
key_id = key_id,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function get_key_info(keybind)
|
||||||
|
local main = keybind.main
|
||||||
|
local e = keybind.enablers
|
||||||
|
local d = keybind.disablers
|
||||||
|
|
||||||
|
local info = get_corresponding_device(main)
|
||||||
|
|
||||||
|
if info then
|
||||||
|
if #e > 0 then
|
||||||
|
local enablers = {}
|
||||||
|
|
||||||
|
for _, key in ipairs(e) do
|
||||||
|
local enabler = get_corresponding_device(key)
|
||||||
|
|
||||||
|
if enabler then
|
||||||
|
enablers[#enablers + 1] = enabler
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
info.enablers = enablers
|
||||||
|
end
|
||||||
|
|
||||||
|
if #d > 0 then
|
||||||
|
local disablers = {}
|
||||||
|
|
||||||
|
for _, key in ipairs(d) do
|
||||||
|
local disabler = get_corresponding_device(key)
|
||||||
|
|
||||||
|
if disabler then
|
||||||
|
disablers[#disablers + 1] = disabler
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
info.disablers = disablers
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return info
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function create_eval_func(keybind)
|
||||||
|
local info = get_key_info(keybind)
|
||||||
|
if info then
|
||||||
|
|
||||||
|
local eval_func
|
||||||
|
if keybind.trigger == "held" then
|
||||||
|
eval_func = callback(info.device, keybind.trigger, info.index)
|
||||||
|
else
|
||||||
|
local function func(device, trigger, index)
|
||||||
|
return device[trigger](index)
|
||||||
|
end
|
||||||
|
|
||||||
|
eval_func = callback(func, info.device:raw_device(), keybind.trigger, info.index)
|
||||||
|
end
|
||||||
|
|
||||||
|
if info.enablers then
|
||||||
|
eval_func = callback(_enabler_func, eval_func, keybind.trigger, info.enablers)
|
||||||
|
end
|
||||||
|
|
||||||
|
if info.disablers then
|
||||||
|
eval_func = callback(_disabler_func, eval_func, keybind.trigger, info.disablers)
|
||||||
|
end
|
||||||
|
|
||||||
|
return eval_func
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
-- ##### DMF internal functions and variables ##########################################################################
|
-- ##### DMF internal functions and variables ##########################################################################
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
|
|
||||||
-- Checks for pressed and released keybinds, performs keybind actions.
|
-- Checks for pressed and released keybinds, performs keybind actions.
|
||||||
-- * Checks for both right and left key modifiers (ctrl, alt, shift).
|
-- * Right and left key modifiers (ctrl, alt, shift) are checked separately.
|
||||||
-- * If some keybind is pressed, won't check for other keybinds until this keybind is released.
|
-- * If several mods bound the same keys, keybind action will be performed for all of them when pressed.
|
||||||
-- * If several mods bound the same keys, keybind action will be performed for all of them, when keybind is pressed.
|
-- * Keybind is considered released when it was previously pressed and is no longer.
|
||||||
-- * Keybind is considered released, when its primary key is released.
|
|
||||||
function dmf.check_keybinds()
|
function dmf.check_keybinds()
|
||||||
local ctrl_pressed = (Keyboard.button(KEYS_INFO["ctrl"][1]) + Keyboard.button(KEYS_INFO["ctrl"][4])) > 0
|
|
||||||
local alt_pressed = (Keyboard.button(KEYS_INFO["alt"][1]) + Keyboard.button(KEYS_INFO["alt"][4])) > 0
|
|
||||||
local shift_pressed = (Keyboard.button(KEYS_INFO["shift"][1]) + Keyboard.button(KEYS_INFO["shift"][4])) > 0
|
|
||||||
|
|
||||||
if not _pressed_key then
|
-- For every keybind
|
||||||
for primary_key, keybinds_data in pairs(_keybinds) do
|
for _, keybind_data in ipairs(_keybinds) do
|
||||||
if keybinds_data.check_pressed(primary_key) then
|
|
||||||
for _, keybind_data in ipairs(keybinds_data) do
|
|
||||||
|
|
||||||
local all_pressed = true
|
-- If the keybind is pressed
|
||||||
for enabler, _ in pairs(keybind_data.enablers) do
|
if keybind_data.eval_func() then
|
||||||
|
|
||||||
-- Check that every enabler key is pressed
|
-- Peform the keybind action once
|
||||||
if OTHER_KEYS[enabler] and
|
if (not keybind_data.pressed) and perform_keybind_action(keybind_data, true) then
|
||||||
(
|
|
||||||
Keyboard.button(KEYS_INFO[enabler][1]) +
|
|
||||||
Keyboard.button(KEYS_INFO[enabler][4])
|
|
||||||
) <= 0
|
|
||||||
or not (Keyboard.button(KEYS_INFO[enabler][1]) > 0)
|
|
||||||
then
|
|
||||||
all_pressed = false
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Check that no modifier keys are pressed that shouldn't be
|
-- Queue the release action if applicable
|
||||||
if all_pressed and
|
|
||||||
(not keybind_data.ctrl and ctrl_pressed) and
|
|
||||||
(not keybind_data.alt and alt_pressed) and
|
|
||||||
(not keybind_data.shift and shift_pressed)
|
|
||||||
then
|
|
||||||
all_pressed = false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Peform the keybind action if everything validates
|
|
||||||
if all_pressed then
|
|
||||||
if perform_keybind_action(keybind_data, true) then
|
|
||||||
if keybind_data.trigger == "held" then
|
if keybind_data.trigger == "held" then
|
||||||
keybind_data.release_action = true
|
keybind_data.release_action = true
|
||||||
end
|
end
|
||||||
_pressed_key = primary_key
|
|
||||||
end
|
-- Prevent a repeat action
|
||||||
end
|
keybind_data.pressed = true
|
||||||
end
|
|
||||||
if _pressed_key then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if _pressed_key then
|
-- If the keybind was previously but is no longer pressed
|
||||||
if _keybinds[_pressed_key].check_released(_pressed_key) then
|
elseif keybind_data.pressed then
|
||||||
for _, keybind_data in ipairs(_keybinds[_pressed_key]) do
|
|
||||||
|
-- Reactivate the keybind
|
||||||
|
keybind_data.pressed = nil
|
||||||
|
|
||||||
|
-- Play the release action if applicable
|
||||||
if keybind_data.release_action then
|
if keybind_data.release_action then
|
||||||
perform_keybind_action(keybind_data, false)
|
perform_keybind_action(keybind_data, false)
|
||||||
keybind_data.release_action = nil
|
keybind_data.release_action = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
_pressed_key = nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Converts managable (raw) table of keybinds data to the table designed for the function checking for pressed and
|
-- Converts manageable (raw) table of keybinds data to a table of callbacks for checking pressed and
|
||||||
-- released keybinds. After initial call requires to be called every time some keybind is added/removed.
|
-- released keybinds. After initial call it must be called every time some keybind is added/removed.
|
||||||
function dmf.generate_keybinds()
|
function dmf.generate_keybinds()
|
||||||
_keybinds = {}
|
_keybinds = {}
|
||||||
|
|
||||||
for mod, mod_keybinds in pairs(_raw_keybinds_data) do
|
for mod, mod_keybinds in pairs(_raw_keybinds_data) do
|
||||||
for _, raw_keybind_data in pairs(mod_keybinds) do
|
for _, raw_keybind_data in pairs(mod_keybinds) do
|
||||||
|
|
||||||
local keys = raw_keybind_data.keys
|
|
||||||
local primary_key = keys[1]
|
|
||||||
local modifier_keys = {}
|
|
||||||
for i = 2, #keys do
|
|
||||||
modifier_keys[keys[i]] = true
|
|
||||||
end
|
|
||||||
|
|
||||||
local keybind_data = {
|
local keybind_data = {
|
||||||
mod = mod,
|
mod = mod,
|
||||||
global = raw_keybind_data.global,
|
global = raw_keybind_data.global,
|
||||||
trigger = raw_keybind_data.trigger,
|
trigger = raw_keybind_data.trigger,
|
||||||
type = raw_keybind_data.type,
|
type = raw_keybind_data.type,
|
||||||
enablers = modifier_keys,
|
eval_func = create_eval_func(raw_keybind_data),
|
||||||
ctrl = modifier_keys["ctrl"] or modifier_keys["left ctrl"] or modifier_keys["right ctrl"],
|
|
||||||
alt = modifier_keys["alt"] or modifier_keys["left alt"] or modifier_keys["right alt"],
|
|
||||||
shift = modifier_keys["shift"] or modifier_keys["left shift"] or modifier_keys["right shift"],
|
|
||||||
|
|
||||||
function_name = raw_keybind_data.function_name,
|
function_name = raw_keybind_data.function_name,
|
||||||
view_name = raw_keybind_data.view_name
|
view_name = raw_keybind_data.view_name
|
||||||
}
|
}
|
||||||
|
|
||||||
_keybinds[primary_key] = _keybinds[primary_key] or {
|
if keybind_data.eval_func then
|
||||||
check_pressed = CHECK_INPUT_FUNCTIONS[KEYS_INFO[primary_key][3]].PRESSED,
|
table.insert(_keybinds, keybind_data)
|
||||||
check_released = CHECK_INPUT_FUNCTIONS[KEYS_INFO[primary_key][3]].RELEASED
|
end
|
||||||
}
|
|
||||||
table.insert(_keybinds[primary_key], keybind_data)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -355,7 +336,7 @@ end
|
||||||
|
|
||||||
-- Adds/removes keybinds.
|
-- Adds/removes keybinds.
|
||||||
function dmf.add_mod_keybind(mod, setting_id, raw_keybind_data)
|
function dmf.add_mod_keybind(mod, setting_id, raw_keybind_data)
|
||||||
if #raw_keybind_data.keys > 0 then
|
if raw_keybind_data.main then
|
||||||
_raw_keybinds_data[mod] = _raw_keybinds_data[mod] or {}
|
_raw_keybinds_data[mod] = _raw_keybinds_data[mod] or {}
|
||||||
_raw_keybinds_data[mod][setting_id] = raw_keybind_data
|
_raw_keybinds_data[mod][setting_id] = raw_keybind_data
|
||||||
elseif _raw_keybinds_data[mod] and _raw_keybinds_data[mod][setting_id] then
|
elseif _raw_keybinds_data[mod] and _raw_keybinds_data[mod][setting_id] then
|
||||||
|
@ -371,55 +352,32 @@ end
|
||||||
|
|
||||||
-- Creates DMF input service. It is required to know when non-global keybinds can be triggered.
|
-- Creates DMF input service. It is required to know when non-global keybinds can be triggered.
|
||||||
-- (Called every time a level is loaded, or on mods reload)
|
-- (Called every time a level is loaded, or on mods reload)
|
||||||
function dmf.create_keybinds_input_service()
|
|
||||||
-- @TODO: Link this input service to the player's input service and find some way to see if it's blocked
|
-- @TODO: Link this input service to the player's input service and find some way to see if it's blocked
|
||||||
--[[
|
function dmf.create_keybinds_input_service()
|
||||||
-- To create the DMF input service in Darktide
|
-- -- To create the DMF input service in Darktide
|
||||||
local input_manager = Managers.input
|
-- local input_manager = Managers.input
|
||||||
local service_type = "DMF"
|
-- local service_type = "DMF"
|
||||||
input_manager:add_setting(service_type, aliases, raw_key_table, filter_table, default_devices)
|
-- input_manager:add_setting(service_type, aliases, raw_key_table, filter_table, default_devices)
|
||||||
input_manager:get_input_service(service_type)
|
-- input_manager:get_input_service(service_type)
|
||||||
--]]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Converts key_index to readable key_id, which is used by DMF to identify keys.
|
-- @TODO: So far it seems like any key can be a primary keybind, but is this actually true?
|
||||||
-- (Used for capturing keybinds)
|
|
||||||
function dmf.get_key_id(device, key_index)
|
|
||||||
local key_info = PRIMARY_BINDABLE_KEYS[device][key_index]
|
|
||||||
return key_info and key_info[2]
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- Simply tells if key with key_id can be binded as primary key.
|
|
||||||
-- (Used for verifying keybind widgets)
|
|
||||||
function dmf.can_bind_as_primary_key(key_id)
|
function dmf.can_bind_as_primary_key(key_id)
|
||||||
return KEYS_INFO[key_id] and not OTHER_KEYS[key_id]
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Builds string with readable keys' names to look like "Primary Key + Ctrl + Alt + Shift".
|
-- Translate keywatch result to array of local key names
|
||||||
-- (Used in keybind widget)
|
-- (Used in keybind widget for compatibility with legacy settings)
|
||||||
function dmf.build_keybind_string(keys)
|
function dmf.keywatch_result_to_local_keys(keywatch_result)
|
||||||
local readable_key_names = {}
|
|
||||||
for _, key_id in ipairs(keys) do
|
|
||||||
table.insert(readable_key_names, KEYS_INFO[key_id][2])
|
|
||||||
end
|
|
||||||
return table.concat(readable_key_names, " + ")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- Translate key watch result to mod options keybind
|
|
||||||
-- (Used in keybind widget)
|
|
||||||
function dmf.keybind_result_to_keys(keybind_result)
|
|
||||||
local keys = {}
|
local keys = {}
|
||||||
|
|
||||||
-- Get the local name of the main key
|
-- Get the local name of the main key
|
||||||
if keybind_result.main then
|
if keywatch_result.main then
|
||||||
|
|
||||||
local global_name = keybind_result.main
|
local global_name = keywatch_result.main
|
||||||
local device_type = InputUtils.key_device_type(global_name)
|
local local_name = InputUtils.local_key_name(global_name, InputUtils.key_device_type(global_name))
|
||||||
local local_name = InputUtils.local_key_name(global_name, device_type)
|
|
||||||
|
|
||||||
-- Check for a missing or unbindable primary key name
|
-- Check for a missing or unbindable primary key name
|
||||||
if not local_name or not dmf.can_bind_as_primary_key(local_name) then
|
if not local_name or not dmf.can_bind_as_primary_key(local_name) then
|
||||||
|
@ -430,12 +388,9 @@ function dmf.keybind_result_to_keys(keybind_result)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Add the enablers keys as additional keys
|
-- Add the enablers keys as additional keys
|
||||||
if keybind_result.enablers then
|
if keywatch_result.enablers then
|
||||||
for _, global_name in ipairs(keybind_result.enablers) do
|
for _, global_name in ipairs(keywatch_result.enablers) do
|
||||||
|
local local_name = InputUtils.local_key_name(global_name, InputUtils.key_device_type(global_name))
|
||||||
local device_type = InputUtils.key_device_type(global_name)
|
|
||||||
local local_name = InputUtils.local_key_name(global_name, device_type)
|
|
||||||
|
|
||||||
keys[#keys + 1] = local_name
|
keys[#keys + 1] = local_name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -444,41 +399,63 @@ function dmf.keybind_result_to_keys(keybind_result)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Translate mod options keybind to key watch result
|
-- Translate array of local key names to keywatch result
|
||||||
-- (Used in keybind widget)
|
-- (Used in keybind widget for compatibility with legacy settings)
|
||||||
function dmf.keys_to_keybind_result(keys)
|
function dmf.local_keys_to_keywatch_result(keys)
|
||||||
local keybind_result = {
|
local keywatch_result = {
|
||||||
enablers = {},
|
enablers = {},
|
||||||
disablers = {}
|
disablers = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if not keys or #keys == 0 then
|
if type(keys) ~= "table" or #keys == 0 then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
if keys[1] then
|
if keys[1] then
|
||||||
local local_name = keys[1]
|
local local_name = keys[1]
|
||||||
local global_name = KEYS_INFO[local_name] and InputUtils.local_to_global_name(local_name, KEYS_INFO[local_name][3])
|
local global_name
|
||||||
|
|
||||||
|
-- Check all supported devices for the global name
|
||||||
|
for _, device_type in ipairs(SUPPORTED_DEVICES) do
|
||||||
|
global_name = InputUtils.local_to_global_name(local_name, device_type)
|
||||||
|
if get_corresponding_device(global_name) then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- End early if our main key doesn't exist, and return an empty result
|
-- End early if our main key doesn't exist, and return an empty result
|
||||||
if not global_name then
|
if not global_name then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
keybind_result.main = global_name
|
if MODIFIER_KEYS_LOC_ALIAS[global_name] then
|
||||||
|
global_name = MODIFIER_KEYS_LOC_ALIAS[global_name]
|
||||||
|
end
|
||||||
|
keywatch_result.main = global_name
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Add all remaining keys to the enablers list
|
-- Add all remaining keys to the enablers list
|
||||||
for i = 2, #keys do
|
for i = 2, #keys do
|
||||||
local local_name = keys[i]
|
local local_name = keys[i]
|
||||||
local global_name = KEYS_INFO[local_name] and InputUtils.local_to_global_name(local_name, KEYS_INFO[local_name][3])
|
local global_name
|
||||||
|
|
||||||
|
-- Check all supported devices for the global name
|
||||||
|
for _, device_type in ipairs(SUPPORTED_DEVICES) do
|
||||||
|
global_name = InputUtils.local_to_global_name(local_name,device_type)
|
||||||
|
if get_corresponding_device(global_name) then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if global_name then
|
if global_name then
|
||||||
keybind_result.enablers[#keybind_result.enablers + 1] = global_name
|
if MODIFIER_KEYS_LOC_ALIAS[global_name] then
|
||||||
|
global_name = MODIFIER_KEYS_LOC_ALIAS[global_name]
|
||||||
|
end
|
||||||
|
keywatch_result.enablers[#keywatch_result.enablers + 1] = global_name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return keybind_result
|
return keywatch_result
|
||||||
end
|
end
|
||||||
|
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
|
|
|
@ -91,13 +91,12 @@ end
|
||||||
-- ##### DMF internal functions and variables #########################################################################
|
-- ##### DMF internal functions and variables #########################################################################
|
||||||
-- ####################################################################################################################
|
-- ####################################################################################################################
|
||||||
|
|
||||||
-- Handles the return of global localize text_ids
|
dmf:hook(LocalizationManager, "localize", function (func, self, text_id, ...)
|
||||||
dmf:hook(_G, "Localize", function (func, text_id, ...)
|
|
||||||
|
|
||||||
local text_translations = text_id and _global_localization_database[text_id]
|
local text_translations = text_id and _global_localization_database[text_id]
|
||||||
local message = get_translated_or_english_message(nil, text_translations, ...)
|
local message = get_translated_or_english_message(nil, text_translations, ...)
|
||||||
|
|
||||||
return message or func(text_id, ...)
|
return message or func(self, text_id, ...)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- ####################################################################################################################
|
-- ####################################################################################################################
|
||||||
|
|
|
@ -122,6 +122,7 @@ local function initialize_generic_widget_data(mod, data, localize)
|
||||||
new_data.title = data.title -- optional, if (localize == true)
|
new_data.title = data.title -- optional, if (localize == true)
|
||||||
new_data.tooltip = data.tooltip -- optional
|
new_data.tooltip = data.tooltip -- optional
|
||||||
new_data.default_value = data.default_value
|
new_data.default_value = data.default_value
|
||||||
|
new_data.require_restart = data.require_restart -- optional
|
||||||
|
|
||||||
-- Overwrite global optons localization setting if widget defined it
|
-- Overwrite global optons localization setting if widget defined it
|
||||||
if data.localize == nil then
|
if data.localize == nil then
|
||||||
|
@ -300,11 +301,6 @@ local allowed_keybind_types = {
|
||||||
view_toggle = true,
|
view_toggle = true,
|
||||||
mod_toggle = true
|
mod_toggle = true
|
||||||
}
|
}
|
||||||
local allowed_modifier_keys = {
|
|
||||||
ctrl = true,
|
|
||||||
alt = true,
|
|
||||||
shift = true
|
|
||||||
}
|
|
||||||
local function validate_keybind_data(data)
|
local function validate_keybind_data(data)
|
||||||
if data.keybind_global and type(data.keybind_global) ~= "boolean" then
|
if data.keybind_global and type(data.keybind_global) ~= "boolean" then
|
||||||
dmf.throw_error("[widget \"%s\" (keybind)]: 'keybind_global' field must have 'boolean' type", data.setting_id)
|
dmf.throw_error("[widget \"%s\" (keybind)]: 'keybind_global' field must have 'boolean' type", data.setting_id)
|
||||||
|
@ -343,13 +339,6 @@ local function validate_keybind_data(data)
|
||||||
if default_value[1] and not dmf.can_bind_as_primary_key(default_value[1]) then
|
if default_value[1] and not dmf.can_bind_as_primary_key(default_value[1]) then
|
||||||
dmf.throw_error("[widget \"%s\" (keybind)]: 'default_value[1]' must be a valid key name", data.setting_id)
|
dmf.throw_error("[widget \"%s\" (keybind)]: 'default_value[1]' must be a valid key name", data.setting_id)
|
||||||
end
|
end
|
||||||
if default_value[2] and not allowed_modifier_keys[default_value[2]] or
|
|
||||||
default_value[3] and not allowed_modifier_keys[default_value[3]] or
|
|
||||||
default_value[4] and not allowed_modifier_keys[default_value[4]]
|
|
||||||
then
|
|
||||||
dmf.throw_error("[widget \"%s\" (keybind)]: 'default_value [2], [3] and [4]' can be only strings: \"ctrl\", " ..
|
|
||||||
"\"alt\" and \"shift\" (in no particular order)", data.setting_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
local used_keys = {}
|
local used_keys = {}
|
||||||
for _, key in ipairs(default_value) do
|
for _, key in ipairs(default_value) do
|
||||||
|
@ -545,6 +534,8 @@ local function initialize_default_settings_and_keybinds(mod, initialized_widgets
|
||||||
mod:set(data.setting_id, data.default_value)
|
mod:set(data.setting_id, data.default_value)
|
||||||
end
|
end
|
||||||
if data.type == "keybind" then
|
if data.type == "keybind" then
|
||||||
|
local keywatch_result = dmf.local_keys_to_keywatch_result(mod:get(data.setting_id))
|
||||||
|
if keywatch_result and keywatch_result.main then
|
||||||
dmf.add_mod_keybind(
|
dmf.add_mod_keybind(
|
||||||
mod,
|
mod,
|
||||||
data.setting_id,
|
data.setting_id,
|
||||||
|
@ -552,7 +543,9 @@ local function initialize_default_settings_and_keybinds(mod, initialized_widgets
|
||||||
global = data.keybind_global,
|
global = data.keybind_global,
|
||||||
trigger = data.keybind_trigger,
|
trigger = data.keybind_trigger,
|
||||||
type = data.keybind_type,
|
type = data.keybind_type,
|
||||||
keys = mod:get(data.setting_id),
|
main = keywatch_result.main,
|
||||||
|
enablers = keywatch_result.enablers,
|
||||||
|
disablers = keywatch_result.disablers,
|
||||||
function_name = data.function_name,
|
function_name = data.function_name,
|
||||||
view_name = data.view_name
|
view_name = data.view_name
|
||||||
}
|
}
|
||||||
|
@ -560,6 +553,7 @@ local function initialize_default_settings_and_keybinds(mod, initialized_widgets
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
-- ##### DMF internal functions and variables ##########################################################################
|
-- ##### DMF internal functions and variables ##########################################################################
|
||||||
|
|
|
@ -87,7 +87,7 @@ function dmf.safe_call_dofile(mod, error_prefix_data, file_path)
|
||||||
show_error(mod, error_prefix_data, "file path should be a string.")
|
show_error(mod, error_prefix_data, "file path should be a string.")
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
return dmf.safe_call(mod, error_prefix_data, dofile, mod, file_path)
|
return dmf.safe_call(mod, error_prefix_data, dofile, file_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -49,8 +49,10 @@ local function close_dev_console()
|
||||||
|
|
||||||
CommandWindow.close()
|
CommandWindow.close()
|
||||||
|
|
||||||
-- CommandWindow won't close by itself, so it have to be closed manually
|
-- CommandWindow won't close by itself, so it has to be closed through FFI
|
||||||
|
if _ffi then
|
||||||
dmf:pcall(function()
|
dmf:pcall(function()
|
||||||
|
if _ffi then
|
||||||
_ffi.cdef([[
|
_ffi.cdef([[
|
||||||
void* FindWindowA(const char* lpClassName, const char* lpWindowName);
|
void* FindWindowA(const char* lpClassName, const char* lpWindowName);
|
||||||
int64_t SendMessageA(void* hWnd, unsigned int Msg, uint64_t wParam, int64_t lParam);
|
int64_t SendMessageA(void* hWnd, unsigned int Msg, uint64_t wParam, int64_t lParam);
|
||||||
|
@ -58,8 +60,14 @@ local function close_dev_console()
|
||||||
local WM_CLOSE = 0x10;
|
local WM_CLOSE = 0x10;
|
||||||
local hwnd = _ffi.C.FindWindowA("ConsoleWindowClass", "Developer console")
|
local hwnd = _ffi.C.FindWindowA("ConsoleWindowClass", "Developer console")
|
||||||
_ffi.C.SendMessageA(hwnd, WM_CLOSE, 0, 0)
|
_ffi.C.SendMessageA(hwnd, WM_CLOSE, 0, 0)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
-- Or manually closed by the user
|
||||||
|
else
|
||||||
|
dmf:warning(dmf:localize("dev_console_close_warning"))
|
||||||
|
end
|
||||||
|
|
||||||
_console_data.enabled = false
|
_console_data.enabled = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,7 @@ if not _io.initialized then
|
||||||
_io = dmf.deepcopy(Mods.lua.io)
|
_io = dmf.deepcopy(Mods.lua.io)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Local backup of the io library
|
-- Local backup of the os library
|
||||||
local _os = dmf:persistent_table("_os")
|
local _os = dmf:persistent_table("_os")
|
||||||
_os.initialized = _os.initialized or false
|
_os.initialized = _os.initialized or false
|
||||||
if not _os.initialized then
|
if not _os.initialized then
|
||||||
|
@ -17,6 +17,11 @@ end
|
||||||
-- Global backup of original print() method
|
-- Global backup of original print() method
|
||||||
local print = __print
|
local print = __print
|
||||||
|
|
||||||
|
local function log_and_console_print(message, ...)
|
||||||
|
print(message, ...)
|
||||||
|
CommandWindow.print(message, ...)
|
||||||
|
end
|
||||||
|
|
||||||
local function table_dump(key, value, depth, max_depth)
|
local function table_dump(key, value, depth, max_depth)
|
||||||
if max_depth < depth then
|
if max_depth < depth then
|
||||||
return
|
return
|
||||||
|
@ -28,7 +33,7 @@ local function table_dump(key, value, depth, max_depth)
|
||||||
if value_type == "table" then
|
if value_type == "table" then
|
||||||
prefix = prefix .. ((key == nil and "") or " = ")
|
prefix = prefix .. ((key == nil and "") or " = ")
|
||||||
|
|
||||||
print(prefix .. "table")
|
log_and_console_print(prefix .. "table")
|
||||||
|
|
||||||
for key_, value_ in pairs(value) do
|
for key_, value_ in pairs(value) do
|
||||||
table_dump(key_, value_, depth + 1, max_depth)
|
table_dump(key_, value_, depth + 1, max_depth)
|
||||||
|
@ -38,9 +43,9 @@ local function table_dump(key, value, depth, max_depth)
|
||||||
|
|
||||||
if meta then
|
if meta then
|
||||||
if type(meta) == "boolean" then
|
if type(meta) == "boolean" then
|
||||||
print(prefix .. "protected metatable")
|
log_and_console_print(prefix .. "protected metatable")
|
||||||
else
|
else
|
||||||
print(prefix .. "metatable")
|
log_and_console_print(prefix .. "metatable")
|
||||||
for key_, value_ in pairs(meta) do
|
for key_, value_ in pairs(meta) do
|
||||||
if key_ ~= "__index" and key_ ~= "super" then
|
if key_ ~= "__index" and key_ ~= "super" then
|
||||||
table_dump(key_, value_, depth + 1, max_depth)
|
table_dump(key_, value_, depth + 1, max_depth)
|
||||||
|
@ -49,24 +54,28 @@ local function table_dump(key, value, depth, max_depth)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif value_type == "function" or value_type == "thread" or value_type == "userdata" or value == nil then
|
elseif value_type == "function" or value_type == "thread" or value_type == "userdata" or value == nil then
|
||||||
print(prefix .. " = " .. tostring(value))
|
log_and_console_print(prefix .. " = " .. tostring(value))
|
||||||
else
|
else
|
||||||
print(prefix .. " = " .. tostring(value) .. " (" .. value_type .. ")")
|
log_and_console_print(prefix .. " = " .. tostring(value) .. " (" .. value_type .. ")")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
DMFMod.dump = function (self, dumped_object, dumped_object_name, max_depth)
|
DMFMod.dump = function (self, dumped_object, object_name, max_depth)
|
||||||
|
if dmf.check_wrong_argument_type(self, "dump", "dumped_object_name", object_name, "string", "nil") or
|
||||||
if dmf.check_wrong_argument_type(self, "dump", "dumped_object_name", dumped_object_name, "string", "nil") or
|
dmf.check_wrong_argument_type(self, "dump", "max_depth", max_depth, "number", "nil")
|
||||||
dmf.check_wrong_argument_type(self, "dump", "max_depth", max_depth, "number")
|
|
||||||
then
|
then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local object_type = type(dumped_object)
|
local object_type = type(dumped_object)
|
||||||
|
max_depth = max_depth or 1
|
||||||
|
|
||||||
if object_type ~= "table" then
|
if object_type ~= "table" then
|
||||||
local error_message = "(dump): \"object_name\" is not a table. It's " .. object_type
|
local error_message = string.format(
|
||||||
|
'(dump): "%s" is not a table but of type "%s"',
|
||||||
|
object_name or "Dump object",
|
||||||
|
object_type
|
||||||
|
)
|
||||||
|
|
||||||
if object_type ~= "nil" then
|
if object_type ~= "nil" then
|
||||||
error_message = error_message .. " (" .. tostring(dumped_object) .. ")"
|
error_message = error_message .. " (" .. tostring(dumped_object) .. ")"
|
||||||
|
@ -76,13 +85,8 @@ DMFMod.dump = function (self, dumped_object, dumped_object_name, max_depth)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if dumped_object_name then
|
if object_name then
|
||||||
print(string.format("<%s>", dumped_object_name))
|
log_and_console_print(string.format("<%s>", object_name))
|
||||||
end
|
|
||||||
|
|
||||||
if not max_depth then
|
|
||||||
self:error("(dump): maximum depth is not specified")
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local success, error_message = pcall(function()
|
local success, error_message = pcall(function()
|
||||||
|
@ -95,17 +99,12 @@ DMFMod.dump = function (self, dumped_object, dumped_object_name, max_depth)
|
||||||
self:error("(dump): %s", tostring(error_message))
|
self:error("(dump): %s", tostring(error_message))
|
||||||
end
|
end
|
||||||
|
|
||||||
if dumped_object_name then
|
if object_name then
|
||||||
print(string.format("</%s>", dumped_object_name))
|
log_and_console_print(string.format("</%s>", object_name))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local function table_dump_to_file(dumped_table, dumped_table_name, max_depth)
|
local function table_dump_to_file(dumped_table, dumped_table_name, max_depth)
|
||||||
|
|
||||||
-- #####################
|
-- #####################
|
||||||
|
@ -343,17 +342,22 @@ end
|
||||||
|
|
||||||
|
|
||||||
DMFMod.dump_to_file = function (self, dumped_object, object_name, max_depth)
|
DMFMod.dump_to_file = function (self, dumped_object, object_name, max_depth)
|
||||||
|
if dmf.check_wrong_argument_type(self, "dump_to_file", "object_name", object_name, "string", "nil") or
|
||||||
if dmf.check_wrong_argument_type(self, "dump_to_file", "object_name", object_name, "string") or
|
dmf.check_wrong_argument_type(self, "dump_to_file", "max_depth", max_depth, "number", "nil")
|
||||||
dmf.check_wrong_argument_type(self, "dump_to_file", "max_depth", max_depth, "number")
|
|
||||||
then
|
then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local object_type = type(dumped_object)
|
local object_type = type(dumped_object)
|
||||||
|
object_name = object_name or "mod_dump_to_file"
|
||||||
|
max_depth = max_depth or 1
|
||||||
|
|
||||||
if object_type ~= "table" then
|
if object_type ~= "table" then
|
||||||
local error_message = "(dump_to_file): \"object_name\" is not a table. It's " .. object_type
|
local error_message = string.format(
|
||||||
|
'(dump_to_file): "%s" is not a table but of type "%s"',
|
||||||
|
object_name or "Dump object",
|
||||||
|
object_type
|
||||||
|
)
|
||||||
|
|
||||||
if object_type ~= "nil" then
|
if object_type ~= "nil" then
|
||||||
error_message = error_message .. " (" .. tostring(dumped_object) .. ")"
|
error_message = error_message .. " (" .. tostring(dumped_object) .. ")"
|
||||||
|
|
|
@ -169,7 +169,7 @@ function dmf.initialize_mod_data(mod, mod_data)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Mod's options initialization
|
-- Mod's options initialization
|
||||||
if mod_data.options or ((mod_data.is_togglable and not mod_data.is_mutator) and not mod_data.options_widgets) then
|
if mod_data.options or (not mod_data.is_mutator and not mod_data.options_widgets) then
|
||||||
local success, error_message = pcall(dmf.initialize_mod_options, mod, mod_data.options)
|
local success, error_message = pcall(dmf.initialize_mod_options, mod, mod_data.options)
|
||||||
if not success then
|
if not success then
|
||||||
mod:error(ERRORS.REGULAR.mod_options_initializing_failed, error_message)
|
mod:error(ERRORS.REGULAR.mod_options_initializing_failed, error_message)
|
||||||
|
|
|
@ -16,7 +16,7 @@ dmf_mod_data.options = {
|
||||||
setting_id = "dmf_options_scrolling_speed",
|
setting_id = "dmf_options_scrolling_speed",
|
||||||
type = "numeric",
|
type = "numeric",
|
||||||
default_value = 100,
|
default_value = 100,
|
||||||
range = {1, 1000},
|
range = {50, 500},
|
||||||
unit_text = "percent"
|
unit_text = "percent"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -38,16 +38,16 @@ dmf_mod_data.options = {
|
||||||
keybind_type = "function_call",
|
keybind_type = "function_call",
|
||||||
function_name = "toggle_developer_console"
|
function_name = "toggle_developer_console"
|
||||||
},
|
},
|
||||||
{
|
-- {
|
||||||
setting_id = "show_network_debug_info",
|
-- setting_id = "show_network_debug_info",
|
||||||
type = "checkbox",
|
-- type = "checkbox",
|
||||||
default_value = false
|
-- default_value = false
|
||||||
},
|
-- },
|
||||||
{
|
-- {
|
||||||
setting_id = "log_ui_renderers_info",
|
-- setting_id = "log_ui_renderers_info",
|
||||||
type = "checkbox",
|
-- type = "checkbox",
|
||||||
default_value = false
|
-- default_value = false
|
||||||
}
|
-- }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,6 +7,8 @@ local _custom_views_data = {}
|
||||||
local _ingame_ui
|
local _ingame_ui
|
||||||
local _loaded_views = {}
|
local _loaded_views = {}
|
||||||
|
|
||||||
|
local _key_watch = false
|
||||||
|
|
||||||
local ERRORS = {
|
local ERRORS = {
|
||||||
THROWABLE = {
|
THROWABLE = {
|
||||||
-- inject_view:
|
-- inject_view:
|
||||||
|
@ -312,13 +314,13 @@ end
|
||||||
|
|
||||||
|
|
||||||
-- Track the creation of the view loader
|
-- Track the creation of the view loader
|
||||||
dmf:hook_safe(ViewLoader, "init", function()
|
dmf:hook_safe(CLASS.ViewLoader, "init", function()
|
||||||
_custom_view_persistent_data.loader_initialized = true
|
_custom_view_persistent_data.loader_initialized = true
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
-- Track the loading of views, set the loader flag if class selection is reached
|
-- Track the loading of views, set the loader flag if class selection is reached
|
||||||
dmf:hook_safe(UIManager, "load_view", function(self, view_name)
|
dmf:hook_safe(CLASS.UIManager, "load_view", function(self, view_name)
|
||||||
if view_name == "class_selection_view" then
|
if view_name == "class_selection_view" then
|
||||||
_custom_view_persistent_data.loader_initialized = true
|
_custom_view_persistent_data.loader_initialized = true
|
||||||
end
|
end
|
||||||
|
@ -326,13 +328,13 @@ dmf:hook_safe(UIManager, "load_view", function(self, view_name)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Track the unloading of views
|
-- Track the unloading of views
|
||||||
dmf:hook_safe(UIManager, "unload_view", function(self, view_name)
|
dmf:hook_safe(CLASS.UIManager, "unload_view", function(self, view_name)
|
||||||
_loaded_views[view_name] = nil
|
_loaded_views[view_name] = nil
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
-- Store the view handler for later use and inject views
|
-- Store the view handler for later use and inject views
|
||||||
dmf:hook_safe(UIViewHandler, "init", function(self)
|
dmf:hook_safe(CLASS.UIViewHandler, "init", function(self)
|
||||||
_ingame_ui = self
|
_ingame_ui = self
|
||||||
for view_name, _ in pairs(_custom_views_data) do
|
for view_name, _ in pairs(_custom_views_data) do
|
||||||
if not dmf.safe_call_nrc(self, {ERRORS.PREFIX.ingameui_hook_injection, view_name}, inject_view, view_name) then
|
if not dmf.safe_call_nrc(self, {ERRORS.PREFIX.ingameui_hook_injection, view_name}, inject_view, view_name) then
|
||||||
|
@ -341,6 +343,16 @@ dmf:hook_safe(UIViewHandler, "init", function(self)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
-- Track the start of key watches
|
||||||
|
dmf:hook_safe(CLASS.InputManager, "start_key_watch", function(self)
|
||||||
|
_key_watch = true
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Track the end of key watches
|
||||||
|
dmf:hook_safe(CLASS.InputManager, "stop_key_watch", function(self)
|
||||||
|
_key_watch = false
|
||||||
|
end)
|
||||||
|
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
-- ##### DMF internal functions and variables ##########################################################################
|
-- ##### DMF internal functions and variables ##########################################################################
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
|
@ -368,8 +380,8 @@ function dmf.keybind_toggle_view(mod, view_name, keybind_transition_data, can_pe
|
||||||
-- If the view is open, this is a toggle close
|
-- If the view is open, this is a toggle close
|
||||||
if Managers.ui:view_active(view_name) then
|
if Managers.ui:view_active(view_name) then
|
||||||
|
|
||||||
-- Don't close the view if it's already closing
|
-- Don't close the view if it's already closing or we have an active key watch
|
||||||
if not Managers.ui:is_view_closing(view_name) then
|
if not Managers.ui:is_view_closing(view_name) and not _key_watch then
|
||||||
local force_close = true
|
local force_close = true
|
||||||
Managers.ui:close_view(view_name, force_close)
|
Managers.ui:close_view(view_name, force_close)
|
||||||
end
|
end
|
||||||
|
|
|
@ -80,8 +80,6 @@ end
|
||||||
dmf:hook("ConstantElementChat", "_handle_active_chat_input", function(func, self, input_service, ui_renderer, ...)
|
dmf:hook("ConstantElementChat", "_handle_active_chat_input", function(func, self, input_service, ui_renderer, ...)
|
||||||
initialize_drawing_function()
|
initialize_drawing_function()
|
||||||
|
|
||||||
local command_executed = false
|
|
||||||
|
|
||||||
_chat_message = get_chat_message(self)
|
_chat_message = get_chat_message(self)
|
||||||
_chat_opened = true
|
_chat_opened = true
|
||||||
|
|
||||||
|
@ -128,8 +126,6 @@ dmf:hook("ConstantElementChat", "_handle_active_chat_input", function(func, self
|
||||||
|
|
||||||
set_chat_message(self, "")
|
set_chat_message(self, "")
|
||||||
|
|
||||||
command_executed = true
|
|
||||||
|
|
||||||
elseif string.sub(_chat_message, 1, 1) == "/" then
|
elseif string.sub(_chat_message, 1, 1) == "/" then
|
||||||
dmf:notify(dmf:localize("chat_command_not_recognized") .. ": " .. _chat_message)
|
dmf:notify(dmf:localize("chat_command_not_recognized") .. ": " .. _chat_message)
|
||||||
set_chat_message(self, "")
|
set_chat_message(self, "")
|
||||||
|
|
|
@ -5,13 +5,12 @@ local MULTISTRING_INDICATOR_TEXT = "[...]"
|
||||||
local DEFAULT_HUD_SCALE = 100
|
local DEFAULT_HUD_SCALE = 100
|
||||||
|
|
||||||
local FONT_TYPE = "arial"
|
local FONT_TYPE = "arial"
|
||||||
local FONT_MATERIAL = "content/ui/fonts/arial"
|
|
||||||
local FONT_SIZE = 22
|
local FONT_SIZE = 22
|
||||||
|
|
||||||
local MAX_COMMANDS_VISIBLE = 5
|
local MAX_COMMANDS_VISIBLE = 5
|
||||||
|
|
||||||
local STRING_HEIGHT = 25
|
local STRING_HEIGHT = 25
|
||||||
local STRING_Y_OFFSET = 7
|
local STRING_Y_OFFSET = 2
|
||||||
local STRING_X_MARGIN = 10
|
local STRING_X_MARGIN = 10
|
||||||
|
|
||||||
local OFFSET_X = 10
|
local OFFSET_X = 10
|
||||||
|
@ -57,8 +56,7 @@ local function get_hud_scale()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function get_text_size(text, font_type, font_size)
|
local function get_text_size(text, font_data, font_size)
|
||||||
local font_data = Managers.font:data_by_type(font_type)
|
|
||||||
local font = font_data.path
|
local font = font_data.path
|
||||||
local additional_settings = {
|
local additional_settings = {
|
||||||
flags = font_data.render_flags or 0
|
flags = font_data.render_flags or 0
|
||||||
|
@ -81,11 +79,11 @@ local function get_text_width(text, font, font_size)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function get_scaled_font_size_by_width(text, font_type, font_size, max_width)
|
local function get_scaled_font_size_by_width(text, font_data, font_size, max_width)
|
||||||
local scale = RESOLUTION_LOOKUP.scale
|
local scale = RESOLUTION_LOOKUP.scale
|
||||||
local min_font_size = 1
|
local min_font_size = 1
|
||||||
local scaled_font_size = math.max(font_size * scale, 1)
|
local scaled_font_size = math.max(font_size * scale, 1)
|
||||||
local text_width = get_text_size(text, font_type, scaled_font_size)
|
local text_width = get_text_size(text, font_data, scaled_font_size)
|
||||||
|
|
||||||
if max_width < text_width then
|
if max_width < text_width then
|
||||||
repeat
|
repeat
|
||||||
|
@ -95,7 +93,7 @@ local function get_scaled_font_size_by_width(text, font_type, font_size, max_wid
|
||||||
|
|
||||||
font_size = math.max(font_size - 1, min_font_size)
|
font_size = math.max(font_size - 1, min_font_size)
|
||||||
scaled_font_size = math.max(font_size * scale, 1)
|
scaled_font_size = math.max(font_size * scale, 1)
|
||||||
text_width = math.floor(get_text_size(text, font_type, scaled_font_size))
|
text_width = math.floor(get_text_size(text, font_data, scaled_font_size))
|
||||||
until text_width <= max_width
|
until text_width <= max_width
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -115,6 +113,8 @@ end
|
||||||
|
|
||||||
|
|
||||||
local function draw(commands_list, selected_command_index)
|
local function draw(commands_list, selected_command_index)
|
||||||
|
local font_data = Managers.font:data_by_type(FONT_TYPE)
|
||||||
|
local font = font_data.path
|
||||||
|
|
||||||
create_gui()
|
create_gui()
|
||||||
if not _gui then
|
if not _gui then
|
||||||
|
@ -152,30 +152,30 @@ local function draw(commands_list, selected_command_index)
|
||||||
local font_size = FONT_SIZE
|
local font_size = FONT_SIZE
|
||||||
|
|
||||||
for i, command in ipairs(displayed_commands) do
|
for i, command in ipairs(displayed_commands) do
|
||||||
font_size = get_scaled_font_size_by_width(command.name, FONT_TYPE, FONT_SIZE, BASE_COMMAND_TEXT_WIDTH)
|
font_size = get_scaled_font_size_by_width(command.name, font_data, FONT_SIZE, BASE_COMMAND_TEXT_WIDTH)
|
||||||
|
|
||||||
-- draw "/command_name" text
|
-- draw "/command_name" text
|
||||||
local scaled_offet_x = (OFFSET_X + STRING_X_MARGIN) * scale
|
local scaled_offet_x = (OFFSET_X + STRING_X_MARGIN) * scale
|
||||||
local scaled_offset_y = (OFFSET_Y - STRING_HEIGHT * (i + selected_strings_number - 1) + STRING_Y_OFFSET) * scale
|
local scaled_offset_y = (OFFSET_Y - STRING_HEIGHT * (i + selected_strings_number - 1) + STRING_Y_OFFSET) * scale
|
||||||
|
|
||||||
local string_position = Vector3(scaled_offet_x, scaled_offset_y, OFFSET_Z + 2)
|
local string_position = Vector3(scaled_offet_x, scaled_offset_y, OFFSET_Z + 2)
|
||||||
Gui.slug_text(_gui, command.name, FONT_MATERIAL, font_size, string_position, nil, Color(255, 100, 255, 100))
|
Gui.slug_text(_gui, command.name, font, font_size, string_position, nil, Color(255, 100, 255, 100))
|
||||||
|
|
||||||
local command_text_strings = word_wrap(command.full_text, FONT_MATERIAL, font_size, BASE_COMMAND_TEXT_WIDTH)
|
local command_text_strings = word_wrap(command.full_text, font, font_size, BASE_COMMAND_TEXT_WIDTH)
|
||||||
local multistring = #command_text_strings > 1
|
local multistring = #command_text_strings > 1
|
||||||
local first_description_string
|
local first_description_string
|
||||||
if multistring then
|
if multistring then
|
||||||
if command.selected then
|
if command.selected then
|
||||||
selected_strings_number = #command_text_strings
|
selected_strings_number = #command_text_strings
|
||||||
else
|
else
|
||||||
local multistring_indicator_width = get_text_width(MULTISTRING_INDICATOR_TEXT, FONT_MATERIAL, font_size)
|
local multistring_indicator_width = get_text_width(MULTISTRING_INDICATOR_TEXT, font, font_size)
|
||||||
local command_text_width = BASE_COMMAND_TEXT_WIDTH - (multistring_indicator_width / scale)
|
local command_text_width = BASE_COMMAND_TEXT_WIDTH - (multistring_indicator_width / scale)
|
||||||
command_text_strings = word_wrap(command.full_text, FONT_MATERIAL, font_size, command_text_width)
|
command_text_strings = word_wrap(command.full_text, font, font_size, command_text_width)
|
||||||
|
|
||||||
-- draw that [...] thing
|
-- draw that [...] thing
|
||||||
local multistring_offset_x = (OFFSET_X + WIDTH) * scale - multistring_indicator_width
|
local multistring_offset_x = (OFFSET_X + WIDTH) * scale - multistring_indicator_width
|
||||||
local multistring_indicator_position = Vector3(multistring_offset_x, string_position.y, string_position.z)
|
local multistring_indicator_position = Vector3(multistring_offset_x, string_position.y, string_position.z)
|
||||||
Gui.slug_text(_gui, MULTISTRING_INDICATOR_TEXT, FONT_MATERIAL, font_size,
|
Gui.slug_text(_gui, MULTISTRING_INDICATOR_TEXT, font, font_size,
|
||||||
multistring_indicator_position, nil, Color(255, 100, 100, 100))
|
multistring_indicator_position, nil, Color(255, 100, 100, 100))
|
||||||
end
|
end
|
||||||
first_description_string = string.sub(command_text_strings[1], #command.name + 2)
|
first_description_string = string.sub(command_text_strings[1], #command.name + 2)
|
||||||
|
@ -184,18 +184,18 @@ local function draw(commands_list, selected_command_index)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- draw command description text (1st string)
|
-- draw command description text (1st string)
|
||||||
local first_description_string_width = get_text_width(command.name, FONT_MATERIAL, font_size)
|
local first_description_string_width = get_text_width(command.name, font, font_size)
|
||||||
|
|
||||||
local first_description_pos_x = string_position.x + first_description_string_width
|
local first_description_pos_x = string_position.x + first_description_string_width
|
||||||
local first_description_string_position = Vector3(first_description_pos_x, string_position.y, string_position.z)
|
local first_description_string_position = Vector3(first_description_pos_x, string_position.y, string_position.z)
|
||||||
Gui.slug_text(_gui, first_description_string, FONT_MATERIAL, font_size,
|
Gui.slug_text(_gui, first_description_string, font, font_size,
|
||||||
first_description_string_position, nil, Color(255, 255, 255, 255))
|
first_description_string_position, nil, Color(255, 255, 255, 255))
|
||||||
|
|
||||||
-- draw command description text (2+ strings)
|
-- draw command description text (2+ strings)
|
||||||
if command.selected and multistring then
|
if command.selected and multistring then
|
||||||
for j = 2, selected_strings_number do
|
for j = selected_strings_number, 2, -1 do
|
||||||
string_position.y = string_position.y - STRING_HEIGHT * scale
|
string_position.y = string_position.y - STRING_HEIGHT * scale
|
||||||
Gui.slug_text(_gui, command_text_strings[j], FONT_MATERIAL, font_size,
|
Gui.slug_text(_gui, command_text_strings[j], font, font_size,
|
||||||
string_position, nil, Color(255, 255, 255, 255))
|
string_position, nil, Color(255, 255, 255, 255))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -227,11 +227,11 @@ local function draw(commands_list, selected_command_index)
|
||||||
if selected_command_index > 0 then
|
if selected_command_index > 0 then
|
||||||
total_number_indicator = selected_command_index .. "/" .. total_number_indicator
|
total_number_indicator = selected_command_index .. "/" .. total_number_indicator
|
||||||
end
|
end
|
||||||
local total_number_indicator_width = get_text_width(total_number_indicator, FONT_MATERIAL, font_size)
|
local total_number_indicator_width = get_text_width(total_number_indicator, font, font_size)
|
||||||
local total_number_indicator_x = (WIDTH) * scale - total_number_indicator_width
|
local total_number_indicator_x = (WIDTH) * scale - total_number_indicator_width
|
||||||
local total_number_indicator_y = (OFFSET_Y + STRING_Y_OFFSET) * scale
|
local total_number_indicator_y = (OFFSET_Y + STRING_Y_OFFSET) * scale
|
||||||
local total_number_indicator_position = Vector3(total_number_indicator_x, total_number_indicator_y, OFFSET_Z + 2)
|
local total_number_indicator_position = Vector3(total_number_indicator_x, total_number_indicator_y, OFFSET_Z + 2)
|
||||||
Gui.slug_text(_gui, total_number_indicator, FONT_MATERIAL, font_size,
|
Gui.slug_text(_gui, total_number_indicator, font, font_size,
|
||||||
total_number_indicator_position, nil, Color(255, 100, 100, 100))
|
total_number_indicator_position, nil, Color(255, 100, 100, 100))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,14 @@ local _widgets_by_name
|
||||||
-- ####################################################################################################################
|
-- ####################################################################################################################
|
||||||
|
|
||||||
local function load_scrolling_speed_setting()
|
local function load_scrolling_speed_setting()
|
||||||
if dmf:get("dmf_options_scrolling_speed") and _widgets_by_name and _widgets_by_name["scrollbar"] then
|
if _widgets_by_name then
|
||||||
_widgets_by_name["scrollbar"].content.scroll_speed = dmf:get("dmf_options_scrolling_speed")
|
local dmf_scroll_speed = math.clamp((dmf:get("dmf_options_scrolling_speed") or 100) / 1000, 0.05, 0.5)
|
||||||
|
if _widgets_by_name["scrollbar"] then
|
||||||
|
_widgets_by_name["scrollbar"].content.scroll_amount = dmf_scroll_speed
|
||||||
|
end
|
||||||
|
if _widgets_by_name["settings_scrollbar"] then
|
||||||
|
_widgets_by_name["settings_scrollbar"].content.scroll_amount = dmf_scroll_speed
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -39,6 +45,9 @@ local ViewElementKeybindPopup = require("scripts/ui/view_elements/view_element_k
|
||||||
local CATEGORIES_GRID = 1
|
local CATEGORIES_GRID = 1
|
||||||
local SETTINGS_GRID = 2
|
local SETTINGS_GRID = 2
|
||||||
|
|
||||||
|
local _last_selected_category_entry
|
||||||
|
local _last_selected_category_widget
|
||||||
|
|
||||||
local DMFOptionsView = class("DMFOptionsView", "BaseView")
|
local DMFOptionsView = class("DMFOptionsView", "BaseView")
|
||||||
|
|
||||||
DMFOptionsView.init = function (self, settings)
|
DMFOptionsView.init = function (self, settings)
|
||||||
|
@ -151,6 +160,8 @@ DMFOptionsView.cb_on_back_pressed = function (self)
|
||||||
self._close_selected_setting = true
|
self._close_selected_setting = true
|
||||||
elseif selected_navigation_column == SETTINGS_GRID then
|
elseif selected_navigation_column == SETTINGS_GRID then
|
||||||
self:_change_navigation_column(selected_navigation_column - 1)
|
self:_change_navigation_column(selected_navigation_column - 1)
|
||||||
|
elseif self._require_restart then
|
||||||
|
self:_restart_popup_info()
|
||||||
else
|
else
|
||||||
local view_name = "dmf_options_view"
|
local view_name = "dmf_options_view"
|
||||||
Managers.ui:close_view(view_name)
|
Managers.ui:close_view(view_name)
|
||||||
|
@ -207,6 +218,30 @@ DMFOptionsView.cb_reset_category_to_default = function (self)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
DMFOptionsView._restart_popup_info = function (self)
|
||||||
|
local context = {
|
||||||
|
title_text = "loc_popup_settings_require_restart_header",
|
||||||
|
description_text = "loc_popup_settings_require_restart_description",
|
||||||
|
options = {
|
||||||
|
{
|
||||||
|
text = "loc_confirm",
|
||||||
|
close_on_pressed = true,
|
||||||
|
callback = callback(function ()
|
||||||
|
self._popup_id = nil
|
||||||
|
local view_name = "dmf_options_view"
|
||||||
|
self._require_restart = false
|
||||||
|
|
||||||
|
Managers.ui:close_view(view_name)
|
||||||
|
end)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Managers.event:trigger("event_show_ui_popup", context, function (id)
|
||||||
|
self._popup_id = id
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
DMFOptionsView._setup_input_legend = function (self)
|
DMFOptionsView._setup_input_legend = function (self)
|
||||||
self._input_legend_element = self:_add_element(ViewElementInputLegend, "input_legend", 10)
|
self._input_legend_element = self:_add_element(ViewElementInputLegend, "input_legend", 10)
|
||||||
local legend_inputs = self._definitions.legend_inputs
|
local legend_inputs = self._definitions.legend_inputs
|
||||||
|
@ -225,9 +260,18 @@ DMFOptionsView._setup_content_grid_scrollbar = function (self, grid, widget_id,
|
||||||
|
|
||||||
load_scrolling_speed_setting()
|
load_scrolling_speed_setting()
|
||||||
|
|
||||||
grid:assign_scrollbar(scrollbar_widget, grid_pivot_scenegraph_id, grid_scenegraph_id)
|
grid:assign_scrollbar(scrollbar_widget, grid_pivot_scenegraph_id, grid_scenegraph_id, true)
|
||||||
|
|
||||||
|
-- Scroll the category grid to the default category widget
|
||||||
|
if widget_id == "scrollbar" and _last_selected_category_widget then
|
||||||
|
local index = grid:index_by_widget(_last_selected_category_widget)
|
||||||
|
local scroll_progress = grid:get_scrollbar_percentage_by_index(index)
|
||||||
|
|
||||||
|
grid:set_scrollbar_progress(scroll_progress)
|
||||||
|
else
|
||||||
grid:set_scrollbar_progress(0)
|
grid:set_scrollbar_progress(0)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
DMFOptionsView._setup_offscreen_gui = function (self)
|
DMFOptionsView._setup_offscreen_gui = function (self)
|
||||||
local ui_manager = Managers.ui
|
local ui_manager = Managers.ui
|
||||||
|
@ -292,6 +336,11 @@ DMFOptionsView._setup_content_widgets = function (self, content, scenegraph_id,
|
||||||
alignment_list[#alignment_list + 1] = widget or {
|
alignment_list[#alignment_list + 1] = widget or {
|
||||||
size = size
|
size = size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if entry.display_name == self._default_category then
|
||||||
|
_last_selected_category_entry = entry
|
||||||
|
_last_selected_category_widget = widget
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -617,9 +666,8 @@ DMFOptionsView._update_grid_navigation_selection = function (self)
|
||||||
end
|
end
|
||||||
elseif navigation_widgets or self._settings_content_widgets then
|
elseif navigation_widgets or self._settings_content_widgets then
|
||||||
self:_set_default_navigation_widget()
|
self:_set_default_navigation_widget()
|
||||||
elseif self._default_category then
|
|
||||||
self:present_category_widgets(self._default_category)
|
|
||||||
end
|
end
|
||||||
|
-- Removed extra condition for default category - moved to on_view_load_complete
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -629,6 +677,8 @@ DMFOptionsView.present_category_widgets = function (self, category)
|
||||||
local grid_data = settings_category_widgets[category]
|
local grid_data = settings_category_widgets[category]
|
||||||
|
|
||||||
if grid_data then
|
if grid_data then
|
||||||
|
dmf:set("options_menu_last_selected", category)
|
||||||
|
|
||||||
local widgets = {}
|
local widgets = {}
|
||||||
local alignment_widgets = {}
|
local alignment_widgets = {}
|
||||||
|
|
||||||
|
@ -644,7 +694,7 @@ DMFOptionsView.present_category_widgets = function (self, category)
|
||||||
local scrollbar_widget_id = "settings_scrollbar"
|
local scrollbar_widget_id = "settings_scrollbar"
|
||||||
local grid_scenegraph_id = "settings_grid_background"
|
local grid_scenegraph_id = "settings_grid_background"
|
||||||
local grid_pivot_scenegraph_id = "settings_grid_content_pivot"
|
local grid_pivot_scenegraph_id = "settings_grid_content_pivot"
|
||||||
local grid_spacing = _view_settings.grid_spacing
|
local grid_spacing = _view_settings.settings_grid_spacing
|
||||||
self._settings_content_grid = self:_setup_grid(self._settings_content_widgets, self._settings_alignment_list, grid_scenegraph_id, grid_spacing, false)
|
self._settings_content_grid = self:_setup_grid(self._settings_content_widgets, self._settings_alignment_list, grid_scenegraph_id, grid_spacing, false)
|
||||||
|
|
||||||
self:_setup_content_grid_scrollbar(self._settings_content_grid, scrollbar_widget_id, grid_scenegraph_id, grid_pivot_scenegraph_id)
|
self:_setup_content_grid_scrollbar(self._settings_content_grid, scrollbar_widget_id, grid_scenegraph_id, grid_pivot_scenegraph_id)
|
||||||
|
@ -667,7 +717,7 @@ DMFOptionsView._setup_category_config = function (self, config)
|
||||||
self._category_content_widgets = {}
|
self._category_content_widgets = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
local config_categories = config.categories
|
local config_categories = config.categories or {}
|
||||||
local entries = {}
|
local entries = {}
|
||||||
local reset_functions_by_category = {}
|
local reset_functions_by_category = {}
|
||||||
local categories_by_display_name = {}
|
local categories_by_display_name = {}
|
||||||
|
@ -706,14 +756,23 @@ DMFOptionsView._setup_category_config = function (self, config)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self._default_category = config_categories[1].display_name
|
-- Retrieve default category from settings
|
||||||
|
local category_setting = dmf:get("options_menu_last_selected")
|
||||||
|
if category_setting and not categories_by_display_name[category_setting] then
|
||||||
|
category_setting = false
|
||||||
|
end
|
||||||
|
|
||||||
|
self._default_category = category_setting or (
|
||||||
|
config_categories[1] and config_categories[1].display_name
|
||||||
|
)
|
||||||
|
|
||||||
local scenegraph_id = "grid_content_pivot"
|
local scenegraph_id = "grid_content_pivot"
|
||||||
local callback_name = "cb_on_category_pressed"
|
local callback_name = "cb_on_category_pressed"
|
||||||
self._category_content_widgets, self._category_alignment_list = self:_setup_content_widgets(entries, scenegraph_id, callback_name)
|
self._category_content_widgets, self._category_alignment_list = self:_setup_content_widgets(entries, scenegraph_id, callback_name)
|
||||||
local scrollbar_widget_id = "scrollbar"
|
local scrollbar_widget_id = "scrollbar"
|
||||||
local grid_scenegraph_id = "background"
|
local grid_scenegraph_id = "background"
|
||||||
local grid_pivot_scenegraph_id = "grid_content_pivot"
|
local grid_pivot_scenegraph_id = "grid_content_pivot"
|
||||||
local grid_spacing = _view_settings.grid_spacing
|
local grid_spacing = _view_settings.category_grid_spacing
|
||||||
self._category_content_grid = self:_setup_grid(self._category_content_widgets, self._category_alignment_list, grid_scenegraph_id, grid_spacing, true)
|
self._category_content_grid = self:_setup_grid(self._category_content_widgets, self._category_alignment_list, grid_scenegraph_id, grid_spacing, true)
|
||||||
|
|
||||||
self:_setup_content_grid_scrollbar(self._category_content_grid, scrollbar_widget_id, grid_scenegraph_id, grid_pivot_scenegraph_id)
|
self:_setup_content_grid_scrollbar(self._category_content_grid, scrollbar_widget_id, grid_scenegraph_id, grid_pivot_scenegraph_id)
|
||||||
|
@ -746,6 +805,7 @@ DMFOptionsView._setup_settings_config = function (self, config)
|
||||||
local settings_default_values = {}
|
local settings_default_values = {}
|
||||||
local aligment_list = {}
|
local aligment_list = {}
|
||||||
local callback_name = "cb_on_settings_pressed"
|
local callback_name = "cb_on_settings_pressed"
|
||||||
|
local changed_callback_name = "cb_on_settings_changed"
|
||||||
|
|
||||||
for setting_index, setting in ipairs(config_settings) do
|
for setting_index, setting in ipairs(config_settings) do
|
||||||
local valid = self._validation_mapping[setting.category].settings[setting.display_name].validation_result
|
local valid = self._validation_mapping[setting.category].settings[setting.display_name].validation_result
|
||||||
|
@ -768,7 +828,7 @@ DMFOptionsView._setup_settings_config = function (self, config)
|
||||||
end
|
end
|
||||||
|
|
||||||
local widget_suffix = "setting_" .. tostring(setting_index)
|
local widget_suffix = "setting_" .. tostring(setting_index)
|
||||||
local widget, alignment_widget = self:_create_settings_widget_from_config(setting, category, widget_suffix, callback_name)
|
local widget, alignment_widget = self:_create_settings_widget_from_config(setting, category, widget_suffix, callback_name, changed_callback_name)
|
||||||
category_widgets[category][#widgets + 1] = {
|
category_widgets[category][#widgets + 1] = {
|
||||||
widget = widget,
|
widget = widget,
|
||||||
alignment_widget = alignment_widget
|
alignment_widget = alignment_widget
|
||||||
|
@ -811,19 +871,24 @@ end
|
||||||
|
|
||||||
DMFOptionsView._set_tooltip_data = function (self, widget)
|
DMFOptionsView._set_tooltip_data = function (self, widget)
|
||||||
local current_widget = self._tooltip_data and self._tooltip_data.widget
|
local current_widget = self._tooltip_data and self._tooltip_data.widget
|
||||||
local display_text = nil
|
local localized_text = nil
|
||||||
local tooltip_text = widget.content.entry.tooltip_text
|
local tooltip_text = widget.content.entry.tooltip_text
|
||||||
local disabled_by_list = widget.content.entry.disabled_by
|
local disabled_by_list = widget.content.entry.disabled_by
|
||||||
|
|
||||||
if tooltip_text then
|
if tooltip_text then
|
||||||
display_text = tooltip_text
|
if type(tooltip_text) == "function" then
|
||||||
|
localized_text = tooltip_text()
|
||||||
|
else
|
||||||
|
-- Should already be localized in mod option generation
|
||||||
|
localized_text = tooltip_text
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if disabled_by_list then
|
if disabled_by_list then
|
||||||
display_text = display_text and string.format("%s\n", display_text)
|
localized_text = localized_text and string.format("%s\n", localized_text)
|
||||||
|
|
||||||
for _, text in pairs(disabled_by_list) do
|
for _, text in pairs(disabled_by_list) do
|
||||||
display_text = display_text and string.format("%s\n%s", display_text, text) or text
|
localized_text = localized_text and string.format("%s\n%s", localized_text, text) or text
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -835,14 +900,14 @@ DMFOptionsView._set_tooltip_data = function (self, widget)
|
||||||
if current_widget ~= widget or current_widget == widget and new_y ~= current_y then
|
if current_widget ~= widget or current_widget == widget and new_y ~= current_y then
|
||||||
self._tooltip_data = {
|
self._tooltip_data = {
|
||||||
widget = widget,
|
widget = widget,
|
||||||
text = display_text
|
text = localized_text
|
||||||
}
|
}
|
||||||
self._widgets_by_name.tooltip.content.text = display_text
|
self._widgets_by_name.tooltip.content.text = localized_text
|
||||||
local text_style = self._widgets_by_name.tooltip.style.text
|
local text_style = self._widgets_by_name.tooltip.style.text
|
||||||
local x_pos = starting_point[1] + widget.offset[1]
|
local x_pos = starting_point[1] + widget.offset[1]
|
||||||
local width = widget.content.size[1] * 0.5
|
local width = widget.content.size[1] * 0.5
|
||||||
local text_options = UIFonts.get_font_options_by_style(text_style)
|
local text_options = UIFonts.get_font_options_by_style(text_style)
|
||||||
local _, text_height = self:_text_size(display_text, text_style.font_type, text_style.font_size, {
|
local _, text_height = self:_text_size(localized_text, text_style.font_type, text_style.font_size, {
|
||||||
width,
|
width,
|
||||||
0
|
0
|
||||||
}, text_options)
|
}, text_options)
|
||||||
|
@ -852,7 +917,7 @@ DMFOptionsView._set_tooltip_data = function (self, widget)
|
||||||
height
|
height
|
||||||
}
|
}
|
||||||
self._widgets_by_name.tooltip.offset[1] = x_pos - width * 0.8
|
self._widgets_by_name.tooltip.offset[1] = x_pos - width * 0.8
|
||||||
self._widgets_by_name.tooltip.offset[2] = new_y - height
|
self._widgets_by_name.tooltip.offset[2] = math.max(new_y - height, 20)
|
||||||
self._widgets_by_name.tooltip.content.visible = true
|
self._widgets_by_name.tooltip.content.visible = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -891,7 +956,7 @@ DMFOptionsView._update_settings_content_widgets = function (self, dt, t, input_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
DMFOptionsView._create_settings_widget_from_config = function (self, config, category, suffix, callback_name)
|
DMFOptionsView._create_settings_widget_from_config = function (self, config, category, suffix, callback_name, changed_callback_name)
|
||||||
local scenegraph_id = "settings_grid_content_pivot"
|
local scenegraph_id = "settings_grid_content_pivot"
|
||||||
local default_value = config.default_value
|
local default_value = config.default_value
|
||||||
local default_value_type = type(default_value)
|
local default_value_type = type(default_value)
|
||||||
|
@ -945,7 +1010,7 @@ DMFOptionsView._create_settings_widget_from_config = function (self, config, cat
|
||||||
local init = template.init
|
local init = template.init
|
||||||
|
|
||||||
if init then
|
if init then
|
||||||
init(self, widget, config, callback_name)
|
init(self, widget, config, callback_name, changed_callback_name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1079,6 +1144,27 @@ DMFOptionsView.cb_on_settings_pressed = function (self, widget, entry)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
DMFOptionsView.cb_on_settings_changed = function (self, widget, entry, option_value)
|
||||||
|
if not self._require_restart then
|
||||||
|
|
||||||
|
-- Entry supersedes option
|
||||||
|
if entry.require_restart then
|
||||||
|
self._require_restart = true
|
||||||
|
|
||||||
|
-- Search by option value
|
||||||
|
elseif option_value then
|
||||||
|
for i = 1, #entry.options do
|
||||||
|
local option = entry.options[i]
|
||||||
|
|
||||||
|
if option.value == option_value then
|
||||||
|
self._require_restart = option.require_restart
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
DMFOptionsView._enable_settings_overlay = function (self, enable)
|
DMFOptionsView._enable_settings_overlay = function (self, enable)
|
||||||
local widgets_by_name = self._widgets_by_name
|
local widgets_by_name = self._widgets_by_name
|
||||||
local settings_overlay_widget = widgets_by_name.settings_overlay
|
local settings_overlay_widget = widgets_by_name.settings_overlay
|
||||||
|
@ -1244,4 +1330,13 @@ DMFOptionsView._set_selected_grid_widget = function (self, widgets, widget_name)
|
||||||
return selected_widget, selected_widget_index
|
return selected_widget, selected_widget_index
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Handles navigation to the last selected category widget
|
||||||
|
DMFOptionsView._on_view_load_complete = function (self, loaded)
|
||||||
|
DMFOptionsView.super._on_view_load_complete(self, loaded)
|
||||||
|
|
||||||
|
if _last_selected_category_entry and _last_selected_category_widget then
|
||||||
|
self:cb_on_category_pressed(_last_selected_category_widget, _last_selected_category_entry)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return DMFOptionsView
|
return DMFOptionsView
|
||||||
|
|
|
@ -23,6 +23,9 @@ local group_header_height = 80
|
||||||
|
|
||||||
local DEFAULT_NUM_DECIMALS = 0
|
local DEFAULT_NUM_DECIMALS = 0
|
||||||
|
|
||||||
|
local _dropdown_deadzone = 0.25 -- 250ms delay before opening keybind popups
|
||||||
|
local _last_dropdown_pressed = -1
|
||||||
|
|
||||||
local value_font_style = table.clone(UIFontSettings.list_button)
|
local value_font_style = table.clone(UIFontSettings.list_button)
|
||||||
value_font_style.offset = {
|
value_font_style.offset = {
|
||||||
settings_grid_width - settings_value_width + 25,
|
settings_grid_width - settings_value_width + 25,
|
||||||
|
@ -53,7 +56,7 @@ local blueprints = {
|
||||||
settings_value_height
|
settings_value_height
|
||||||
},
|
},
|
||||||
pass_template = ButtonPassTemplates.list_button,
|
pass_template = ButtonPassTemplates.list_button,
|
||||||
init = function (parent, widget, entry, callback_name)
|
init = function (parent, widget, entry, callback_name, changed_callback_name)
|
||||||
local content = widget.content
|
local content = widget.content
|
||||||
local hotspot = content.hotspot
|
local hotspot = content.hotspot
|
||||||
|
|
||||||
|
@ -78,7 +81,7 @@ local blueprints = {
|
||||||
settings_value_height
|
settings_value_height
|
||||||
},
|
},
|
||||||
pass_template = ButtonPassTemplates.settings_button(settings_grid_width, settings_value_height, settings_value_width, true),
|
pass_template = ButtonPassTemplates.settings_button(settings_grid_width, settings_value_height, settings_value_width, true),
|
||||||
init = function (parent, widget, entry, callback_name)
|
init = function (parent, widget, entry, callback_name, changed_callback_name)
|
||||||
local content = widget.content
|
local content = widget.content
|
||||||
|
|
||||||
content.hotspot.pressed_callback = function ()
|
content.hotspot.pressed_callback = function ()
|
||||||
|
@ -95,6 +98,10 @@ local blueprints = {
|
||||||
content.text = display_name
|
content.text = display_name
|
||||||
content.button_text = Localize("loc_settings_change")
|
content.button_text = Localize("loc_settings_change")
|
||||||
content.entry = entry
|
content.entry = entry
|
||||||
|
|
||||||
|
entry.changed_callback = function (changed_value)
|
||||||
|
callback(parent, changed_callback_name, widget, entry)()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
group_header = {
|
group_header = {
|
||||||
|
@ -110,7 +117,7 @@ local blueprints = {
|
||||||
value = Localize("loc_settings_option_unavailable")
|
value = Localize("loc_settings_option_unavailable")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
init = function (parent, widget, entry, callback_name)
|
init = function (parent, widget, entry, callback_name, changed_callback_name)
|
||||||
local content = widget.content
|
local content = widget.content
|
||||||
local display_name = entry.display_name
|
local display_name = entry.display_name
|
||||||
content.text = display_name
|
content.text = display_name
|
||||||
|
@ -124,9 +131,9 @@ local blueprints = {
|
||||||
pass_template_function = function (parent, config, size)
|
pass_template_function = function (parent, config, size)
|
||||||
return CheckboxPassTemplates.settings_checkbox(size[1], settings_value_height, settings_value_width, 2, true)
|
return CheckboxPassTemplates.settings_checkbox(size[1], settings_value_height, settings_value_width, 2, true)
|
||||||
end,
|
end,
|
||||||
init = function (parent, widget, entry, callback_name)
|
init = function (parent, widget, entry, callback_name, changed_callback_name)
|
||||||
local content = widget.content
|
local content = widget.content
|
||||||
local display_name = entry.display_name or Localize("loc_settings_option_unavailable")
|
local display_name = entry.display_name or Managers.localization:localize("loc_settings_option_unavailable")
|
||||||
content.text = display_name
|
content.text = display_name
|
||||||
content.entry = entry
|
content.entry = entry
|
||||||
|
|
||||||
|
@ -134,6 +141,11 @@ local blueprints = {
|
||||||
local widget_option_id = "option_" .. i
|
local widget_option_id = "option_" .. i
|
||||||
content[widget_option_id] = i == 1 and Managers.localization:localize("loc_setting_checkbox_on") or Managers.localization:localize("loc_setting_checkbox_off")
|
content[widget_option_id] = i == 1 and Managers.localization:localize("loc_setting_checkbox_on") or Managers.localization:localize("loc_setting_checkbox_off")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
entry.changed_callback = function (changed_value)
|
||||||
|
--callback(parent, callback_name, widget, entry)()
|
||||||
|
callback(parent, changed_callback_name, widget, entry)()
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
update = function (parent, widget, input_service, dt, t)
|
update = function (parent, widget, input_service, dt, t)
|
||||||
local content = widget.content
|
local content = widget.content
|
||||||
|
@ -146,7 +158,7 @@ local blueprints = {
|
||||||
content.disabled = is_disabled
|
content.disabled = is_disabled
|
||||||
local new_value = nil
|
local new_value = nil
|
||||||
|
|
||||||
if hotspot.on_pressed and not is_disabled then
|
if hotspot.on_pressed and not parent._navigation_column_changed_this_frame and not is_disabled then
|
||||||
new_value = not value
|
new_value = not value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -159,14 +171,15 @@ local blueprints = {
|
||||||
|
|
||||||
if new_value ~= nil and new_value ~= value then
|
if new_value ~= nil and new_value ~= value then
|
||||||
on_activated(new_value, entry)
|
on_activated(new_value, entry)
|
||||||
|
entry.changed_callback(new_value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
local function slider_init_function(parent, widget, entry, callback_name)
|
local function slider_init_function(parent, widget, entry, callback_name, changed_callback_name)
|
||||||
local content = widget.content
|
local content = widget.content
|
||||||
local display_name = entry.display_name or Localize("loc_settings_option_unavailable")
|
local display_name = entry.display_name or Managers.localization:localize("loc_settings_option_unavailable")
|
||||||
content.text = display_name
|
content.text = display_name
|
||||||
content.entry = entry
|
content.entry = entry
|
||||||
content.area_length = settings_value_width
|
content.area_length = settings_value_width
|
||||||
|
@ -183,7 +196,7 @@ local function slider_init_function(parent, widget, entry, callback_name)
|
||||||
content.previous_slider_value = value
|
content.previous_slider_value = value
|
||||||
content.slider_value = value
|
content.slider_value = value
|
||||||
|
|
||||||
content.pressed_callback = function ()
|
entry.pressed_callback = function ()
|
||||||
local is_disabled = entry.is_disabled
|
local is_disabled = entry.is_disabled
|
||||||
|
|
||||||
if is_disabled then
|
if is_disabled then
|
||||||
|
@ -192,6 +205,10 @@ local function slider_init_function(parent, widget, entry, callback_name)
|
||||||
|
|
||||||
callback(parent, callback_name, widget, entry)()
|
callback(parent, callback_name, widget, entry)()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
entry.changed_callback = function (changed_value)
|
||||||
|
callback(parent, changed_callback_name, widget, entry)()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
blueprints.percent_slider = {
|
blueprints.percent_slider = {
|
||||||
|
@ -202,8 +219,8 @@ blueprints.percent_slider = {
|
||||||
pass_template_function = function (parent, config, size)
|
pass_template_function = function (parent, config, size)
|
||||||
return SliderPassTemplates.settings_percent_slider(size[1], settings_value_height, settings_value_width, true)
|
return SliderPassTemplates.settings_percent_slider(size[1], settings_value_height, settings_value_width, true)
|
||||||
end,
|
end,
|
||||||
init = function (parent, widget, entry, callback_name)
|
init = function (parent, widget, entry, callback_name, changed_callback_name)
|
||||||
slider_init_function(parent, widget, entry, callback_name)
|
slider_init_function(parent, widget, entry, callback_name, changed_callback_name)
|
||||||
end,
|
end,
|
||||||
update = function (parent, widget, input_service, dt, t)
|
update = function (parent, widget, input_service, dt, t)
|
||||||
local content = widget.content
|
local content = widget.content
|
||||||
|
@ -260,8 +277,8 @@ blueprints.percent_slider = {
|
||||||
if hotspot.on_pressed and not is_disabled then
|
if hotspot.on_pressed and not is_disabled then
|
||||||
if focused then
|
if focused then
|
||||||
new_value = content.slider_value
|
new_value = content.slider_value
|
||||||
elseif using_gamepad then
|
elseif using_gamepad and entry.pressed_callback then
|
||||||
content.pressed_callback()
|
entry.pressed_callback()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -275,6 +292,7 @@ blueprints.percent_slider = {
|
||||||
|
|
||||||
if new_value then
|
if new_value then
|
||||||
on_activated(new_value * 100, entry)
|
on_activated(new_value * 100, entry)
|
||||||
|
entry.changed_callback(new_value)
|
||||||
|
|
||||||
content.slider_value = new_value
|
content.slider_value = new_value
|
||||||
content.previous_slider_value = new_value
|
content.previous_slider_value = new_value
|
||||||
|
@ -293,8 +311,8 @@ blueprints.value_slider = {
|
||||||
pass_template_function = function (parent, config, size)
|
pass_template_function = function (parent, config, size)
|
||||||
return SliderPassTemplates.settings_value_slider(size[1], settings_value_height, settings_value_width, true)
|
return SliderPassTemplates.settings_value_slider(size[1], settings_value_height, settings_value_width, true)
|
||||||
end,
|
end,
|
||||||
init = function (parent, widget, entry, callback_name)
|
init = function (parent, widget, entry, callback_name, changed_callback_name)
|
||||||
slider_init_function(parent, widget, entry, callback_name)
|
slider_init_function(parent, widget, entry, callback_name, changed_callback_name)
|
||||||
end,
|
end,
|
||||||
update = function (parent, widget, input_service, dt, t)
|
update = function (parent, widget, input_service, dt, t)
|
||||||
local content = widget.content
|
local content = widget.content
|
||||||
|
@ -356,8 +374,8 @@ blueprints.value_slider = {
|
||||||
if hotspot.on_pressed then
|
if hotspot.on_pressed then
|
||||||
if focused then
|
if focused then
|
||||||
new_normalized_value = content.slider_value
|
new_normalized_value = content.slider_value
|
||||||
elseif using_gamepad then
|
elseif using_gamepad and entry.pressed_callback then
|
||||||
content.pressed_callback()
|
entry.pressed_callback()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -373,6 +391,7 @@ blueprints.value_slider = {
|
||||||
local new_value = explode_function(new_normalized_value, entry)
|
local new_value = explode_function(new_normalized_value, entry)
|
||||||
|
|
||||||
on_activated(new_value, entry)
|
on_activated(new_value, entry)
|
||||||
|
entry.changed_callback(new_value)
|
||||||
|
|
||||||
content.slider_value = new_normalized_value
|
content.slider_value = new_normalized_value
|
||||||
content.previous_slider_value = new_normalized_value
|
content.previous_slider_value = new_normalized_value
|
||||||
|
@ -391,9 +410,9 @@ blueprints.slider = {
|
||||||
pass_template_function = function (parent, config, size)
|
pass_template_function = function (parent, config, size)
|
||||||
return SliderPassTemplates.settings_value_slider(size[1], settings_value_height, settings_value_width, true)
|
return SliderPassTemplates.settings_value_slider(size[1], settings_value_height, settings_value_width, true)
|
||||||
end,
|
end,
|
||||||
init = function (parent, widget, entry, callback_name)
|
init = function (parent, widget, entry, callback_name, changed_callback_name)
|
||||||
local content = widget.content
|
local content = widget.content
|
||||||
local display_name = entry.display_name or Localize("loc_settings_option_unavailable")
|
local display_name = entry.display_name or Managers.localization:localize("loc_settings_option_unavailable")
|
||||||
content.text = display_name
|
content.text = display_name
|
||||||
content.entry = entry
|
content.entry = entry
|
||||||
content.area_length = settings_value_width
|
content.area_length = settings_value_width
|
||||||
|
@ -403,7 +422,11 @@ blueprints.slider = {
|
||||||
local value, value_fraction = get_function(entry)
|
local value, value_fraction = get_function(entry)
|
||||||
content.previous_slider_value = value_fraction
|
content.previous_slider_value = value_fraction
|
||||||
content.slider_value = value_fraction
|
content.slider_value = value_fraction
|
||||||
content.pressed_callback = callback(parent, callback_name, widget, entry)
|
entry.pressed_callback = callback(parent, callback_name, widget, entry)
|
||||||
|
|
||||||
|
entry.changed_callback = function (changed_value)
|
||||||
|
callback(parent, changed_callback_name, widget, entry)()
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
update = function (parent, widget, input_service, dt, t)
|
update = function (parent, widget, input_service, dt, t)
|
||||||
local content = widget.content
|
local content = widget.content
|
||||||
|
@ -463,7 +486,7 @@ blueprints.slider = {
|
||||||
if focused then
|
if focused then
|
||||||
new_value_fraction = content.slider_value
|
new_value_fraction = content.slider_value
|
||||||
elseif not hotspot.is_hover then
|
elseif not hotspot.is_hover then
|
||||||
content.pressed_callback()
|
entry.pressed_callback()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -479,6 +502,7 @@ blueprints.slider = {
|
||||||
local new_value = math.lerp(entry.min_value, entry.max_value, new_value_fraction)
|
local new_value = math.lerp(entry.min_value, entry.max_value, new_value_fraction)
|
||||||
|
|
||||||
on_activated(new_value, entry)
|
on_activated(new_value, entry)
|
||||||
|
entry.changed_callback(new_value)
|
||||||
|
|
||||||
content.slider_value = new_value_fraction
|
content.slider_value = new_value_fraction
|
||||||
content.previous_slider_value = new_value_fraction
|
content.previous_slider_value = new_value_fraction
|
||||||
|
@ -504,9 +528,9 @@ blueprints.dropdown = {
|
||||||
|
|
||||||
return DropdownPassTemplates.settings_dropdown(size[1], settings_value_height, settings_value_width, num_visible_options, true)
|
return DropdownPassTemplates.settings_dropdown(size[1], settings_value_height, settings_value_width, num_visible_options, true)
|
||||||
end,
|
end,
|
||||||
init = function (parent, widget, entry, callback_name)
|
init = function (parent, widget, entry, callback_name, changed_callback_name)
|
||||||
local content = widget.content
|
local content = widget.content
|
||||||
local display_name = entry.display_name or Localize("loc_settings_option_unavailable")
|
local display_name = entry.display_name or Managers.localization:localize("loc_settings_option_unavailable")
|
||||||
content.text = display_name
|
content.text = display_name
|
||||||
content.entry = entry
|
content.entry = entry
|
||||||
local has_options_function = entry.options_function ~= nil
|
local has_options_function = entry.options_function ~= nil
|
||||||
|
@ -548,6 +572,10 @@ blueprints.dropdown = {
|
||||||
local scroll_amount = scroll_length > 0 and (size[2] + spacing) / scroll_length or 0
|
local scroll_amount = scroll_length > 0 and (size[2] + spacing) / scroll_length or 0
|
||||||
content.scroll_amount = scroll_amount
|
content.scroll_amount = scroll_amount
|
||||||
local value = entry.get_function and entry:get_function() or entry.default_value
|
local value = entry.get_function and entry:get_function() or entry.default_value
|
||||||
|
|
||||||
|
entry.changed_callback = function (changed_value)
|
||||||
|
callback(parent, changed_callback_name, widget, entry, changed_value)()
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
update = function (parent, widget, input_service, dt, t)
|
update = function (parent, widget, input_service, dt, t)
|
||||||
local content = widget.content
|
local content = widget.content
|
||||||
|
@ -577,7 +605,7 @@ blueprints.dropdown = {
|
||||||
|
|
||||||
if selected_index and focused then
|
if selected_index and focused then
|
||||||
if using_gamepad and hotspot.on_pressed then
|
if using_gamepad and hotspot.on_pressed then
|
||||||
new_value = options[selected_index].id
|
new_value = options[selected_index].value
|
||||||
end
|
end
|
||||||
|
|
||||||
hotspot_style.on_pressed_sound = hotspot_style.on_pressed_fold_in_sound
|
hotspot_style.on_pressed_sound = hotspot_style.on_pressed_fold_in_sound
|
||||||
|
@ -588,8 +616,8 @@ blueprints.dropdown = {
|
||||||
value = entry.get_function and entry:get_function() or content.internal_value or "<not selected>"
|
value = entry.get_function and entry:get_function() or content.internal_value or "<not selected>"
|
||||||
|
|
||||||
local preview_option = options_by_value[value]
|
local preview_option = options_by_value[value]
|
||||||
local preview_option_id = preview_option and preview_option.id
|
local preview_option_value = preview_option and preview_option.value
|
||||||
local preview_value = preview_option and preview_option.display_name or Localize("loc_settings_option_unavailable")
|
local preview_value = preview_option and preview_option.display_name or Managers.localization:localize("loc_settings_option_unavailable")
|
||||||
|
|
||||||
content.value_text = preview_value
|
content.value_text = preview_value
|
||||||
|
|
||||||
|
@ -600,6 +628,7 @@ blueprints.dropdown = {
|
||||||
local scroll_area_height = parent:settings_grid_length()
|
local scroll_area_height = parent:settings_grid_length()
|
||||||
local dropdown_length = size[2] * (num_visible_options + 1)
|
local dropdown_length = size[2] * (num_visible_options + 1)
|
||||||
local grow_downwards = true
|
local grow_downwards = true
|
||||||
|
local always_keep_order = true
|
||||||
|
|
||||||
if scroll_area_height <= offset[2] - scroll_amount + dropdown_length then
|
if scroll_area_height <= offset[2] - scroll_amount + dropdown_length then
|
||||||
grow_downwards = false
|
grow_downwards = false
|
||||||
|
@ -612,7 +641,7 @@ blueprints.dropdown = {
|
||||||
for i = 1, #options do
|
for i = 1, #options do
|
||||||
local option = options[i]
|
local option = options[i]
|
||||||
|
|
||||||
if option.id == preview_option_id then
|
if option.value == preview_option_value then
|
||||||
selected_index = i
|
selected_index = i
|
||||||
|
|
||||||
break
|
break
|
||||||
|
@ -624,13 +653,13 @@ blueprints.dropdown = {
|
||||||
|
|
||||||
if selected_index and focused then
|
if selected_index and focused then
|
||||||
if input_service:get("navigate_up_continuous") then
|
if input_service:get("navigate_up_continuous") then
|
||||||
if grow_downwards then
|
if grow_downwards or not grow_downwards and always_keep_order then
|
||||||
new_selection_index = math.max(selected_index - 1, 1)
|
new_selection_index = math.max(selected_index - 1, 1)
|
||||||
else
|
else
|
||||||
new_selection_index = math.min(selected_index + 1, num_options)
|
new_selection_index = math.min(selected_index + 1, num_options)
|
||||||
end
|
end
|
||||||
elseif input_service:get("navigate_down_continuous") then
|
elseif input_service:get("navigate_down_continuous") then
|
||||||
if grow_downwards then
|
if grow_downwards or not grow_downwards and always_keep_order then
|
||||||
new_selection_index = math.min(selected_index + 1, num_options)
|
new_selection_index = math.min(selected_index + 1, num_options)
|
||||||
else
|
else
|
||||||
new_selection_index = math.max(selected_index - 1, 1)
|
new_selection_index = math.max(selected_index - 1, 1)
|
||||||
|
@ -667,18 +696,24 @@ blueprints.dropdown = {
|
||||||
local using_scrollbar = num_visible_options < num_options
|
local using_scrollbar = num_visible_options < num_options
|
||||||
|
|
||||||
for i = start_index, end_index do
|
for i = start_index, end_index do
|
||||||
|
local actual_i = i
|
||||||
|
|
||||||
|
if not grow_downwards and always_keep_order then
|
||||||
|
actual_i = end_index - i + start_index
|
||||||
|
end
|
||||||
|
|
||||||
local option_text_id = "option_text_" .. option_index
|
local option_text_id = "option_text_" .. option_index
|
||||||
local option_hotspot_id = "option_hotspot_" .. option_index
|
local option_hotspot_id = "option_hotspot_" .. option_index
|
||||||
local outline_style_id = "outline_" .. option_index
|
local outline_style_id = "outline_" .. option_index
|
||||||
local option_hotspot = content[option_hotspot_id]
|
local option_hotspot = content[option_hotspot_id]
|
||||||
option_hovered = option_hovered or option_hotspot.is_hover
|
option_hovered = option_hovered or option_hotspot.is_hover
|
||||||
option_hotspot.is_selected = i == selected_index
|
option_hotspot.is_selected = actual_i == selected_index
|
||||||
local option = options[i]
|
local option = options[actual_i]
|
||||||
|
|
||||||
if not new_value and focused and not using_gamepad and option_hotspot.on_pressed then
|
if not new_value and focused and not using_gamepad and option_hotspot.on_pressed then
|
||||||
option_hotspot.on_pressed = nil
|
option_hotspot.on_pressed = nil
|
||||||
new_value = option.value
|
new_value = option.value
|
||||||
content.selected_index = i
|
content.selected_index = actual_i
|
||||||
end
|
end
|
||||||
|
|
||||||
local option_display_name = option.display_name
|
local option_display_name = option.display_name
|
||||||
|
@ -694,10 +729,13 @@ blueprints.dropdown = {
|
||||||
|
|
||||||
local value_changed = new_value ~= nil
|
local value_changed = new_value ~= nil
|
||||||
|
|
||||||
if value_changed and new_value ~= value then
|
if value_changed then
|
||||||
|
_last_dropdown_pressed = t
|
||||||
|
if new_value ~= value then
|
||||||
local on_activated = entry.on_activated
|
local on_activated = entry.on_activated
|
||||||
|
|
||||||
on_activated(new_value, entry)
|
on_activated(new_value, entry)
|
||||||
|
entry.changed_callback(new_value)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local scrollbar_hotspot = content.scrollbar_hotspot
|
local scrollbar_hotspot = content.scrollbar_hotspot
|
||||||
|
@ -714,9 +752,9 @@ blueprints.keybind = {
|
||||||
settings_value_height
|
settings_value_height
|
||||||
},
|
},
|
||||||
pass_template = KeybindPassTemplates.settings_keybind(settings_grid_width, settings_value_height, settings_value_width),
|
pass_template = KeybindPassTemplates.settings_keybind(settings_grid_width, settings_value_height, settings_value_width),
|
||||||
init = function (parent, widget, entry, callback_name)
|
init = function (parent, widget, entry, callback_name, changed_callback_name)
|
||||||
local content = widget.content
|
local content = widget.content
|
||||||
local display_name = entry.display_name or Localize("loc_settings_option_unavailable")
|
local display_name = entry.display_name or parent:_localize("loc_settings_option_unavailable")
|
||||||
content.text = display_name
|
content.text = display_name
|
||||||
content.entry = entry
|
content.entry = entry
|
||||||
content.key_unassigned_string = Managers.localization:localize("loc_keybind_unassigned")
|
content.key_unassigned_string = Managers.localization:localize("loc_keybind_unassigned")
|
||||||
|
@ -730,7 +768,11 @@ blueprints.keybind = {
|
||||||
local hotspot = content.hotspot
|
local hotspot = content.hotspot
|
||||||
|
|
||||||
if hotspot.on_released then
|
if hotspot.on_released then
|
||||||
|
if (t - _last_dropdown_pressed) > _dropdown_deadzone then
|
||||||
parent:show_keybind_popup(widget, entry, content.entry.cancel_keys)
|
parent:show_keybind_popup(widget, entry, content.entry.cancel_keys)
|
||||||
|
else
|
||||||
|
_last_dropdown_pressed = -1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
@ -763,8 +805,7 @@ blueprints.description = {
|
||||||
local content = widget.content
|
local content = widget.content
|
||||||
local style = widget.style
|
local style = widget.style
|
||||||
local text_style = style.text
|
local text_style = style.text
|
||||||
local display_name = entry.display_name
|
local display_text = entry.display_name
|
||||||
local display_text = display_name
|
|
||||||
local ui_renderer = parent._ui_renderer
|
local ui_renderer = parent._ui_renderer
|
||||||
local size = content.size
|
local size = content.size
|
||||||
local text_options = UIFonts.get_font_options_by_style(text_style)
|
local text_options = UIFonts.get_font_options_by_style(text_style)
|
||||||
|
|
|
@ -25,6 +25,7 @@ local settings_mask_size = {
|
||||||
}
|
}
|
||||||
|
|
||||||
local settings_grid_height = grid_height + mask_offset_y
|
local settings_grid_height = grid_height + mask_offset_y
|
||||||
|
local settings_grid_scroll_amount = math.clamp((dmf:get("dmf_options_scrolling_speed") or 100) / 1000, 0.05, 0.5)
|
||||||
|
|
||||||
local tooltip_text_style = table.clone(UIFontSettings.body)
|
local tooltip_text_style = table.clone(UIFontSettings.body)
|
||||||
tooltip_text_style.text_horizontal_alignment = "left"
|
tooltip_text_style.text_horizontal_alignment = "left"
|
||||||
|
@ -62,9 +63,10 @@ local scenegraph_definition = {
|
||||||
grid_width,
|
grid_width,
|
||||||
grid_height
|
grid_height
|
||||||
},
|
},
|
||||||
|
-- Move the categories up and left to compensate for removed icons
|
||||||
position = {
|
position = {
|
||||||
180,
|
140,
|
||||||
240,
|
190,
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -385,7 +387,10 @@ local widget_definitions = {
|
||||||
}, "tooltip", {
|
}, "tooltip", {
|
||||||
visible = false
|
visible = false
|
||||||
}),
|
}),
|
||||||
scrollbar = UIWidget.create_definition(ScrollbarPassTemplates.default_scrollbar, "scrollbar"),
|
scrollbar = UIWidget.create_definition(ScrollbarPassTemplates.default_scrollbar, "scrollbar", {
|
||||||
|
scroll_speed = 10,
|
||||||
|
scroll_amount = settings_grid_scroll_amount,
|
||||||
|
}),
|
||||||
grid_mask = UIWidget.create_definition({
|
grid_mask = UIWidget.create_definition({
|
||||||
{
|
{
|
||||||
value = "content/ui/materials/offscreen_masks/ui_overlay_offscreen_vertical_blur",
|
value = "content/ui/materials/offscreen_masks/ui_overlay_offscreen_vertical_blur",
|
||||||
|
@ -406,7 +411,10 @@ local widget_definitions = {
|
||||||
content_id = "hotspot"
|
content_id = "hotspot"
|
||||||
}
|
}
|
||||||
}, "grid_interaction"),
|
}, "grid_interaction"),
|
||||||
settings_scrollbar = UIWidget.create_definition(ScrollbarPassTemplates.default_scrollbar, "settings_scrollbar"),
|
settings_scrollbar = UIWidget.create_definition(ScrollbarPassTemplates.default_scrollbar, "settings_scrollbar", {
|
||||||
|
scroll_speed = 10,
|
||||||
|
scroll_amount = settings_grid_scroll_amount,
|
||||||
|
}),
|
||||||
settings_grid_mask = UIWidget.create_definition({
|
settings_grid_mask = UIWidget.create_definition({
|
||||||
{
|
{
|
||||||
value = "content/ui/materials/offscreen_masks/ui_overlay_offscreen_vertical_blur",
|
value = "content/ui/materials/offscreen_masks/ui_overlay_offscreen_vertical_blur",
|
||||||
|
|
|
@ -5,9 +5,13 @@ local dmf_options_view_settings = {
|
||||||
shading_environment = "content/shading_environments/ui/system_menu",
|
shading_environment = "content/shading_environments/ui/system_menu",
|
||||||
grid_size = {
|
grid_size = {
|
||||||
500,
|
500,
|
||||||
800
|
820 -- Increased to compensate for upshifted category grid
|
||||||
},
|
},
|
||||||
grid_spacing = {
|
category_grid_spacing = {
|
||||||
|
0,
|
||||||
|
3
|
||||||
|
},
|
||||||
|
settings_grid_spacing = {
|
||||||
0,
|
0,
|
||||||
10
|
10
|
||||||
},
|
},
|
||||||
|
|
|
@ -6,13 +6,22 @@ local _type_template_map = {}
|
||||||
|
|
||||||
local _devices = {
|
local _devices = {
|
||||||
"keyboard",
|
"keyboard",
|
||||||
"mouse"
|
"mouse",
|
||||||
}
|
}
|
||||||
|
|
||||||
local _cancel_keys = {
|
local _cancel_keys = {
|
||||||
"keyboard_esc"
|
"keyboard_esc"
|
||||||
}
|
}
|
||||||
|
|
||||||
local _reserved_keys = {}
|
local _reserved_keys = {}
|
||||||
|
|
||||||
|
local ERRORS = {
|
||||||
|
REGULAR = {
|
||||||
|
invalid_widget_type = "[DMF Mod Options] (%s): \"%s\" is not a valid widget type " ..
|
||||||
|
"in this version of Darktide Mod Framework.",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
-- ####################################################################################################################
|
-- ####################################################################################################################
|
||||||
-- ##### Local functions ##############################################################################################
|
-- ##### Local functions ##############################################################################################
|
||||||
-- ####################################################################################################################
|
-- ####################################################################################################################
|
||||||
|
@ -53,6 +62,21 @@ local create_description_template = function (self, params)
|
||||||
end
|
end
|
||||||
_type_template_map["description"] = create_description_template
|
_type_template_map["description"] = create_description_template
|
||||||
|
|
||||||
|
-- ##########################
|
||||||
|
-- ###### Group #############
|
||||||
|
-- ##########################
|
||||||
|
|
||||||
|
-- Create group template
|
||||||
|
local create_group_template = function(self, params)
|
||||||
|
local template = {
|
||||||
|
display_name = params.title,
|
||||||
|
widget_type = "group_header",
|
||||||
|
after = params.parent_index
|
||||||
|
}
|
||||||
|
return template
|
||||||
|
end
|
||||||
|
_type_template_map["group"] = create_group_template
|
||||||
|
|
||||||
-- ###########################
|
-- ###########################
|
||||||
-- ###### Percent Slider #####
|
-- ###### Percent Slider #####
|
||||||
-- ###########################
|
-- ###########################
|
||||||
|
@ -136,6 +160,7 @@ local create_checkbox_template = function (self, params)
|
||||||
default_value = params.default_value,
|
default_value = params.default_value,
|
||||||
display_name = params.title,
|
display_name = params.title,
|
||||||
indentation_level = params.depth,
|
indentation_level = params.depth,
|
||||||
|
require_restart = params.require_restart,
|
||||||
tooltip_text = params.tooltip,
|
tooltip_text = params.tooltip,
|
||||||
value_type = "boolean",
|
value_type = "boolean",
|
||||||
}
|
}
|
||||||
|
@ -163,9 +188,11 @@ local create_mod_toggle_template = function (self, params)
|
||||||
after = params.after,
|
after = params.after,
|
||||||
category = params.category,
|
category = params.category,
|
||||||
default_value = true,
|
default_value = true,
|
||||||
display_name = dmf:localize("toggle_mod"),
|
disabled = params.disabled,
|
||||||
|
display_name = params.readable_mod_name or params.mod_name,
|
||||||
indentation_level = 0,
|
indentation_level = 0,
|
||||||
tooltip_text = dmf:localize("toggle_mod_description"),
|
require_restart = params.require_restart,
|
||||||
|
tooltip_text = params.description,
|
||||||
value_type = "boolean",
|
value_type = "boolean",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,6 +230,7 @@ local create_dropdown_template = function (self, params)
|
||||||
indentation_level = params.depth,
|
indentation_level = params.depth,
|
||||||
options = params.options,
|
options = params.options,
|
||||||
tooltip_text = params.tooltip,
|
tooltip_text = params.tooltip,
|
||||||
|
require_restart = params.require_restart,
|
||||||
widget_type = "dropdown",
|
widget_type = "dropdown",
|
||||||
}
|
}
|
||||||
template.on_activated = function(new_value)
|
template.on_activated = function(new_value)
|
||||||
|
@ -223,7 +251,9 @@ _type_template_map["dropdown"] = create_dropdown_template
|
||||||
-- ######### Keybind #########
|
-- ######### Keybind #########
|
||||||
-- ###########################
|
-- ###########################
|
||||||
|
|
||||||
local set_new_keybind = function (self, keybind_data)
|
local set_keybind = function (self, keybind_data, keywatch_result)
|
||||||
|
keybind_data.keys = keywatch_result
|
||||||
|
|
||||||
local mod = get_mod(keybind_data.mod_name)
|
local mod = get_mod(keybind_data.mod_name)
|
||||||
dmf.add_mod_keybind(
|
dmf.add_mod_keybind(
|
||||||
mod,
|
mod,
|
||||||
|
@ -232,18 +262,19 @@ local set_new_keybind = function (self, keybind_data)
|
||||||
global = keybind_data.keybind_global,
|
global = keybind_data.keybind_global,
|
||||||
trigger = keybind_data.keybind_trigger,
|
trigger = keybind_data.keybind_trigger,
|
||||||
type = keybind_data.keybind_type,
|
type = keybind_data.keybind_type,
|
||||||
keys = keybind_data.keys,
|
main = keywatch_result.main,
|
||||||
|
enablers = keywatch_result.enablers,
|
||||||
|
disablers = keywatch_result.disablers,
|
||||||
function_name = keybind_data.function_name,
|
function_name = keybind_data.function_name,
|
||||||
view_name = keybind_data.view_name,
|
view_name = keybind_data.view_name,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
mod:set(keybind_data.setting_id, keybind_data.keys, true)
|
mod:set(keybind_data.setting_id, dmf.keywatch_result_to_local_keys(keywatch_result), true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Create keybind template
|
-- Create keybind template
|
||||||
local create_keybind_template = function (self, params)
|
local create_keybind_template = function (self, params)
|
||||||
|
|
||||||
local template = {
|
local template = {
|
||||||
widget_type = "keybind",
|
widget_type = "keybind",
|
||||||
service_type = "Ingame",
|
service_type = "Ingame",
|
||||||
|
@ -259,26 +290,31 @@ local create_keybind_template = function (self, params)
|
||||||
indentation_level = params.depth,
|
indentation_level = params.depth,
|
||||||
mod_name = params.mod_name,
|
mod_name = params.mod_name,
|
||||||
setting_id = params.setting_id,
|
setting_id = params.setting_id,
|
||||||
keys = dmf.keys_to_keybind_result(params.keys),
|
keys = dmf.local_keys_to_keywatch_result(params.keys),
|
||||||
|
default_value = dmf.local_keys_to_keywatch_result(params.default_value) or {},
|
||||||
|
|
||||||
on_activated = function (new_value, old_value)
|
on_activated = function (new_value, old_value)
|
||||||
|
|
||||||
for i = 1, #_cancel_keys do
|
|
||||||
local cancel_key = _cancel_keys[i]
|
|
||||||
if cancel_key == new_value.main then
|
|
||||||
|
|
||||||
-- Prevent unbinding the mod options menu
|
-- Prevent unbinding the mod options menu
|
||||||
if params.setting_id ~= "open_dmf_options" then
|
if params.setting_id ~= "open_dmf_options" then
|
||||||
|
|
||||||
-- Unbind the keybind
|
-- Unbind the keybind if the new value is empty
|
||||||
params.keys = {}
|
if not (new_value and new_value.main) then
|
||||||
set_new_keybind(self, params)
|
set_keybind(self, params, {})
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Unbind the keybind if the new value matches a cancel key
|
||||||
|
for i = 1, #_cancel_keys do
|
||||||
|
local cancel_key = _cancel_keys[i]
|
||||||
|
if cancel_key == new_value.main then
|
||||||
|
set_keybind(self, params, {})
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Don't modify the keybind if the new value is a reserved key
|
||||||
for i = 1, #_reserved_keys do
|
for i = 1, #_reserved_keys do
|
||||||
local reserved_key = _reserved_keys[i]
|
local reserved_key = _reserved_keys[i]
|
||||||
if reserved_key == new_value.main then
|
if reserved_key == new_value.main then
|
||||||
|
@ -286,23 +322,23 @@ local create_keybind_template = function (self, params)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get the new keybind
|
-- Get the keys of the new value
|
||||||
local keys = dmf.keybind_result_to_keys(new_value)
|
local keys = dmf.keywatch_result_to_local_keys(new_value)
|
||||||
|
|
||||||
-- Bind the new key and prevent unbinding the mod options menu
|
-- Set the new keybind unless it would unbind the mod options menu
|
||||||
if keys and #keys > 0 or params.setting_id ~= "open_dmf_options" then
|
if keys and #keys > 0 or params.setting_id ~= "open_dmf_options" then
|
||||||
params.keys = keys
|
set_keybind(self, params, new_value)
|
||||||
set_new_keybind(self, params)
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return false
|
||||||
end,
|
end,
|
||||||
|
|
||||||
get_function = function (template)
|
get_function = function (template)
|
||||||
local keys = get_mod(template.mod_name):get(template.setting_id)
|
local saved_keys = get_mod(template.mod_name):get(template.setting_id)
|
||||||
local keybind_result = dmf.keys_to_keybind_result(keys)
|
local keywatch_result = dmf.local_keys_to_keywatch_result(saved_keys)
|
||||||
|
|
||||||
return keybind_result
|
return keywatch_result
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,11 +357,23 @@ local function widget_data_to_template(self, data)
|
||||||
return _type_template_map[data.type](self, data)
|
return _type_template_map[data.type](self, data)
|
||||||
else
|
else
|
||||||
dmf:dump(data, "widget", 1)
|
dmf:dump(data, "widget", 1)
|
||||||
dmf.throw_error("[widget \"%s\"]: 'type' field must contain valid widget type name.", data.setting_id)
|
dmf:error(ERRORS.REGULAR.invalid_widget_type, tostring(data.mod_name), tostring(data.type))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Add a category for toggling mods
|
||||||
|
local function create_toggle_category(self, categories)
|
||||||
|
local category = {
|
||||||
|
can_be_reset = false,
|
||||||
|
display_name = dmf:localize("toggle_mods"),
|
||||||
|
custom = true
|
||||||
|
}
|
||||||
|
categories[#categories + 1] = category
|
||||||
|
return category
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Add a mod category to the options view categories
|
-- Add a mod category to the options view categories
|
||||||
local function create_mod_category(self, categories, widget_data)
|
local function create_mod_category(self, categories, widget_data)
|
||||||
local category = {
|
local category = {
|
||||||
|
@ -350,10 +398,63 @@ local function create_option_template(self, widget_data, category_name, index_of
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Insert a new item into a table before any items that pass the item_tester function
|
||||||
|
local function insert_before(tbl, item_tester, new_item)
|
||||||
|
local copy = {}
|
||||||
|
for _, item in ipairs(tbl) do
|
||||||
|
if item_tester(item) then
|
||||||
|
table.insert(copy, new_item)
|
||||||
|
end
|
||||||
|
table.insert(copy, item)
|
||||||
|
end
|
||||||
|
return copy
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- ####################################################################################################################
|
-- ####################################################################################################################
|
||||||
-- ##### Hooks ########################################################################################################
|
-- ##### Hooks ########################################################################################################
|
||||||
-- ####################################################################################################################
|
-- ####################################################################################################################
|
||||||
|
|
||||||
|
-- Add Mods Options title to global localization table
|
||||||
|
-- so that the SystemView options menu can localize it
|
||||||
|
dmf:add_global_localize_strings({
|
||||||
|
-- TODO: copied from dmf/localization/dmf.lua, figure out a better way
|
||||||
|
mods_options = {
|
||||||
|
en = "Mod Options",
|
||||||
|
es = "Configuración de mods",
|
||||||
|
ru = "Настройки модов",
|
||||||
|
["zh-cn"] = "模组选项",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
local dmf_option_definition = {
|
||||||
|
text = "mods_options",
|
||||||
|
type = "button",
|
||||||
|
icon = "content/ui/materials/icons/system/escape/settings",
|
||||||
|
trigger_function = function()
|
||||||
|
local context = {
|
||||||
|
can_exit = true,
|
||||||
|
}
|
||||||
|
local view_name = "dmf_options_view"
|
||||||
|
Managers.ui:open_view(view_name, nil, nil, nil, nil, context)
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
local function is_options_button(item)
|
||||||
|
return item.text == "loc_options_view_display_name"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Inject DMF Options button into the Esc menu
|
||||||
|
dmf:hook_require("scripts/ui/views/system_view/system_view_content_list", function(instance)
|
||||||
|
-- Don't re-inject if it's already there
|
||||||
|
if table.find_by_key(instance.default, "text", dmf_option_definition.text) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
instance.default = insert_before(instance.default, is_options_button, dmf_option_definition)
|
||||||
|
instance.StateMainMenu = insert_before(instance.StateMainMenu, is_options_button, dmf_option_definition)
|
||||||
|
end)
|
||||||
|
|
||||||
-- ####################################################################################################################
|
-- ####################################################################################################################
|
||||||
-- ##### DMF internal functions and variables #########################################################################
|
-- ##### DMF internal functions and variables #########################################################################
|
||||||
-- ####################################################################################################################
|
-- ####################################################################################################################
|
||||||
|
@ -363,8 +464,61 @@ dmf.create_mod_options_settings = function (self, options_templates)
|
||||||
local categories = options_templates.categories
|
local categories = options_templates.categories
|
||||||
local settings = options_templates.settings
|
local settings = options_templates.settings
|
||||||
|
|
||||||
-- Create a category for every mod
|
-- Create the toggle category
|
||||||
|
local toggle_category = create_toggle_category(self, categories)
|
||||||
|
local toggle_index_offset = 0
|
||||||
|
|
||||||
|
-- Create the toggle category header
|
||||||
|
local toggle_header_data = {
|
||||||
|
type = "header",
|
||||||
|
category = toggle_category,
|
||||||
|
title = dmf:localize("toggle_mods"),
|
||||||
|
mod_name = "dmf",
|
||||||
|
tooltip = dmf:localize("toggle_mods"),
|
||||||
|
}
|
||||||
|
local toggle_header = create_option_template(self, toggle_header_data, toggle_category.display_name, toggle_index_offset)
|
||||||
|
if toggle_header then
|
||||||
|
settings[#settings + 1] = toggle_header
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create the toggle category description
|
||||||
|
local desc_widget_data = {
|
||||||
|
mod_name = "dmf",
|
||||||
|
description = dmf:localize("toggle_mods_description"),
|
||||||
|
category = toggle_category.display_name,
|
||||||
|
display_name = toggle_category.display_name,
|
||||||
|
after = #settings,
|
||||||
|
type = "description"
|
||||||
|
}
|
||||||
|
local desc_template = create_option_template(self, desc_widget_data, toggle_category.display_name, toggle_index_offset)
|
||||||
|
|
||||||
|
if desc_template then
|
||||||
|
settings[#settings + 1] = desc_template
|
||||||
|
toggle_index_offset = toggle_index_offset + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create a toggle for each mod; non-toggleable mods' toggles are disabled
|
||||||
for _, mod_data in ipairs(dmf.options_widgets_data) do
|
for _, mod_data in ipairs(dmf.options_widgets_data) do
|
||||||
|
local toggle_widget_data = {
|
||||||
|
mod_name = mod_data[1].mod_name,
|
||||||
|
readable_mod_name = mod_data[1].readable_mod_name or mod_data[1].title,
|
||||||
|
description = mod_data[1].description,
|
||||||
|
disabled = not mod_data[1].is_togglable,
|
||||||
|
category = toggle_category.display_name,
|
||||||
|
after = #settings,
|
||||||
|
type = "mod_toggle"
|
||||||
|
}
|
||||||
|
|
||||||
|
local toggle_template = create_option_template(self, toggle_widget_data, toggle_category.display_name, toggle_index_offset)
|
||||||
|
if toggle_template then
|
||||||
|
settings[#settings + 1] = toggle_template
|
||||||
|
toggle_index_offset = toggle_index_offset + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create a category for every mod that has additional settings
|
||||||
|
for _, mod_data in ipairs(dmf.options_widgets_data) do
|
||||||
|
if #mod_data > 1 then
|
||||||
local category = create_mod_category(self, categories, mod_data[1])
|
local category = create_mod_category(self, categories, mod_data[1])
|
||||||
|
|
||||||
local index_offset = 0
|
local index_offset = 0
|
||||||
|
@ -393,22 +547,6 @@ dmf.create_mod_options_settings = function (self, options_templates)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Create a top-level toggle option if the mod is togglable
|
|
||||||
if mod_data[1].is_togglable then
|
|
||||||
local toggle_widget_data = {
|
|
||||||
mod_name = mod_data[1].mod_name,
|
|
||||||
category = category.display_name,
|
|
||||||
after = #settings,
|
|
||||||
type = "mod_toggle"
|
|
||||||
}
|
|
||||||
|
|
||||||
local toggle_template = create_option_template(self, toggle_widget_data, category.display_name, index_offset)
|
|
||||||
if toggle_template then
|
|
||||||
settings[#settings + 1] = toggle_template
|
|
||||||
index_offset = index_offset + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Populate the category with options taken from the remaining options data
|
-- Populate the category with options taken from the remaining options data
|
||||||
for i = 2, #mod_data do
|
for i = 2, #mod_data do
|
||||||
local widget_data = mod_data[i]
|
local widget_data = mod_data[i]
|
||||||
|
@ -423,6 +561,7 @@ dmf.create_mod_options_settings = function (self, options_templates)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return options_templates
|
return options_templates
|
||||||
end
|
end
|
||||||
|
|
0
docs/.nojekyll
Normal file
0
docs/.nojekyll
Normal file
1
docs/CNAME
Normal file
1
docs/CNAME
Normal file
|
@ -0,0 +1 @@
|
||||||
|
dmf-docs.darkti.de
|
48
docs/index.html
Normal file
48
docs/index.html
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>DMF Docs</title>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content="The Darktide Mod Framework is an open-source, community-run framework of modules that provides enhanced modding capabilities and support."
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1.0, minimum-scale=1.0"
|
||||||
|
/>
|
||||||
|
<link rel="stylesheet" media="(prefers-color-scheme: light)" href="https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/css/theme-simple.css">
|
||||||
|
<link rel="stylesheet" media="(prefers-color-scheme: dark)" href="https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/css/theme-simple-dark.css">
|
||||||
|
<style>
|
||||||
|
h1.app-name {
|
||||||
|
font-weight: 900;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-family: system-ui, "Helvetica Neue", Arial, sans-serif;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script>
|
||||||
|
const repo = "Darktide-Mod-Framework/Darktide-Mod-Framework";
|
||||||
|
window.$docsify = {
|
||||||
|
name: "Darktide Mod Framework",
|
||||||
|
repo,
|
||||||
|
basePath: `https://raw.githubusercontent.com/wiki/${repo}/`,
|
||||||
|
coverpage: false,
|
||||||
|
alias: {
|
||||||
|
"/.*/_sidebar.md": "/_sidebar.md",
|
||||||
|
},
|
||||||
|
loadSidebar: true,
|
||||||
|
auto2top: true,
|
||||||
|
search: "auto",
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<!-- Docsify v4 -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/docsify@4"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/js/docsify-themeable.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-lua.min.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
2024
docs/package-lock.json
generated
Normal file
2024
docs/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
10
docs/package.json
Normal file
10
docs/package.json
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"name": "dmf-docs",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"start": "docsify serve ."
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"docsify-cli": "^4.4.4"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue