Rewrote custom textures module
This commit is contained in:
parent
c861e19f2e
commit
e688b5bd91
1 changed files with 209 additions and 47 deletions
|
@ -1,90 +1,252 @@
|
||||||
local vmf = get_mod("VMF")
|
local vmf = get_mod("VMF")
|
||||||
|
|
||||||
local injected_materials = {}
|
local _CUSTOM_NONE_ATLAS_TEXTURES = {}
|
||||||
local none_atlas_textures = {}
|
local _CUSTOM_UI_ATLAS_SETTINGS = {}
|
||||||
|
|
||||||
-- @TODO: can several materials be specified via 1 material file? Figure it out.
|
local _UI_RENDERERS = {}
|
||||||
function inject_material(material_path, material_name, ...)
|
local _INJECTED_MATERIALS = {}
|
||||||
|
|
||||||
--print("[FUCK]: Mods.gui.inject_material " .. material_path .. material_name)
|
-- ####################################################################################################################
|
||||||
|
-- ##### Local functions ##############################################################################################
|
||||||
|
-- ####################################################################################################################
|
||||||
|
|
||||||
local material_users = {...}
|
local original_gasbtn_function = UIAtlasHelper.get_atlas_settings_by_texture_name
|
||||||
if #material_users == 0 then
|
local function check_texture_availability(mod, texture_name)
|
||||||
material_users = {"all"}
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, material_user in ipairs(material_users) do
|
local texture_exists, texture_settings = pcall(original_gasbtn_function, texture_name)
|
||||||
if not injected_materials[material_user] then
|
if texture_exists then
|
||||||
injected_materials[material_user] = {}
|
|
||||||
|
if type(texture_settings) == "nil" then
|
||||||
|
mod:error("(custom texture/atlas): texture name '%s' is already used by Fatshark in 'none_atlas_textures'", texture_name)
|
||||||
|
else
|
||||||
|
mod:error("(custom texture/atlas): texture name '%s' is already used by Fatshark in atlas '%s'", texture_name, tostring(texture_settings.material_name))
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(injected_materials[material_user], material_path)
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
none_atlas_textures[material_name] = true
|
if _CUSTOM_NONE_ATLAS_TEXTURES[texture_name] then
|
||||||
|
mod:error("(custom texture/atlas): texture name '%s' is already used by the mod '%s' as none atlas texture", texture_name, _CUSTOM_NONE_ATLAS_TEXTURES[texture_name])
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if _CUSTOM_UI_ATLAS_SETTINGS[texture_name] then
|
||||||
|
texture_settings = _CUSTOM_UI_ATLAS_SETTINGS[texture_name]
|
||||||
|
mod:error("(custom texture/atlas): texture name '%s' is already used by the mod '%s' in atlas '%s'", texture_name, texture_settings.mod_name, tostring(texture_settings.material_name))
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- ####################################################################################################################
|
||||||
|
-- ##### VMFMod #######################################################################################################
|
||||||
|
-- ####################################################################################################################
|
||||||
|
|
||||||
--table.dump(injected_materials, "injected_materials", 2)
|
VMFMod.custom_textures = function (self, ...)
|
||||||
|
|
||||||
|
for i, texture_name in ipairs({...}) do
|
||||||
|
if type(texture_name) == "string" then
|
||||||
|
if check_texture_availability(self, texture_name) then
|
||||||
|
_CUSTOM_NONE_ATLAS_TEXTURES[texture_name] = self:get_name()
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self:error("(custom_textures): all arguments should have the string type, but the argument #%s is %s", i, type(texture_name))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
VMFMod.custom_atlas = function (self, material_settings_file, material_name, masked_material_name, point_sample_material_name,
|
||||||
|
masked_point_sample_material_name, saturated_material_name)
|
||||||
|
|
||||||
|
-- @TODO: this check is legit... is it?
|
||||||
|
if type(material_settings_file) ~= "string" or
|
||||||
|
type(material_name) ~= "string" or
|
||||||
|
type(masked_material_name) ~= "string" or
|
||||||
|
type(point_sample_material_name) ~= "string" or
|
||||||
|
type(masked_point_sample_material_name) ~= "string" or
|
||||||
|
type(saturated_material_name) ~= "string" then
|
||||||
|
self:error("(custom_atlas): all the arguments have to have the string type")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local material_settings = self:dofile(material_settings_file)
|
||||||
|
if material_settings then
|
||||||
|
|
||||||
|
local mod_name = self:get_name()
|
||||||
|
|
||||||
|
for texture_name, texture_settings in pairs(material_settings) do
|
||||||
|
if check_texture_availability(self, texture_name) then
|
||||||
|
texture_settings.mod_name = mod_name
|
||||||
|
|
||||||
|
texture_settings.material_name = material_name
|
||||||
|
texture_settings.masked_material_name = masked_material_name
|
||||||
|
texture_settings.point_sample_material_name = point_sample_material_name
|
||||||
|
texture_settings.masked_point_sample_material_name = masked_point_sample_material_name
|
||||||
|
texture_settings.saturated_material_name = saturated_material_name
|
||||||
|
|
||||||
|
_CUSTOM_UI_ATLAS_SETTINGS[texture_name] = texture_settings
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
self:error("(custom_atlas): can't load 'material_settings'")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
VMFMod.inject_materials = function (self, ui_renderer_creator, ...)
|
||||||
|
|
||||||
|
if type(ui_renderer_creator) ~= "string" then
|
||||||
|
self:error("(inject_materials): argument 'ui_renderer_creator' should have the string type, not %s", type(ui_renderer_creator))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local injected_materials_list = _INJECTED_MATERIALS[ui_renderer_creator] or {}
|
||||||
|
|
||||||
|
local can_inject = true
|
||||||
|
for i, new_injected_material in ipairs({...}) do
|
||||||
|
if type(new_injected_material) == "string" then
|
||||||
|
|
||||||
|
can_inject = true
|
||||||
|
|
||||||
|
-- check if injected_materials_list already contains current material
|
||||||
|
for _, injected_material in ipairs(injected_materials_list) do
|
||||||
|
if new_injected_material == injected_material then
|
||||||
|
can_inject = false
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if can_inject then
|
||||||
|
table.insert(injected_materials_list, new_injected_material)
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
self:error("(inject_materials): all arguments should have the string type, but the argument #%s is %s", i + 1, type(new_injected_material))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
_INJECTED_MATERIALS[ui_renderer_creator] = injected_materials_list
|
||||||
|
|
||||||
|
-- recreate GUIs with injected materials for ui_renderers created by 'ui_renderer_creator'
|
||||||
|
for ui_renderer, _ in pairs(_UI_RENDERERS) do
|
||||||
|
if ui_renderer.vmf_data.ui_renderer_creator == ui_renderer_creator then
|
||||||
|
|
||||||
|
local new_materials_list = table.clone(ui_renderer.vmf_data.original_materials)
|
||||||
|
|
||||||
|
for _, injected_material in ipairs(injected_materials_list) do
|
||||||
|
table.insert(new_materials_list, "material")
|
||||||
|
table.insert(new_materials_list, injected_material)
|
||||||
|
end
|
||||||
|
|
||||||
|
World.destroy_gui(ui_renderer.world, ui_renderer.gui)
|
||||||
|
World.destroy_gui(ui_renderer.world, ui_renderer.gui_retained)
|
||||||
|
|
||||||
|
ui_renderer.gui = World.create_screen_gui(ui_renderer.world, "immediate", unpack(new_materials_list))
|
||||||
|
ui_renderer.gui_retained = World.create_screen_gui(ui_renderer.world, unpack(new_materials_list))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ####################################################################################################################
|
||||||
|
-- ##### Hooks ########################################################################################################
|
||||||
|
-- ####################################################################################################################
|
||||||
|
|
||||||
|
local ui_renderer_creating = false
|
||||||
vmf:hook("UIRenderer.create", function(func, world, ...)
|
vmf:hook("UIRenderer.create", function(func, world, ...)
|
||||||
|
|
||||||
|
-- FINDING OUT WHO CREATED UI_RENDERER
|
||||||
|
|
||||||
local ui_renderer_creator = nil
|
local ui_renderer_creator = nil
|
||||||
|
|
||||||
-- extract the part with actual callstack
|
local callstack = debug.traceback()
|
||||||
local callstack = Script.callstack():match('Callstack>(.-)<')
|
-- get the name of lua script which called 'UIRenderer.create'
|
||||||
if callstack then
|
-- it's always the 3rd string of the 'debug.traceback()' output
|
||||||
|
local i = 0
|
||||||
-- get the name of lua script which called 'UIRenderer.create'
|
for s in callstack:gmatch("(.-)\n") do
|
||||||
-- it's always the 4th string of callstack ([ ] [0] [1] >[2]<)
|
i = i + 1
|
||||||
-- print(callstack) -- @DEBUG
|
if i == 3 then
|
||||||
local i = 0
|
ui_renderer_creator = s:match("([^%/]+)%.lua:")
|
||||||
for s in callstack:gmatch("(.-)\n") do
|
break
|
||||||
i = i + 1
|
|
||||||
if i == 4 then
|
|
||||||
ui_renderer_creator = s:match("([^%/]+)%.lua")
|
|
||||||
break --@TODO: uncomment after debugging or ... (?)
|
|
||||||
end
|
|
||||||
--EchoConsole(s) -- @DELETEME
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if ui_renderer_creator then
|
if not ui_renderer_creator then
|
||||||
print("UI_RENDERER CREATED BY: " .. ui_renderer_creator) -- @DEBUG
|
print(Script.callstack())
|
||||||
else
|
vmf:error("(UIRenderer.create): ui_renderer_creator not found. You're never supposed to see this message. " ..
|
||||||
--EchoConsole("You're never supposed to see this.")
|
"If you see this, please, save the game log and report about this incident to the VMF team.")
|
||||||
--assert(true, "That's not right. That's not right at all!")
|
|
||||||
--EchoConsole(callstack)
|
|
||||||
return func(world, ...)
|
return func(world, ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- CREATING THE LIST OF TEXTURES FOR THE NEW UI_RENDERER
|
||||||
|
|
||||||
local ui_renderer_materials = {...}
|
local ui_renderer_materials = {...}
|
||||||
|
|
||||||
if injected_materials[ui_renderer_creator] then
|
if _INJECTED_MATERIALS[ui_renderer_creator] then
|
||||||
for _, material in ipairs(injected_materials[ui_renderer_creator]) do
|
for _, injected_material in ipairs(_INJECTED_MATERIALS[ui_renderer_creator]) do
|
||||||
table.insert(ui_renderer_materials, "material")
|
table.insert(ui_renderer_materials, "material")
|
||||||
table.insert(ui_renderer_materials, material)
|
table.insert(ui_renderer_materials, injected_material)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if injected_materials["all"] then
|
-- DEBUG INFO
|
||||||
for _, material in ipairs(injected_materials["all"]) do
|
|
||||||
table.insert(ui_renderer_materials, "material")
|
print("UI_RENDERER CREATED BY: " .. ui_renderer_creator) -- @DEBUG
|
||||||
table.insert(ui_renderer_materials, material)
|
vmf:dump(ui_renderer_materials, "UI_RENDERER MATERIALS", 1) -- @DEBUG
|
||||||
end
|
|
||||||
|
|
||||||
|
-- CREATING THE NEW UI_RENDERER AND SAVING SOME DATA INSIDE OF IT
|
||||||
|
|
||||||
|
ui_renderer_creating = true
|
||||||
|
local ui_renderer = func(world, unpack(ui_renderer_materials))
|
||||||
|
|
||||||
|
_UI_RENDERERS[ui_renderer] = true
|
||||||
|
|
||||||
|
ui_renderer.vmf_data.original_materials = {...}
|
||||||
|
ui_renderer.vmf_data.ui_renderer_creator = ui_renderer_creator
|
||||||
|
|
||||||
|
return ui_renderer
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
vmf:hook("MakeTableStrict", function(func, t)
|
||||||
|
|
||||||
|
if ui_renderer_creating then
|
||||||
|
t.vmf_data = {}
|
||||||
|
ui_renderer_creating = false
|
||||||
end
|
end
|
||||||
|
|
||||||
table.dump(ui_renderer_materials, "UI_RENDERER MATERIALS", 2) -- @DEBUG
|
return func(t)
|
||||||
|
end)
|
||||||
|
|
||||||
return func(world, unpack(ui_renderer_materials))
|
|
||||||
|
vmf:hook("UIRenderer.destroy", function(func, self, world)
|
||||||
|
|
||||||
|
_UI_RENDERERS[self] = nil
|
||||||
|
|
||||||
|
func(self, world)
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
vmf:hook("UIAtlasHelper.has_atlas_settings_by_texture_name", function(func, texture_name)
|
||||||
|
|
||||||
|
if _CUSTOM_UI_ATLAS_SETTINGS[texture_name] then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return func(texture_name)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
vmf:hook("UIAtlasHelper.get_atlas_settings_by_texture_name", function(func, texture_name)
|
vmf:hook("UIAtlasHelper.get_atlas_settings_by_texture_name", function(func, texture_name)
|
||||||
|
|
||||||
if none_atlas_textures[texture_name] then
|
if _CUSTOM_NONE_ATLAS_TEXTURES[texture_name] then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if _CUSTOM_UI_ATLAS_SETTINGS[texture_name] then
|
||||||
|
return _CUSTOM_UI_ATLAS_SETTINGS[texture_name]
|
||||||
|
end
|
||||||
|
|
||||||
return func(texture_name)
|
return func(texture_name)
|
||||||
end)
|
end)
|
Loading…
Add table
Reference in a new issue