init.lua 68 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605
  1. local S = minetest.get_translator("advtrains_livery_designer")
  2. ----------------------------------------------------------------------------------------
  3. local function get_materials_minetest_game()
  4. return {
  5. base_game = "Minetest Game",
  6. bronze_ingot = "default:bronze_ingot",
  7. diamond = "default:diamond",
  8. dye_blue = "dye:blue",
  9. dye_green = "dye:green",
  10. dye_red = "dye:red",
  11. glass = "default:glass",
  12. gold_ingot = "default:gold_ingot",
  13. mese = "default:mese",
  14. obsidian_glass = "default:obsidian_glass",
  15. }
  16. end
  17. local function get_materials_mineclonia()
  18. return {
  19. base_game = "Mineclonia",
  20. bronze_ingot = "mcl_core:gold_ingot", -- bronze is not available
  21. diamond = "mcl_core:diamond",
  22. dye_blue = "mcl_dyes:blue",
  23. dye_green = "mcl_dyes:green",
  24. dye_red = "mcl_dyes:red",
  25. glass = "mcl_core:glass",
  26. gold_ingot = "mcl_core:gold_ingot",
  27. mese = minetest.get_modpath("mesecons_torch") and "mesecons_torch:redstoneblock" or "mcl_core:lapisblock",
  28. obsidian_glass = "mcl_core:glass_black", -- obsidian glass is not available
  29. }
  30. end
  31. local function get_materials_voxelibre()
  32. return {
  33. base_game = "VoxeLibre/MineClone2",
  34. bronze_ingot = "mcl_core:gold_ingot", -- bronze is not available
  35. diamond = "mcl_core:diamond",
  36. dye_blue = "mcl_dye:blue",
  37. dye_green = "mcl_dye:green",
  38. dye_red = "mcl_dye:red",
  39. glass = "mcl_core:glass",
  40. gold_ingot = "mcl_core:gold_ingot",
  41. mese = minetest.get_modpath("mesecons_torch") and "mesecons_torch:redstoneblock" or "mcl_core:lapisblock",
  42. obsidian_glass = "mcl_core:glass_black", -- obsidian glass is not available
  43. }
  44. end
  45. local function get_materials_farlands_reloaded()
  46. return {
  47. base_game = "Farlands Reloaded",
  48. bronze_ingot = "fl_ores:bronze_ingot",
  49. diamond = "fl_ores:diamond_ore",
  50. dye_blue = "fl_dyes:blue_dye",
  51. dye_green = "fl_dyes:green_dye",
  52. dye_red = "fl_dyes:red_dye",
  53. glass = "fl_glass:framed_glass",
  54. gold_ingot = "fl_ores:gold_ingot",
  55. mese = "fl_ores:bronze_ingot",
  56. obsidian_glass = "fl_ores:bronze_ingot", -- obsidian is not yet available, use an alternate for now.
  57. }
  58. end
  59. local function get_materials_hades_revisited()
  60. return {
  61. base_game = "Hades Revisited",
  62. bronze_ingot = "hades_core:bronze_ingot",
  63. diamond = "hades_core:diamond",
  64. dye_blue = "hades_dye:blue",
  65. dye_green = "hades_dye:green",
  66. dye_red = "hades_dye:red",
  67. glass = "hades_core:glass",
  68. gold_ingot = "hades_core:gold_ingot",
  69. mese = "hades_core:mese",
  70. obsidian_glass = "hades_core:obsidian_glass",
  71. }
  72. end
  73. local function get_materials()
  74. if minetest.get_modpath("default") and minetest.get_modpath("dye") then
  75. return get_materials_minetest_game()
  76. end
  77. if minetest.get_modpath("mcl_core") and minetest.get_modpath("mcl_dyes") then
  78. return get_materials_mineclonia()
  79. end
  80. if minetest.get_modpath("mcl_core") and minetest.get_modpath("mcl_dye") then
  81. return get_materials_voxelibre()
  82. end
  83. if minetest.get_modpath("fl_dyes") and minetest.get_modpath("fl_glass") and minetest.get_modpath("fl_ores") then
  84. return get_materials_farlands_reloaded()
  85. end
  86. if minetest.get_modpath("hades_core") and minetest.get_modpath("hades_dye") then
  87. return get_materials_hades_revisited()
  88. end
  89. return nil
  90. end
  91. local materials = get_materials()
  92. ----------------------------------------------------------------------------------------
  93. local callback_functions = {}
  94. local livery_designer_tool = "advtrains_livery_designer:livery_designer"
  95. local livery_designer_form = "advtrains_livery_designer:livery_designer_form"
  96. local max_visible_overlay_controls = 5
  97. local overlay_row_height = 0.8
  98. local overlay_list_scroll_height = overlay_row_height * max_visible_overlay_controls
  99. local overlay_list_height = 0.1 + overlay_list_scroll_height
  100. local overlay_control_height = overlay_row_height - 0.2
  101. local edit_livery_design_tooltip = "tooltip[11.25,7.0;2.0,0.8;"..S("Copies the livery design into the editor and then activates the editor.").."\n\n"..S("The existing design in the editor will be overwritten.").."]"
  102. local apply_livery_design_tooltip = "tooltip[13.375,7.0;2.0,0.8;"..S("Applies the livery design to the wagon.").."]"
  103. local undefined_str = "<"..S("Undefined")..">"
  104. local unknown_str = "<"..S("Unknown")..">"
  105. minetest.register_tool(livery_designer_tool, {
  106. description = S("Livery Designer Tool"),
  107. inventory_image = "advtrains_livery_designer_tool.png",
  108. wield_image = "advtrains_livery_designer_tool.png",
  109. stack_max = 1,
  110. })
  111. -- Only register the crafting recipe if the needed mods and their materials are available.
  112. if materials then
  113. minetest.register_craft({
  114. output = livery_designer_tool,
  115. recipe = {
  116. {materials.dye_red, materials.obsidian_glass, materials.diamond},
  117. {materials.dye_green, materials.mese, materials.gold_ingot},
  118. {materials.dye_blue, materials.glass, materials.bronze_ingot},
  119. }
  120. })
  121. end
  122. advtrains_livery_designer = {
  123. contexts = {},
  124. tool_name = livery_designer_tool,
  125. }
  126. --------------------------------------------------------------------------------------------------------
  127. function advtrains_livery_designer.get_mod_version()
  128. -- Keep mod versions in synch for now. This could change in the future.
  129. return advtrains_livery_database.get_mod_version()
  130. end
  131. -- This utility function is intended to allow dependent mods to check if the
  132. -- needed version of advtrains_livery_designer is in use. It returns true if
  133. -- the current version of advtrains_livery_designer is equal to or greater
  134. -- than the target version info.
  135. function advtrains_livery_designer.is_compatible_mod_version(target_version)
  136. local current_version = advtrains_livery_designer.get_mod_version()
  137. return advtrains_livery_database.compare_version_info(target_version, current_version)
  138. end
  139. --------------------------------------------------------------------------------------------------------
  140. local color_definitions = {
  141. {value = "#FA8072", name = S("Salmon")},
  142. {value = "#DC143C", name = S("Crimson")},
  143. {value = "#FF0000", name = S("Red")},
  144. {value = "#800000", name = S("Maroon")},
  145. {value = "#FFC0CB", name = S("Pink")},
  146. {value = "#FF1493", name = S("Deep Pink")},
  147. {value = "#FF7F50", name = S("Coral")},
  148. {value = "#FF4500", name = S("Orange Red")},
  149. {value = "#FF8C00", name = S("Dark Orange")},
  150. {value = "#FFA500", name = S("Orange")},
  151. {value = "#FFD700", name = S("Gold")},
  152. {value = "#FFFF00", name = S("Yellow")},
  153. {value = "#F0E68C", name = S("Khaki")},
  154. {value = "#DDA0DD", name = S("Plumb")},
  155. {value = "#DA70D6", name = S("Orchid")},
  156. {value = "#FF00FF", name = S("Magenta")},
  157. {value = "#8A2BE2", name = S("Blue Violet")},
  158. {value = "#800080", name = S("Purple")},
  159. {value = "#6A5ACD", name = S("Slate Blue")},
  160. {value = "#ADFF2F", name = S("Green Yellow")},
  161. {value = "#00FF00", name = S("Lime")},
  162. {value = "#2E8B57", name = S("Sea Green")},
  163. {value = "#008000", name = S("Green")},
  164. {value = "#006400", name = S("Dark Green")},
  165. {value = "#808000", name = S("Olive")},
  166. {value = "#008080", name = S("Teal")},
  167. {value = "#00FFFF", name = S("Cyan")},
  168. {value = "#40E0D0", name = S("Turquoise")},
  169. {value = "#ADD8E6", name = S("Light Blue")},
  170. {value = "#87CEEB", name = S("Sky Blue")},
  171. {value = "#4682B4", name = S("Steel Blue")},
  172. {value = "#4169E1", name = S("Royal Blue")},
  173. {value = "#0000FF", name = S("Blue")},
  174. {value = "#000080", name = S("Navy")},
  175. {value = "#F5DEB3", name = S("Wheat")},
  176. {value = "#D2B48C", name = S("Tan")},
  177. {value = "#DAA520", name = S("Goldenrod")},
  178. {value = "#D2691E", name = S("Chocolate")},
  179. {value = "#A0522D", name = S("Sienna")},
  180. {value = "#8B4513", name = S("Saddle Brown")},
  181. {value = "#A52A2A", name = S("Brown")},
  182. {value = "#FFFFFF", name = S("White")},
  183. {value = "#FFFAFA", name = S("Snow")},
  184. {value = "#F0FFFF", name = S("Azure")},
  185. {value = "#FFFFF0", name = S("Ivory")},
  186. {value = "#FAF0E6", name = S("Linen")},
  187. {value = "#F5F5DC", name = S("Beige")},
  188. {value = "#C0C0C0", name = S("Silver")},
  189. {value = "#808080", name = S("Grey")},
  190. {value = "#708090", name = S("Slate Grey")},
  191. {value = "#696969", name = S("Dim Grey")},
  192. {value = "#2F4F4F", name = S("Dark Slate Grey")},
  193. {value = "#000000", name = S("Black")},
  194. }
  195. -- Build a table for lookup of a color value by name
  196. local color_definitions_name_lookup = {}
  197. for _, color_definition in ipairs(color_definitions) do
  198. color_definitions_name_lookup[color_definition.name] = color_definition.value
  199. end
  200. local function get_color_by_name(color_name)
  201. return color_definitions_name_lookup[color_name]
  202. end
  203. -- Build a table for lookup of a color name by value
  204. local color_definitions_value_lookup = {}
  205. for _, color_definition in ipairs(color_definitions) do
  206. color_definitions_value_lookup[color_definition.value] = color_definition.name
  207. end
  208. local function get_color_name_by_value(color)
  209. return color_definitions_value_lookup[color]
  210. end
  211. -- Build a table of color override options
  212. local color_overrides = {
  213. S("None"),
  214. S("Custom"),
  215. }
  216. for _, color_definition in ipairs(color_definitions) do
  217. table.insert(color_overrides, color_definition.name)
  218. end
  219. local color_override_options = table.concat(color_overrides, ",")
  220. -- Build a table of predefined color options (for use by the color selector)
  221. local predefined_colors = {
  222. S("Custom"),
  223. }
  224. for _, color_definition in ipairs(color_definitions) do
  225. table.insert(predefined_colors, color_definition.name)
  226. end
  227. local predefined_color_options = table.concat(predefined_colors, ",")
  228. --------------------------------------------------------------------------------------------------------
  229. local function get_index(array, value)
  230. for idx, val in ipairs(array) do
  231. if val == value then
  232. return idx
  233. end
  234. end
  235. return nil
  236. end
  237. local function get_livery_name_index(array, value)
  238. for idx, val in ipairs(array) do
  239. if val.livery_name == value then
  240. return idx
  241. end
  242. end
  243. return nil
  244. end
  245. local function is_valid_wagon(wagon)
  246. return wagon and wagon.id and advtrains.wagons[wagon.id] and advtrains.wagons[wagon.id].type
  247. end
  248. --------------------------------------------------------------------------------------------------------
  249. local function get_color_from_color_components(r, g, b)
  250. return string.format("#%02X%02X%02X", r, g, b)
  251. end
  252. local function get_color_components_from_color(color)
  253. -- Skip leading "#" in color
  254. local color_components = {
  255. r = tonumber("0x"..color:sub(2, 3)),
  256. g = tonumber("0x"..color:sub(4, 5)),
  257. b = tonumber("0x"..color:sub(6, 7)),
  258. }
  259. return color_components
  260. end
  261. local function is_valid_color(color)
  262. return #color == 7 and color:match("#%x%x%x%x%x%x")
  263. end
  264. --------------------------------------------------------------------------------------------------------
  265. local function get_or_create_context(player)
  266. local name = player:get_player_name()
  267. local context = advtrains_livery_designer.contexts[name]
  268. if not context then
  269. advtrains_livery_designer.contexts[name] = {}
  270. end
  271. return context
  272. end
  273. local function set_context(player, context)
  274. advtrains_livery_designer.contexts[player:get_player_name()] = context
  275. end
  276. local function remove_context(player)
  277. advtrains_livery_designer.contexts[player:get_player_name()] = nil
  278. end
  279. minetest.register_on_joinplayer(function(player)
  280. get_or_create_context(player)
  281. end)
  282. minetest.register_on_leaveplayer(function(player)
  283. remove_context(player)
  284. end)
  285. local function play_apply_sound(wagon)
  286. minetest.sound_play("advtrains_livery_designerr_tool", {object = wagon.object, gain = 0.06, max_hear_distance = 11})
  287. end
  288. --------------------------------------------------------------------------------------------------------
  289. function advtrains_livery_designer.register_mod(mod_name, apply_wagon_livery_textures, optional_callback_functions)
  290. assert(mod_name, "Missing required mod name")
  291. assert(apply_wagon_livery_textures, "Missing required callback function")
  292. advtrains_livery_database.register_mod(mod_name, optional_callback_functions)
  293. if not callback_functions[mod_name] then
  294. callback_functions[mod_name] = {
  295. apply_wagon_livery_textures = apply_wagon_livery_textures,
  296. }
  297. end
  298. end
  299. local function update_overlay_controls(wagon_livery_template, livery_design, overlay_controls)
  300. if not wagon_livery_template or not livery_design then
  301. return
  302. end
  303. -- Clear the overlay control values but keep the control entries since they determine what is visible in the UI.
  304. for key, _ in pairs(overlay_controls) do
  305. overlay_controls[key] = nil
  306. end
  307. for id, overlay in ipairs(wagon_livery_template.overlays) do -- This will need to change if supporting resequenced overlays.
  308. local overlay_color = livery_design.overlays and livery_design.overlays[id] and livery_design.overlays[id].color or nil -- A template overlay is not required to be present in a livery_design
  309. local override_selection_idx = overlay_color and 2 or 1
  310. -- Update override_selection_idx if the overlay color matches one of the named colors
  311. if override_selection_idx == 2 then
  312. local predefined_color_name = get_color_name_by_value(overlay_color)
  313. override_selection_idx = get_index(color_overrides, predefined_color_name) or 2
  314. end
  315. overlay_controls[id] = {
  316. name = overlay.name or undefined_str,
  317. override_selection_idx = override_selection_idx,
  318. override_selection_name = color_overrides[override_selection_idx],
  319. color = livery_design.overlays[id] and livery_design.overlays[id].color,
  320. }
  321. end
  322. end
  323. local function update_color_selector_controls(color_selector_dialog)
  324. local color = color_selector_dialog.current_color
  325. local color_name = get_color_name_by_value(color)
  326. -- Update the quick select control
  327. color_selector_dialog.controls.predefined_color_selection_idx = get_index(predefined_colors, color_name) or 1
  328. -- Update the color component scrollbars
  329. local color_components = get_color_components_from_color(color)
  330. color_selector_dialog.controls.component_scrollbar_pos = {
  331. r = color_components.r,
  332. g = color_components.g,
  333. b = color_components.b,
  334. }
  335. end
  336. local function clone_control_settings(src_controls)
  337. local controls = {
  338. livery_template_name_selection = src_controls.livery_template_name_selection,
  339. overlays = {},
  340. }
  341. for id, overlay in ipairs(src_controls.overlays) do
  342. controls.overlays[id] = {
  343. name = overlay.name,
  344. override_selection_idx = overlay.override_selection_idx,
  345. override_selection_name = overlay.override_selection_name,
  346. color = overlay.color,
  347. }
  348. end
  349. return controls
  350. end
  351. local function clone_tab(src_tab)
  352. local tab = {
  353. textures = advtrains_livery_database.clone_textures(src_tab.textures),
  354. livery_design = advtrains_livery_database.clone_livery_design(src_tab.livery_design),
  355. controls = clone_control_settings(src_tab.controls),
  356. }
  357. return tab
  358. end
  359. -- This function is similar to clone_tab() but is used when copying a livery design from
  360. -- the predefined_liveries_tab which doesn't have the same controls as the other tabs. Thus,
  361. -- the target tab must be updated from the selected livery rather than have values copied
  362. -- from the source tab.
  363. local function update_tab_from_predefined_livery_design(context, target_tab)
  364. target_tab.textures = advtrains_livery_database.clone_textures(context.predefined_liveries_tab.textures)
  365. target_tab.livery_design = advtrains_livery_database.clone_livery_design(context.predefined_liveries_tab.livery_design)
  366. local wagon_livery_template = advtrains_livery_database.get_wagon_livery_template(context.wagon_type, target_tab.livery_design.livery_template_name)
  367. target_tab.controls.livery_template_name_selection = get_index(context.wagon_valid_livery_template_names, target_tab.livery_design.livery_template_name)
  368. update_overlay_controls(wagon_livery_template, target_tab.livery_design, target_tab.controls.overlays)
  369. end
  370. -- Record the current state of the override values. These values are restored to the override
  371. -- controls later when switching to a different livery template in order to view the newly
  372. -- selected template with the overrides that had been displayed.
  373. local function save_override_values(context)
  374. context.override_values = {}
  375. for seq_num, overlay in ipairs(context.livery_editor_tab.controls.overlays) do
  376. if overlay.color then
  377. context.override_values[seq_num] = overlay.color
  378. end
  379. end
  380. end
  381. local function save_override_value(context, idx, color)
  382. context.override_values[idx] = color
  383. end
  384. local function restore_override_values(context)
  385. -- Update the color overlays in the livery design
  386. if context.override_values then
  387. for idx, override_value in pairs(context.override_values) do
  388. -- Update the livery design with the specified color
  389. if not context.livery_editor_tab.livery_design.overlays[idx] then
  390. -- Only add an overlay to the livery design if the template supports it.
  391. local wagon_livery_template = advtrains_livery_database.get_wagon_livery_template(context.wagon_type, context.livery_editor_tab.livery_design.livery_template_name)
  392. if wagon_livery_template and wagon_livery_template.overlays and idx <= #wagon_livery_template.overlays then
  393. -- A color override did not previously exist in the livery design so create one
  394. context.livery_editor_tab.livery_design.overlays[idx] = {
  395. id = idx,
  396. color = override_value,
  397. }
  398. end
  399. else
  400. -- Update the existing color override value in the livery design
  401. context.livery_editor_tab.livery_design.overlays[idx].color = override_value
  402. end
  403. end
  404. end
  405. end
  406. local function update_predefined_liveries_tab_selection(context, selection_idx)
  407. context.predefined_liveries_tab.controls.livery_name_selection_idx = selection_idx
  408. context.predefined_liveries_tab.selected_livery_name = context.wagon_predefined_livery_names[selection_idx].livery_name
  409. context.predefined_liveries_tab.livery_design = advtrains_livery_database.get_predefined_livery(context.wagon_type, context.predefined_liveries_tab.selected_livery_name)
  410. context.predefined_liveries_tab.textures = advtrains_livery_database.get_livery_textures_from_design(context.predefined_liveries_tab.livery_design, context.wagon.id)
  411. end
  412. local function are_livery_templates_equivalent(livery_template_1, livery_template_2)
  413. if not livery_template_1 or
  414. not livery_template_2 or
  415. livery_template_1.overlays and not livery_template_2.overlays or
  416. not livery_template_1.overlays and livery_template_2.overlays then
  417. return false
  418. end
  419. -- Every overlay in livery template 1 should be in livery template 2 and...
  420. for id, overlay in pairs(livery_template_1.overlays) do
  421. if not livery_template_2.overlays[id] or
  422. overlay.name ~= livery_template_2.overlays[id].name then
  423. return false
  424. end
  425. end
  426. -- ...every overlay in livery template 2 should also be in livery template 1
  427. for id, overlay in pairs(livery_template_2.overlays) do
  428. if not livery_template_1.overlays[id] or
  429. overlay.name ~= livery_template_1.overlays[id].name then
  430. return false
  431. end
  432. end
  433. return true
  434. end
  435. local function get_livery_designer_context(player, wagon)
  436. -- Validate the given wagon
  437. if not is_valid_wagon(wagon) then
  438. return
  439. end
  440. local wagon_type = advtrains.wagons[wagon.id].type
  441. local wagon_mod_name = advtrains_livery_database.get_wagon_mod_name(wagon_type)
  442. if not wagon_mod_name then
  443. return
  444. end
  445. -- Validate that livery options have been registered for the given wagon.
  446. local livery_template_names = advtrains_livery_database.get_livery_template_names_for_wagon(wagon_type)
  447. if #livery_template_names < 1 then
  448. -- There is no reason to continue if there are no valid options to present to the player.
  449. return
  450. end
  451. table.sort(livery_template_names, function(a, b) return a < b end)
  452. local actual_textures = advtrains_livery_database.clone_textures(advtrains.wagon_objects[wagon.id]:get_properties().textures)
  453. local livery_design = advtrains_livery_database.get_livery_design_from_textures(wagon_type, actual_textures, wagon.id)
  454. local current_textures = livery_design and advtrains_livery_database.get_livery_textures_from_design(livery_design, wagon.id)
  455. local editor_livery_design = livery_design
  456. local editor_textures = advtrains_livery_database.clone_textures(current_textures)
  457. if not editor_livery_design then
  458. -- The current livery texture cannot be mapped to a known livery design. Initialize the editor
  459. -- with a default design for for given wagon type so that the user can optionally replace the
  460. -- unknown livery with a known one.
  461. editor_livery_design = {
  462. wagon_type = wagon_type,
  463. livery_template_name = livery_template_names[1],
  464. overlays = {},
  465. }
  466. editor_textures = advtrains_livery_database.get_livery_textures_from_design(editor_livery_design, wagon.id)
  467. end
  468. -- Initialize predefined livery name options
  469. local predefined_livery_names = advtrains_livery_database.get_predefined_livery_names(wagon_type)
  470. table.sort(predefined_livery_names, function(a, b) return a.livery_name < b.livery_name end)
  471. local predefined_livery_options = {}
  472. for _, predefined_livery_name in ipairs(predefined_livery_names) do
  473. table.insert(predefined_livery_options, minetest.formspec_escape(predefined_livery_name.livery_name))
  474. end
  475. local context = {
  476. current_tab = 2,
  477. -- This is information about the selected wagon. It does not change while the livery tool is active.
  478. wagon = wagon,
  479. wagon_type = wagon_type,
  480. wagon_model = wagon.mesh,
  481. wagon_mod_name = wagon_mod_name,
  482. wagon_valid_livery_template_names = livery_template_names,
  483. wagon_livery_options = table.concat(livery_template_names, ","),
  484. wagon_predefined_livery_names = predefined_livery_names,
  485. wagon_predefined_livery_options = table.concat(predefined_livery_options, ","),
  486. -- These controls on the current/edit/saved livery tabs share a common state.
  487. common_controls = {
  488. overlay_scrollbar_pos = 0,
  489. rotate_checkbox = true,
  490. },
  491. -- The following is a cache of override values that is used to preserve them when
  492. -- switching between liveries. They are sequence based, not related to overlay names.
  493. -- The cache is not part of livery_editor_tab since it is not to be included when
  494. -- cloning tabs.
  495. override_values = {},
  496. -- This is a snapshot of the selected wagon's design. It is only updated when the user applies
  497. -- a livery design to the wagon. It should otherwise not be updated or edited.
  498. current_livery_tab = {
  499. textures = current_textures,
  500. livery_design = advtrains_livery_database.clone_livery_design(livery_design),
  501. controls = {
  502. livery_template_name_selection = livery_design and get_index(livery_template_names, livery_design.livery_template_name) or 1,
  503. overlays = {},
  504. },
  505. },
  506. -- This is the livery design currently being edited. It can be updated by the user making edits
  507. -- or when the user copies a livry design to the editer from a different tab.
  508. livery_editor_tab = {
  509. textures = editor_textures,
  510. livery_design = advtrains_livery_database.clone_livery_design(editor_livery_design),
  511. controls = {
  512. livery_template_name_selection = editor_livery_design and get_index(livery_template_names, editor_livery_design.livery_template_name) or 1,
  513. overlays = {},
  514. },
  515. },
  516. predefined_liveries_tab = {
  517. livery_names = advtrains_livery_database.get_predefined_livery_names(wagon_type),
  518. controls = {
  519. livery_name_selection_idx = 1,
  520. }
  521. },
  522. -- This is the color picker control. It needs to be initialized with a color and the id of the
  523. -- button that initiated it. It will then update the color override for the applicable override
  524. -- when the user selects the "OK" button.
  525. color_selector_dialog = {
  526. is_active = false,
  527. color_button_idx = 0, -- 0 is an invalid id. A value of 0 indicates that the dialog has not been initialized.
  528. current_color = "#404040",
  529. controls = {
  530. predefined_color_selection_idx = 1,
  531. component_scrollbar_pos = {r = 500, g = 500, b = 500},
  532. },
  533. },
  534. -- This is the model preview control which is used to display an enlarged preview of the model.
  535. model_preview_dialog = {
  536. is_active = false,
  537. textures = {},
  538. },
  539. -- This is the livery template info dialog which is used to display some additional info about a template.
  540. livery_template_info_dialog = {
  541. is_active = false,
  542. livery_template_name = nil,
  543. textures = {},
  544. },
  545. applied = true, -- The current livery is is prepopulated into the livery editor so consider it to be "applied".
  546. }
  547. -- Update context.current_livery_tab.controls and context.livery_editor_tab.controls with overlay information.
  548. local wagon_livery_template = livery_design and advtrains_livery_database.get_wagon_livery_template(wagon_type, livery_design.livery_template_name)
  549. update_overlay_controls(wagon_livery_template, livery_design, context.current_livery_tab.controls.overlays)
  550. local editor_livery_template = editor_livery_design and advtrains_livery_database.get_wagon_livery_template(wagon_type, editor_livery_design.livery_template_name)
  551. update_overlay_controls(editor_livery_template, editor_livery_design, context.livery_editor_tab.controls.overlays)
  552. -- Initialize override_values
  553. save_override_values(context)
  554. -- Restore the relevant values from the previous invocation of the tool, if they exist.
  555. local previous_context = get_or_create_context(player)
  556. if previous_context.common_controls then
  557. -- Get the rotation checkbox from the previous session
  558. context.common_controls.rotate_checkbox = previous_context.common_controls.rotate_checkbox
  559. end
  560. if previous_context.current_tab then
  561. -- Get the tab that was last active
  562. context.current_tab = previous_context.current_tab
  563. end
  564. if previous_context.saved_livery_tab and previous_context.saved_livery_tab.textures and previous_context.saved_livery_tab.livery_design then
  565. if context.wagon_type == previous_context.wagon_type then
  566. -- Get the saved livery
  567. context.saved_livery_tab = clone_tab(previous_context.saved_livery_tab)
  568. else
  569. -- If the previous_context's save livery tab is not empty and its livery design's
  570. -- template name exists for the current wagon type and the templates for the
  571. -- previous and curent wagon types are equivalent then convert the previous
  572. -- context's save tab into one that is valid for the new context.
  573. local previous_livery_template_name = previous_context.saved_livery_tab.livery_design.livery_template_name
  574. if previous_livery_template_name then
  575. local previous_livery_template = advtrains_livery_database.get_wagon_livery_template(previous_context.wagon_type, previous_livery_template_name)
  576. if previous_livery_template then
  577. -- Determine if the template name is valid for the current wagon type
  578. local current_livery_template = advtrains_livery_database.get_wagon_livery_template(context.wagon_type, previous_livery_template_name)
  579. if current_livery_template and are_livery_templates_equivalent(current_livery_template, previous_livery_template) then
  580. -- Now that equivalent livery templates are confirmed to exist
  581. -- for both the current and previous wagon types, copy the
  582. -- previously saved livery design tab to the current context
  583. -- and adjust it as needed for the current wagon type.
  584. context.saved_livery_tab = clone_tab(previous_context.saved_livery_tab)
  585. context.saved_livery_tab.livery_design.wagon_type = context.wagon_type
  586. context.saved_livery_tab.textures = advtrains_livery_database.get_livery_textures_from_design(context.saved_livery_tab.livery_design, context.wagon.id)
  587. context.saved_livery_tab.controls.livery_template_name_selection = get_index(context.wagon_valid_livery_template_names, context.saved_livery_tab.livery_design.livery_template_name) or 1
  588. end
  589. end
  590. end
  591. end
  592. end
  593. if previous_context.predefined_liveries_tab then
  594. if context.wagon_type == previous_context.wagon_type then
  595. -- Get the selected predefined livery selection from the previous session
  596. context.predefined_liveries_tab.controls.livery_name_selection_idx = previous_context.predefined_liveries_tab.controls.livery_name_selection_idx
  597. elseif previous_context.predefined_liveries_tab.selected_livery_name then
  598. -- Since the wagon types are different, try to find the same predefined livery
  599. -- name for the current wagon type that was selected for the previous wagon type.
  600. -- They could be at different index postions for their respective wagon types
  601. -- since each wagon type can have a different set of predefined liveries.
  602. local livery_name_selection_idx = get_livery_name_index(context.wagon_predefined_livery_names, previous_context.predefined_liveries_tab.selected_livery_name)
  603. if livery_name_selection_idx then
  604. context.predefined_liveries_tab.controls.livery_name_selection_idx = livery_name_selection_idx
  605. end
  606. end
  607. end
  608. if previous_context.color_selector_dialog and previous_context.color_selector_dialog.saved_color then
  609. -- Get saved color from previous session of the color selector dialog
  610. context.color_selector_dialog.saved_color = previous_context.color_selector_dialog.saved_color
  611. end
  612. if context.wagon_predefined_livery_names and #context.wagon_predefined_livery_names > 0 then
  613. update_predefined_liveries_tab_selection(context, context.predefined_liveries_tab.controls.livery_name_selection_idx)
  614. else
  615. -- There are no predefined liveries for the wagon type
  616. context.predefined_liveries_tab.selected_livery_name = nil
  617. context.predefined_liveries_tab.textures = nil
  618. context.predefined_liveries_tab.livery_design = nil
  619. context.predefined_liveries_tab.controls.livery_name_selection_idx = 0
  620. end
  621. return context
  622. end
  623. local function get_model_preview_formspec(context, wagon_textures, show_rotate_checkbox)
  624. local formspec = ""
  625. if context.wagon_model and wagon_textures and #wagon_textures > 0 then
  626. local textures = table.concat(wagon_textures, ",")
  627. local rotate_model = false
  628. if show_rotate_checkbox then
  629. rotate_model = context.common_controls.rotate_checkbox
  630. end
  631. formspec = formspec..
  632. "container[11.25,1.5]"..
  633. "box[0,0;6.25,5;#ffffff09]"..
  634. "model[0,0;6.25,5;WagonModelPreview;"..context.wagon_model..";"..textures..";-15,45;"..tostring(rotate_model)..";true;0,0]"
  635. if show_rotate_checkbox then
  636. formspec = formspec..
  637. "checkbox[0.1,4.75;RotationCheckbox;"..S("Rotate")..";"..tostring(rotate_model).."]"
  638. end
  639. formspec = formspec..
  640. "button[5.75,4.5;0.4,0.4;ExpandPreviewButton;<>]"..
  641. "tooltip[5.75,4.5;0.4,0.4;"..S("Expands the livery preview.").."]"..
  642. "container_end[]"
  643. end
  644. return formspec
  645. end
  646. local function get_model_preview_formspec_section(context)
  647. local formspec = ""
  648. if context.wagon_model and context.model_preview_dialog.textures and context.model_preview_dialog.textures[1] then
  649. local rotate_model = context.common_controls.rotate_checkbox
  650. local textures = table.concat(context.model_preview_dialog.textures, ",")
  651. formspec = formspec..
  652. "container[0.25,0.25]"..
  653. "box[0,0;19.5,15.5;#ffffff09]"..
  654. "model[0,0;19.5,15.5;WagonModelPreview;"..context.wagon_model..";"..textures..";-15,45;"..tostring(rotate_model)..";true;0,0]"..
  655. "checkbox[0.1,15.25;RotationCheckbox;"..S("Rotate")..";"..tostring(rotate_model).."]"..
  656. "button[19.0,15.0;0.4,0.4;CollapsePreviewButton;><]"..
  657. "tooltip[19.0,15.0;0.4,0.4;"..S("Collapses the livery preview.").."]"..
  658. "container_end[]"
  659. end
  660. return formspec
  661. end
  662. local function get_livery_template_info_formspec_section(context)
  663. local formspec = ""
  664. if context.wagon_type and context.wagon_model and context.livery_template_info_dialog.livery_template_name then
  665. local livery_template = advtrains_livery_database.get_wagon_livery_template(context.wagon_type, context.livery_template_info_dialog.livery_template_name)
  666. formspec = formspec..
  667. "container[0.1,0.1]"..
  668. "box[0,0;13.8,0.5;#555555ff]"..
  669. "label[5.0,0.275;"..S("Livery Template Information").."]"..
  670. "container_end[]"..
  671. "container[0.25,1.00]"..
  672. "container[0.0,0.25]"..
  673. "label[0.00,0.000;"..S("Livery Template")..":]"..
  674. "label[0.30,0.575;"..context.livery_template_info_dialog.livery_template_name.."]"..
  675. "container_end[]"..
  676. "container[0.0,1.5]"..
  677. "label[0.00,0.000;"..S("Source Mod")..":]"..
  678. "label[0.30,0.575;"..(livery_template.livery_mod or "").."]"..
  679. "container_end[]"..
  680. "container[0.0,2.75]"..
  681. "label[0.00,0.000;"..S("Template Designer")..":]"..
  682. "label[0.30,0.575;"..(livery_template.designer or "").."]"..
  683. "container_end[]"..
  684. "container[0.0,4.00]"..
  685. "label[0.00,0.000;"..S("Base Texture Filename")..":]"..
  686. "label[0.30,0.575;"..(livery_template.base_textures[1] or "").."]"..
  687. "container_end[]"..
  688. "container[0.0,5.25]"..
  689. "label[0.00,0.000;"..S("Texture Creator")..":]"..
  690. "label[0.30,0.575;"..(livery_template.texture_creator or "").."]"..
  691. "container_end[]"..
  692. "container[0.0,6.5]"..
  693. "label[0.00,0.000;"..S("Texture License")..":]"..
  694. "label[0.30,0.575;"..(livery_template.texture_license or "").."]"..
  695. "container_end[]"..
  696. "container[0.0,7.75]"..
  697. "label[0.00,0.000;"..S("Notes")..":]"..
  698. "textarea[0.30,0.275;13.0,1.0;;;"..(livery_template.notes or "").."]"..
  699. "container_end[]"..
  700. "button[11.4,9.25;2.0,0.8;CloseLiveryTemplateInfoDialogButton;OK]"..
  701. "container_end[]"
  702. end
  703. return formspec
  704. end
  705. local function get_current_livery_formspec_section(context)
  706. local current_livery_design = context.current_livery_tab.livery_design
  707. local current_livery_template_name = current_livery_design and current_livery_design.livery_template_name or unknown_str
  708. local formspec =
  709. "container[0.25,1.0]"..
  710. "label[0,0.25;"..S("Livery Template")..":]"..
  711. "label[0.30,0.825;"..current_livery_template_name.."]"
  712. if current_livery_design then
  713. formspec = formspec..
  714. "label[0,1.45;"..S("Color Overrides")..":]"..
  715. "container[0.25,1.65]"..
  716. "box[0,0;10.5,"..overlay_list_height..";#ffffff09]"
  717. local overlay_count = #context.current_livery_tab.controls.overlays
  718. local scroll_pos = context.common_controls.overlay_scrollbar_pos
  719. local overlay_box_width = 10.4
  720. local use_overlay_scrollbar = overlay_count > max_visible_overlay_controls
  721. if use_overlay_scrollbar then
  722. overlay_box_width = overlay_box_width - .25
  723. local max_step = overlay_count - max_visible_overlay_controls
  724. formspec = formspec..
  725. "scrollbaroptions[arrows=default;thumbsize=1;max="..max_step..";min=0;smallstep=1;largestep=1]"..
  726. "scroll_container[0,0;10.5,"..overlay_list_scroll_height..";OverlayScrollbar;vertical;"..overlay_row_height.."]"
  727. end
  728. for id, overlay in ipairs(context.current_livery_tab.controls.overlays) do
  729. local overlay_name = overlay.name or undefined_str
  730. local overlay_color_override = overlay.override_selection_name or "None"
  731. local overlay_color = overlay.color
  732. formspec = formspec..
  733. "container[0,"..(0.1 + (id - 1) * overlay_row_height).."]"..
  734. "box[0.05,0.0;"..overlay_box_width..","..(overlay_row_height - 0.1)..";#ffffff09]"..
  735. "label[0.1,0.35;"..id..".]"..
  736. "label[0.6,0.35;"..overlay_name.."]"..
  737. "label[4.15,0.35;"..overlay_color_override.."]"
  738. if overlay_color then
  739. formspec = formspec..
  740. "box[8.75,0.05;"..overlay_control_height..","..overlay_control_height..";#252525ff]"..
  741. "box[8.80,0.09;"..(overlay_control_height - 0.08)..","..(overlay_control_height - 0.08)..";"..overlay_color.."]"..
  742. "tooltip[8.80,0.09;"..(overlay_control_height - 0.08)..","..(overlay_control_height - 0.08)..";"..overlay_color.."]"
  743. end
  744. formspec = formspec..
  745. "container_end[]"
  746. end
  747. if use_overlay_scrollbar then
  748. formspec = formspec..
  749. "scroll_container_end[]"..
  750. "scrollbar[10.25,0.0;.25,"..overlay_list_height..";vertical;OverlayScrollbar;"..scroll_pos.."]"
  751. end
  752. formspec = formspec..
  753. "container_end[]"
  754. end
  755. formspec = formspec..
  756. "container_end[]"..
  757. get_model_preview_formspec(context, context.current_livery_tab.textures, true)
  758. if current_livery_design then
  759. if not advtrains_livery_database.are_livery_designs_equivalent(current_livery_design, context.livery_editor_tab.livery_design) then
  760. formspec = formspec..
  761. "button[11.25,7.0;2.0,0.8;CurrentLiveryEditButton;"..S("Edit").."]"..
  762. edit_livery_design_tooltip
  763. end
  764. end
  765. return formspec
  766. end
  767. local function get_livery_editor_formspec_section(context)
  768. local livery_design = context.livery_editor_tab.livery_design
  769. local livery_template_name = livery_design and livery_design.livery_template_name or unknown_str
  770. local formspec =
  771. "container[0.25,1.0]"..
  772. "label[0,0.25;"..S("Livery Template")..":]"
  773. if livery_design then
  774. local wagon_livery_options = context.wagon_livery_options or undefined_str
  775. local livery_template_name_selection = context.livery_editor_tab.controls.livery_template_name_selection or 1
  776. formspec = formspec..
  777. "dropdown[0.27,0.52;10.5,0.6;EditorLiveryTemplateName;"..wagon_livery_options..";"..livery_template_name_selection.."]"..
  778. "label[0,1.45;"..S("Color Overrides")..":]"..
  779. "container[0.25,1.65]"..
  780. "box[0,0;10.5,"..overlay_list_height..";#ffffff09]"
  781. local overlay_count = #context.livery_editor_tab.controls.overlays
  782. local scroll_pos = context.common_controls.overlay_scrollbar_pos
  783. local overlay_box_width = 10.4
  784. local use_overlay_scrollbar = overlay_count > max_visible_overlay_controls
  785. if use_overlay_scrollbar then
  786. overlay_box_width = overlay_box_width - .25
  787. local max_step = overlay_count - max_visible_overlay_controls
  788. formspec = formspec..
  789. "scrollbaroptions[arrows=default;thumbsize=1;max="..max_step..";min=0;smallstep=1;largestep=1]"..
  790. "scroll_container[0,0;10.5,"..overlay_list_scroll_height..";OverlayScrollbar;vertical;"..overlay_row_height.."]"
  791. end
  792. local override_count = 0
  793. for id, overlay in ipairs(context.livery_editor_tab.controls.overlays) do
  794. local overlay_name = overlay.name or undefined_str
  795. local overlay_color_override = context.livery_editor_tab.controls.overlays and context.livery_editor_tab.controls.overlays[id] and context.livery_editor_tab.controls.overlays[id].override_selection_idx or 1
  796. local overlay_color = overlay.color
  797. formspec = formspec..
  798. "container[0,"..(0.1 + (id - 1) * overlay_row_height).."]"..
  799. "box[0.05,0.0;"..overlay_box_width..","..(overlay_row_height - 0.1)..";#ffffff09]"..
  800. "label[0.1,0.35;"..id..".]"..
  801. "label[0.6,0.35;"..overlay_name.."]"..
  802. "dropdown[4.12,0.05;4.5,"..overlay_control_height..";ColorOverride"..id..";"..color_override_options..";"..(overlay_color_override or 1).."]"
  803. if overlay.override_selection_idx > 1 then
  804. override_count = override_count + 1
  805. formspec = formspec..
  806. "box[8.75,0.05;"..overlay_control_height..","..overlay_control_height..";#252525ff]"..
  807. "box[8.80,0.09;"..(overlay_control_height - 0.08)..","..(overlay_control_height - 0.08)..";"..(overlay_color or "#00000000").."]"..
  808. "tooltip[8.80,0.09;"..(overlay_control_height - 0.08)..","..(overlay_control_height - 0.08)..";"..(overlay_color or "#00000000").."]"
  809. if overlay.override_selection_idx > 1 then
  810. formspec = formspec..
  811. "button[9.45,0.05;"..overlay_control_height..","..overlay_control_height..";EditColorButton"..(id)..";...]"..
  812. "tooltip[9.45,0.05;"..overlay_control_height..","..overlay_control_height..";"..S("Edit Color").."]"
  813. end
  814. end
  815. formspec = formspec..
  816. "container_end[]"
  817. end
  818. if use_overlay_scrollbar then
  819. formspec = formspec..
  820. "scroll_container_end[]"..
  821. "scrollbar[10.25,0.0;.25,"..overlay_list_height..";vertical;OverlayScrollbar;"..scroll_pos.."]"
  822. end
  823. formspec = formspec..
  824. "container_end[]"..
  825. "container_end[]"..
  826. get_model_preview_formspec(context, context.livery_editor_tab.textures, false)..
  827. "button[0.5,7.0;0.8,0.8;InfoButton;i]"..
  828. "tooltip[0.5,7.0;0.8,0.8;"..S("Displays information about the current livery template.").."]"
  829. if override_count > 0 then
  830. formspec = formspec..
  831. "button[1.425,7.0;2.0,0.8;EditorResetButton;"..S("Reset").."]"..
  832. "tooltip[1.425,7.0;2.0,0.8;"..S("Resets all color overrides to 'None'.").."]"
  833. end
  834. if not context.saved_livery_tab or not advtrains_livery_database.are_livery_designs_equivalent(context.saved_livery_tab.livery_design, context.livery_editor_tab.livery_design) then
  835. formspec = formspec..
  836. "button[11.25,7.0;2.0,0.8;EditorSaveButton;"..S("Save").."]"..
  837. "tooltip[11.25,7.0;2.0,0.8;"..S("Copies the livery design to the saved livery tab and then activates the saved livery tab.").."\n\n"..S("The currently saved livery design will be overwritten.").."]"
  838. end
  839. if not context.applied then
  840. formspec = formspec..
  841. "button[13.375,7.0;2.0,0.8;ApplyButton;"..S("Apply").."]"..
  842. apply_livery_design_tooltip
  843. end
  844. else
  845. formspec = formspec..
  846. "label[0.30,0.825;"..livery_template_name.."]"..
  847. "container_end[]"..
  848. get_model_preview_formspec(context, context.livery_editor_tab.textures, false)
  849. end
  850. return formspec
  851. end
  852. local function get_saved_livery_formspec_section(context)
  853. local formspec = "textarea[0.5,2.5;13.5,2;;;"..S("A livery for this wagon type has not been recently saved.").."]"
  854. if context.saved_livery_tab and context.saved_livery_tab.livery_design then
  855. local livery_template_name = context.saved_livery_tab.livery_design.livery_template_name or unknown_str
  856. formspec =
  857. "container[0.25,1.0]"..
  858. "label[0,0.25;"..S("Livery Template")..":]"..
  859. "label[0.30,0.825;"..livery_template_name.."]"..
  860. "label[0,1.45;"..S("Color Overrides")..":]"..
  861. "container[0.25,1.65]"..
  862. "box[0,0;10.5,"..overlay_list_height..";#ffffff09]"
  863. local overlay_count = #context.saved_livery_tab.controls.overlays
  864. local scroll_pos = context.common_controls.overlay_scrollbar_pos
  865. local overlay_box_width = 10.4
  866. local use_overlay_scrollbar = overlay_count > max_visible_overlay_controls
  867. if use_overlay_scrollbar then
  868. overlay_box_width = overlay_box_width - .25
  869. local max_step = overlay_count - max_visible_overlay_controls
  870. formspec = formspec..
  871. "scrollbaroptions[arrows=default;thumbsize=1;max="..max_step..";min=0;smallstep=1;largestep=1]"..
  872. "scroll_container[0,0;10.5,"..overlay_list_scroll_height..";OverlayScrollbar;vertical;"..overlay_row_height.."]"
  873. end
  874. for id, overlay in ipairs(context.saved_livery_tab.controls.overlays) do
  875. local overlay_name = overlay.name or undefined_str
  876. local overlay_color_override = overlay.override_selection_name or "None"
  877. local overlay_color = overlay.color
  878. formspec = formspec..
  879. "container[0,"..(0.1 + (id - 1) * overlay_row_height).."]"..
  880. "box[0.05,0.0;"..overlay_box_width..","..(overlay_row_height - 0.1)..";#ffffff09]"..
  881. "label[0.1,0.35;"..id..".]"..
  882. "label[0.6,0.35;"..overlay_name.."]"..
  883. "label[4.15,0.35;"..overlay_color_override.."]"
  884. if overlay_color then
  885. formspec = formspec..
  886. "box[8.75,0.05;"..overlay_control_height..","..overlay_control_height..";#252525ff]"..
  887. "box[8.80,0.09;"..(overlay_control_height - 0.08)..","..(overlay_control_height - 0.08)..";"..overlay_color.."]"..
  888. "tooltip[8.80,0.09;"..(overlay_control_height - 0.08)..","..(overlay_control_height - 0.08)..";"..overlay_color.."]"
  889. end
  890. formspec = formspec..
  891. "container_end[]"
  892. end
  893. if use_overlay_scrollbar then
  894. formspec = formspec..
  895. "scroll_container_end[]"..
  896. "scrollbar[10.25,0.0;.25,"..overlay_list_height..";vertical;OverlayScrollbar;"..scroll_pos.."]"
  897. end
  898. formspec = formspec..
  899. "container_end[]"..
  900. "container_end[]"..
  901. get_model_preview_formspec(context, context.saved_livery_tab.textures, true)
  902. if not advtrains_livery_database.are_livery_designs_equivalent(context.saved_livery_tab.livery_design, context.livery_editor_tab.livery_design) then
  903. formspec = formspec..
  904. "button[11.25,7.0;2.0,0.8;SavedLiveryEditButton;"..S("Edit").."]"..
  905. edit_livery_design_tooltip
  906. end
  907. if not advtrains_livery_database.are_livery_designs_equivalent(context.saved_livery_tab.livery_design, context.current_livery_tab.livery_design) then
  908. formspec = formspec..
  909. "button[13.375,7.0;2.0,0.8;SavedLiveryApplyButton;"..S("Apply").."]"..
  910. apply_livery_design_tooltip
  911. end
  912. end
  913. return formspec
  914. end
  915. local function get_predefined_liveries_formspec_section(context)
  916. local predefined_livery_count = #context.wagon_predefined_livery_names
  917. local formspec = "textarea[0.5,2.5;13.5,2;;;"..S("No predefined liveries are available for this wagon type.").."]"
  918. if predefined_livery_count > 0 then
  919. local selection_idx = context.predefined_liveries_tab.controls.livery_name_selection_idx
  920. formspec =
  921. "container[0.25,1]"..
  922. "textlist[0,0.5;10.5,5;PredefinedLiveriesTextList;"..context.wagon_predefined_livery_options..";"..selection_idx..";false]"..
  923. "container_end[]"..
  924. get_model_preview_formspec(context, context.predefined_liveries_tab.textures, false)
  925. if not advtrains_livery_database.are_livery_designs_equivalent(context.predefined_liveries_tab.livery_design, context.livery_editor_tab.livery_design) then
  926. formspec = formspec..
  927. "button[11.25,7.0;2.0,0.8;PredefinedLiveriesEditButton;"..S("Edit").."]"..
  928. edit_livery_design_tooltip
  929. end
  930. if not advtrains_livery_database.are_livery_designs_equivalent(context.predefined_liveries_tab.livery_design, context.current_livery_tab.livery_design) then
  931. formspec = formspec..
  932. "button[13.375,7.0;2.0,0.8;PredefinedLiveriesApplyButton;"..S("Apply").."]"..
  933. apply_livery_design_tooltip
  934. end
  935. end
  936. return formspec
  937. end
  938. local function get_color_selector_formspec_section(context)
  939. local color = context.color_selector_dialog.current_color or "#000000"
  940. local saved_color = context.color_selector_dialog.saved_color or "#000000"
  941. local formspec =
  942. "container[0,0]"..
  943. "box[0,0;14,7;#333333ff]"..
  944. "container[0.1,0.1]"..
  945. "box[0,0;13.8,0.5;#555555ff]"..
  946. "label[6.0,0.275;"..S("Color Selector").."]"..
  947. "container_end[]"..
  948. "container[0.4,1.0]"..
  949. "label[0.1,0.1;"..S("Preview")..":]"..
  950. "box[0.0,0.5;3.7,3.7;#0a0a0aff]"..
  951. "box[0.1,0.6;3.5,3.5;"..color.."ff]"..
  952. "tooltip[0.1,0.6;3.5,3.5;"..color.."]"..
  953. "container_end[]"..
  954. "container[4.5,0.75]"..
  955. "box[0,0;4.35,1.3;#ffffff09]"..
  956. "label[0.1,0.28;"..S("Color")..":]"..
  957. "dropdown[0.1,0.5;4.15,0.7;ColorSelectorQuickSelectDropdown;"..predefined_color_options..";"..context.color_selector_dialog.controls.predefined_color_selection_idx..";true]"..
  958. "container_end[]"..
  959. "container[9.25,0.75]"..
  960. "box[0,0;4.6,1.3;#ffffff09]"..
  961. "label[0.1,0.28;"..S("Hex Value")..":]"..
  962. "field[0.1,0.5;2.25,0.7;ColorSelectorInputColor;;"..color.."]"..
  963. "field_close_on_enter[ColorSelectorInputColor;false]"..
  964. "button[2.5,0.5;2.0,0.7;ColorSelectorUpdateButton;"..S("Update").."]"..
  965. "tooltip[2.5,0.5;2.0,0.7;"..S("Updates the current color based on the entered hex value.").."]"..
  966. "container_end[]"..
  967. "container[4.5,2.0]"..
  968. "scrollbaroptions[arrows=default;thumbsize=8;max=255;min=0;smallstep=1;largestep=32]"..
  969. "container[0,0.5]"..
  970. "label[0,0;"..S("Red")..":]"..
  971. "scrollbar[0,0.25;8.2,0.4;horizontal;ColorSelectorScrollBarR;"..context.color_selector_dialog.controls.component_scrollbar_pos.r.."]"..
  972. "label[8.3,0.47;"..context.color_selector_dialog.controls.component_scrollbar_pos.r.."]"..
  973. "container_end[]"..
  974. "container[0,1.5]"..
  975. "label[0,0;"..S("Green")..":]"..
  976. "scrollbar[0,0.25;8.2,0.4;horizontal;ColorSelectorScrollBarG;"..context.color_selector_dialog.controls.component_scrollbar_pos.g.."]"..
  977. "label[8.3,0.47;"..context.color_selector_dialog.controls.component_scrollbar_pos.g.."]"..
  978. "container_end[]"..
  979. "container[0,2.5]"..
  980. "label[0,0;"..S("Blue")..":]"..
  981. "scrollbar[0,0.25;8.2,0.4;horizontal;ColorSelectorScrollBarB;"..context.color_selector_dialog.controls.component_scrollbar_pos.b.."]"..
  982. "label[8.3,0.47;"..context.color_selector_dialog.controls.component_scrollbar_pos.b.."]"..
  983. "container_end[]"..
  984. "container_end[]"..
  985. "container[0.3,5.5]"..
  986. "box[0,0;5.1,1.3;#ffffff09]"..
  987. "label[0.1,0.25;"..S("Saved Color")..":]"..
  988. "box[0.1,0.5;0.7,0.7;#0a0a0aff]"..
  989. "box[0.2,0.6;0.5,0.5;"..saved_color.."ff]"..
  990. "tooltip[0.2,0.6;0.5,0.5;"..saved_color.."]"..
  991. "button[0.9,0.5;2.0,0.7;ColorSelectorSaveColorButton;"..S("Update").."]"..
  992. "tooltip[0.9,0.5;2.0,0.7;"..S("Updates the saved color to match the current color.").."]"..
  993. "button[3.0,0.5;2.0,0.7;ColorSelectorRecallButton;"..S("Recall").."]"..
  994. "tooltip[3.0,0.5;2.0,0.7;"..S("Updates the current color to match the saved color.").."]"..
  995. "container_end[]"..
  996. "button[8.25,6;2.5,0.8;ColorSelectorOkButton;"..S("OK").."]"..
  997. "button[11.0,6;2.5,0.8;ColorSelectorCancelButton;"..S("Cancel").."]"..
  998. "container_end[]"
  999. return formspec
  1000. end
  1001. local function get_formspec(player, context)
  1002. local tab_names = S("Current Livery")..", "..S("Editor")..", "..S("Saved Livery")..", "..S("Predefined Liveries")
  1003. local wagon_type = context.wagon_type and context.wagon_type or undefined_str
  1004. local formspec =
  1005. "formspec_version[4]"
  1006. if context.model_preview_dialog.is_active then
  1007. formspec = formspec..
  1008. "size[20,16]"..
  1009. "position[0.5,0.5]"..
  1010. get_model_preview_formspec_section(context)
  1011. elseif context.livery_template_info_dialog.is_active then
  1012. formspec = formspec..
  1013. "size[14,11.25]"..
  1014. "position[0.5,0.5]"..
  1015. get_livery_template_info_formspec_section(context)
  1016. elseif context.color_selector_dialog.is_active then
  1017. formspec = formspec..
  1018. "size[14,7]"..
  1019. "position[0.5,0.5]"..
  1020. get_color_selector_formspec_section(context)
  1021. else
  1022. formspec = formspec..
  1023. "size[18,8]"..
  1024. "position[0.5,0.5]"..
  1025. "tabheader[0,0;CurrentTab;"..tab_names..";"..context.current_tab.."]"..
  1026. "container[0.1,0.1]"..
  1027. "box[0.00,0.00;17.80,0.80;#ffffff09]"..
  1028. "label[0.15,0.38;"..(minetest.registered_items[wagon_type].description or wagon_type or "<"..S("Unknown Wagon")..">").."]"..
  1029. "container_end[]"
  1030. if context.current_tab == 1 then
  1031. formspec = formspec..get_current_livery_formspec_section(context)
  1032. elseif context.current_tab == 2 then
  1033. formspec = formspec..get_livery_editor_formspec_section(context)
  1034. elseif context.current_tab == 3 then
  1035. formspec = formspec..get_saved_livery_formspec_section(context)
  1036. elseif context.current_tab == 4 then
  1037. formspec = formspec..get_predefined_liveries_formspec_section(context)
  1038. end
  1039. formspec = formspec..
  1040. "button_exit[15.5,7.0;2.0,0.8;exit_button;"..S("Exit").."]"
  1041. end
  1042. return formspec
  1043. end
  1044. local function show_livery_designer_form(player, wagon)
  1045. local context = get_livery_designer_context(player, wagon)
  1046. if context then
  1047. set_context(player, context)
  1048. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1049. else
  1050. -- This is an unsupported wagon type or no livery templates have been registered for the wagon type.
  1051. minetest.chat_send_player(player:get_player_name(), S("No livery templates are defined for the wagon."))
  1052. end
  1053. end
  1054. local function get_indexed_selection(base_name, max_idx, fields)
  1055. if not base_name or not max_idx or max_idx < 1 or not fields then
  1056. return
  1057. end
  1058. local len = #base_name
  1059. for key, val in pairs(fields) do
  1060. if key:sub(1, len) == base_name then
  1061. for i = 1, max_idx do
  1062. if key == base_name..i then
  1063. return i, val
  1064. end
  1065. end
  1066. end
  1067. end
  1068. end
  1069. minetest.register_on_player_receive_fields(function(player, formname, fields)
  1070. if formname == livery_designer_form then
  1071. local itemstack = player:get_wielded_item()
  1072. if itemstack:get_name() ~= livery_designer_tool then
  1073. minetest.debug("ERROR: Not wielding the correct livery tool.")
  1074. return
  1075. end
  1076. local context = get_or_create_context(player)
  1077. if fields.quit then
  1078. set_context(player, context)
  1079. return
  1080. end
  1081. if context.model_preview_dialog.is_active then
  1082. if fields.RotationCheckbox then
  1083. context.common_controls.rotate_checkbox = fields.RotationCheckbox == "true"
  1084. set_context(player, context)
  1085. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1086. return
  1087. end
  1088. if fields.CollapsePreviewButton then
  1089. context.model_preview_dialog.is_active = false
  1090. context.model_preview_dialog.textures = {}
  1091. set_context(player, context)
  1092. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1093. return
  1094. end
  1095. end
  1096. if context.livery_template_info_dialog.is_active then
  1097. if fields.CloseLiveryTemplateInfoDialogButton then
  1098. context.livery_template_info_dialog.is_active = false
  1099. context.livery_template_info_dialog.livery_template_name = nil
  1100. context.livery_template_info_dialog.textures = {}
  1101. set_context(player, context)
  1102. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1103. return
  1104. end
  1105. end
  1106. if context.color_selector_dialog.is_active then
  1107. if fields.ColorSelectorCancelButton or fields.ColorSelectorOkButton then
  1108. if context.color_selector_dialog.color_button_idx and fields.ColorSelectorOkButton then
  1109. local override_idx = context.color_selector_dialog.color_button_idx
  1110. -- Update the livery design
  1111. context.livery_editor_tab.livery_design.overlays[override_idx].color = context.color_selector_dialog.current_color
  1112. -- Update context.livery_editor_tab.textures
  1113. context.livery_editor_tab.textures = advtrains_livery_database.get_livery_textures_from_design(context.livery_editor_tab.livery_design, context.wagon.id)
  1114. -- Update context.livery_editor_tab.controls to match the updated livery design
  1115. local wagon_livery_template = advtrains_livery_database.get_wagon_livery_template(context.wagon_type, context.livery_editor_tab.livery_design.livery_template_name)
  1116. update_overlay_controls(wagon_livery_template, context.livery_editor_tab.livery_design, context.livery_editor_tab.controls.overlays)
  1117. -- Update the applicable context.override_values[] to the updated value
  1118. save_override_value(context, override_idx, context.livery_editor_tab.livery_design.overlays[override_idx].color)
  1119. context.applied = advtrains_livery_database.are_livery_designs_equivalent(context.current_livery_tab.livery_design, context.livery_editor_tab.livery_design)
  1120. end
  1121. context.color_selector_dialog.is_active = false
  1122. set_context(player, context)
  1123. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1124. return
  1125. end
  1126. if fields.ColorSelectorSaveColorButton and context.color_selector_dialog.saved_color ~= context.color_selector_dialog.current_color then
  1127. context.color_selector_dialog.saved_color = context.color_selector_dialog.current_color
  1128. update_color_selector_controls(context.color_selector_dialog)
  1129. set_context(player, context)
  1130. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1131. return
  1132. end
  1133. if fields.ColorSelectorRecallButton and context.color_selector_dialog.current_color ~= context.color_selector_dialog.saved_color then
  1134. context.color_selector_dialog.current_color = context.color_selector_dialog.saved_color
  1135. update_color_selector_controls(context.color_selector_dialog)
  1136. set_context(player, context)
  1137. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1138. return
  1139. end
  1140. if fields.ColorSelectorUpdateButton and is_valid_color(fields.ColorSelectorInputColor) then
  1141. context.color_selector_dialog.current_color = fields.ColorSelectorInputColor
  1142. update_color_selector_controls(context.color_selector_dialog)
  1143. set_context(player, context)
  1144. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1145. return
  1146. end
  1147. local scrollbar_changed = false
  1148. if fields.ColorSelectorScrollBarR and fields.ColorSelectorScrollBarR:sub(1, 3) == "CHG" then
  1149. context.color_selector_dialog.controls.component_scrollbar_pos.r = tonumber(fields.ColorSelectorScrollBarR:sub(5, 8))
  1150. scrollbar_changed = true
  1151. elseif fields.ColorSelectorScrollBarG and fields.ColorSelectorScrollBarG:sub(1, 3) == "CHG" then
  1152. context.color_selector_dialog.controls.component_scrollbar_pos.g = tonumber(fields.ColorSelectorScrollBarG:sub(5, 8))
  1153. scrollbar_changed = true
  1154. elseif fields.ColorSelectorScrollBarB and fields.ColorSelectorScrollBarB:sub(1, 3) == "CHG" then
  1155. context.color_selector_dialog.controls.component_scrollbar_pos.b = tonumber(fields.ColorSelectorScrollBarB:sub(5, 8))
  1156. scrollbar_changed = true
  1157. end
  1158. if scrollbar_changed then
  1159. context.color_selector_dialog.current_color = get_color_from_color_components(
  1160. context.color_selector_dialog.controls.component_scrollbar_pos.r,
  1161. context.color_selector_dialog.controls.component_scrollbar_pos.g,
  1162. context.color_selector_dialog.controls.component_scrollbar_pos.b)
  1163. context.color_selector_dialog.controls.predefined_color_selection_idx = get_index(predefined_colors, get_color_name_by_value(context.color_selector_dialog.current_color)) or 1
  1164. elseif fields.ColorSelectorQuickSelectDropdown ~= context.color_selector_dialog.controls.predefined_color_selection_idx then
  1165. local selection_idx = tonumber(fields.ColorSelectorQuickSelectDropdown)
  1166. if selection_idx > 1 then
  1167. context.color_selector_dialog.current_color = get_color_by_name(predefined_colors[selection_idx])
  1168. update_color_selector_controls(context.color_selector_dialog)
  1169. end
  1170. end
  1171. set_context(player, context)
  1172. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1173. return
  1174. end
  1175. if fields.OverlayScrollbar and fields.OverlayScrollbar:sub(1, 3) == "CHG" then
  1176. context.common_controls.overlay_scrollbar_pos = tonumber(fields.OverlayScrollbar:sub(5, 8))
  1177. return
  1178. end
  1179. if fields.ExpandPreviewButton then
  1180. context.model_preview_dialog.is_active = true
  1181. if context.current_tab == 1 then
  1182. context.model_preview_dialog.textures = context.current_livery_tab.textures
  1183. elseif context.current_tab == 2 then
  1184. context.model_preview_dialog.textures = context.livery_editor_tab.textures
  1185. elseif context.current_tab == 3 then
  1186. context.model_preview_dialog.textures = context.saved_livery_tab.textures
  1187. elseif context.current_tab == 4 then
  1188. context.model_preview_dialog.textures = context.predefined_liveries_tab.textures
  1189. end
  1190. set_context(player, context)
  1191. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1192. return
  1193. end
  1194. if fields.InfoButton then
  1195. context.livery_template_info_dialog.is_active = true
  1196. local livery_design = context.livery_editor_tab.livery_design
  1197. local livery_template_name = livery_design and livery_design.livery_template_name
  1198. if livery_template_name then
  1199. context.livery_template_info_dialog.livery_template_name = livery_template_name
  1200. set_context(player, context)
  1201. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1202. end
  1203. return
  1204. end
  1205. local color_button_idx = get_indexed_selection("EditColorButton", advtrains_livery_database.get_overlays_per_template_limit(), fields)
  1206. if color_button_idx then
  1207. context.color_selector_dialog.is_active = true
  1208. context.color_selector_dialog.color_button_idx = color_button_idx
  1209. context.color_selector_dialog.current_color = context.livery_editor_tab.controls.overlays[color_button_idx].color or "#808080"
  1210. if not context.color_selector_dialog.saved_color then
  1211. context.color_selector_dialog.saved_color = context.color_selector_dialog.current_color
  1212. end
  1213. update_color_selector_controls(context.color_selector_dialog)
  1214. set_context(player, context)
  1215. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1216. return
  1217. end
  1218. if fields.CurrentLiveryEditButton then
  1219. context.livery_editor_tab = clone_tab(context.current_livery_tab)
  1220. -- Update override_values in order to keep them in sync with the new livery design loaded into the editor.
  1221. save_override_values(context)
  1222. context.current_tab = 2 -- Switch to the editor tab
  1223. context.applied = advtrains_livery_database.are_livery_designs_equivalent(context.current_livery_tab.livery_design, context.livery_editor_tab.livery_design) -- should always be true
  1224. set_context(player, context)
  1225. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1226. return
  1227. end
  1228. if fields.SavedLiveryEditButton then
  1229. context.livery_editor_tab = clone_tab(context.saved_livery_tab)
  1230. -- Update override_values in order to keep them in sync with the new livery design loaded into the editor.
  1231. save_override_values(context)
  1232. context.current_tab = 2 -- Switch to the editor tab
  1233. context.applied = advtrains_livery_database.are_livery_designs_equivalent(context.current_livery_tab.livery_design, context.livery_editor_tab.livery_design)
  1234. set_context(player, context)
  1235. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1236. return
  1237. end
  1238. if fields.SavedLiveryApplyButton then
  1239. callback_functions[context.wagon_mod_name].apply_wagon_livery_textures(player, context.wagon, context.saved_livery_tab.textures)
  1240. play_apply_sound(context.wagon)
  1241. context.current_livery_tab = clone_tab(context.saved_livery_tab)
  1242. context.applied = advtrains_livery_database.are_livery_designs_equivalent(context.saved_livery_tab.livery_design, context.livery_editor_tab.livery_design)
  1243. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context))
  1244. return
  1245. end
  1246. if fields.ApplyButton then
  1247. callback_functions[context.wagon_mod_name].apply_wagon_livery_textures(player, context.wagon, context.livery_editor_tab.textures)
  1248. play_apply_sound(context.wagon)
  1249. context.current_livery_tab = clone_tab(context.livery_editor_tab)
  1250. context.applied = true
  1251. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context))
  1252. return
  1253. end
  1254. if fields.EditorSaveButton then
  1255. context.saved_livery_tab = clone_tab(context.livery_editor_tab)
  1256. context.current_tab = 3 -- Switch to the save livery tab
  1257. set_context(player, context)
  1258. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1259. return
  1260. end
  1261. if fields.CurrentTab then
  1262. local tab = tonumber(fields.CurrentTab)
  1263. if tab ~= context.current_tab then
  1264. context.current_tab = tab
  1265. set_context(player, context)
  1266. return minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1267. end
  1268. end
  1269. if fields.RotationCheckbox then
  1270. context.common_controls.rotate_checkbox = fields.RotationCheckbox == "true"
  1271. set_context(player, context)
  1272. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1273. end
  1274. if fields.EditorResetButton then
  1275. context.livery_editor_tab.livery_design.overlays = {}
  1276. context.override_values = {}
  1277. -- Update context.livery_editor_tab.textures
  1278. context.livery_editor_tab.textures = advtrains_livery_database.get_livery_textures_from_design(context.livery_editor_tab.livery_design, context.wagon.id)
  1279. context.applied = advtrains_livery_database.are_livery_designs_equivalent(context.current_livery_tab.livery_design, context.livery_editor_tab.livery_design)
  1280. set_context(player, context)
  1281. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1282. end
  1283. if fields.EditorLiveryTemplateName then
  1284. -- Update context.livery_editor_tab.livery_design
  1285. context.livery_editor_tab.livery_design.livery_template_name = fields.EditorLiveryTemplateName
  1286. context.livery_editor_tab.livery_design.overlays = {}
  1287. -- Update all color overlays in the livery design based on recent edits/changes
  1288. -- (Without this, all color override values would be lost whenever a different livery template is selected.)
  1289. restore_override_values(context)
  1290. -- Update context.livery_editor_tab.textures
  1291. context.livery_editor_tab.textures = advtrains_livery_database.get_livery_textures_from_design(context.livery_editor_tab.livery_design, context.wagon.id)
  1292. -- Update context.livery_editor_tab.controls
  1293. context.livery_editor_tab.controls.livery_template_name_selection = get_index(context.wagon_valid_livery_template_names, fields.EditorLiveryTemplateName) or 1
  1294. local wagon_livery_template = advtrains_livery_database.get_wagon_livery_template(context.wagon_type, context.livery_editor_tab.livery_design.livery_template_name)
  1295. update_overlay_controls(wagon_livery_template, context.livery_editor_tab.livery_design, context.livery_editor_tab.controls.overlays)
  1296. context.applied = advtrains_livery_database.are_livery_designs_equivalent(context.current_livery_tab.livery_design, context.livery_editor_tab.livery_design)
  1297. set_context(player, context)
  1298. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1299. return
  1300. end
  1301. if fields.PredefinedLiveriesTextList and fields.PredefinedLiveriesTextList:sub(1, 3) == "CHG" then
  1302. update_predefined_liveries_tab_selection(context, tonumber(fields.PredefinedLiveriesTextList:sub(5, 8)))
  1303. set_context(player, context)
  1304. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1305. return
  1306. end
  1307. if fields.PredefinedLiveriesEditButton then
  1308. update_tab_from_predefined_livery_design(context, context.livery_editor_tab)
  1309. -- Update override_values in order to keep them in sync with the new livery design loaded into the editor.
  1310. -- (Without this, all color override values would be lost whenever a different livery template is selected.)
  1311. save_override_values(context)
  1312. context.current_tab = 2 -- Switch to the editor tab
  1313. context.applied = advtrains_livery_database.are_livery_designs_equivalent(context.current_livery_tab.livery_design, context.livery_editor_tab.livery_design)
  1314. set_context(player, context)
  1315. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1316. return
  1317. end
  1318. if fields.PredefinedLiveriesApplyButton then
  1319. callback_functions[context.wagon_mod_name].apply_wagon_livery_textures(player, context.wagon, context.predefined_liveries_tab.textures)
  1320. play_apply_sound(context.wagon)
  1321. update_tab_from_predefined_livery_design(context, context.current_livery_tab)
  1322. context.applied = false
  1323. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context))
  1324. return
  1325. end
  1326. local override_idx, selection_value = get_indexed_selection("ColorOverride", advtrains_livery_database.get_overlays_per_template_limit(), fields)
  1327. if override_idx then
  1328. local selection_idx = get_index(color_overrides, selection_value)
  1329. if not selection_idx then
  1330. return
  1331. end
  1332. -- Update the applicable color overlay in the livery design based on the color override field that was changed.
  1333. if context.livery_editor_tab.livery_design.overlays then
  1334. if selection_idx > 1 then
  1335. -- A color override was specified, make note of it in the livery design
  1336. local color = get_color_by_name(color_overrides[selection_idx])
  1337. if selection_idx == 2 then -- "Custom"
  1338. if context.livery_editor_tab.livery_design.overlays[override_idx] and
  1339. context.livery_editor_tab.livery_design.overlays[override_idx].color then
  1340. -- Keep color if switching from an existing override.
  1341. color = context.livery_editor_tab.livery_design.overlays[override_idx].color
  1342. else
  1343. color = "#7F7F7F" -- An unnamed color
  1344. end
  1345. end
  1346. context.livery_editor_tab.livery_design.overlays[override_idx] = {
  1347. id = override_idx, -- This should be an index to an overlay in livery_templates. Currently, it will likely a cause a problem if a template's overlays are not registered with contiguous numbers starting with 1.
  1348. color = color
  1349. }
  1350. elseif context.livery_editor_tab.livery_design.overlays[override_idx] then
  1351. -- The color override was removed so remove if from the livery design.
  1352. context.livery_editor_tab.livery_design.overlays[override_idx] = nil
  1353. end
  1354. end
  1355. -- Update context.livery_editor_tab.textures
  1356. context.livery_editor_tab.textures = advtrains_livery_database.get_livery_textures_from_design(context.livery_editor_tab.livery_design, context.wagon.id)
  1357. -- Update context.livery_editor_tab.controls to match the updated livery design
  1358. context.livery_editor_tab.controls.overlays[override_idx].override_selection_idx = selection_idx
  1359. context.livery_editor_tab.controls.overlays[override_idx].override_selection_name = selection_value
  1360. context.livery_editor_tab.controls.overlays[override_idx].color =
  1361. context.livery_editor_tab.livery_design.overlays and
  1362. context.livery_editor_tab.livery_design.overlays[override_idx] and
  1363. context.livery_editor_tab.livery_design.overlays[override_idx].color or nil
  1364. -- Update the applicable context.override_values[] to the updated value
  1365. save_override_value(context, override_idx, override_idx and context.livery_editor_tab.livery_design.overlays and
  1366. context.livery_editor_tab.livery_design.overlays[override_idx] and
  1367. context.livery_editor_tab.livery_design.overlays[override_idx].color or nil)
  1368. context.applied = advtrains_livery_database.are_livery_designs_equivalent(context.current_livery_tab.livery_design, context.livery_editor_tab.livery_design)
  1369. set_context(player, context)
  1370. minetest.show_formspec(player:get_player_name(), livery_designer_form, get_formspec(player, context) )
  1371. return
  1372. end
  1373. end
  1374. end)
  1375. function advtrains_livery_designer.activate_tool(player, wagon, mod_name)
  1376. assert(mod_name, "Invalid mod name")
  1377. assert(callback_functions[mod_name], "Attempted use of unregistered mod '"..mod_name.."'")
  1378. assert(callback_functions[mod_name].apply_wagon_livery_textures, "Missing registration of apply_wagon_livery_textures() for '"..mod_name.."' mod.")
  1379. show_livery_designer_form(player, wagon)
  1380. end