Divergent/mods/Shader 3D Scopes Editor/gamedata/scripts/shader_scopes_editor.script

951 lines
29 KiB
Plaintext
Raw Normal View History

--========================================================
--
-- Shader 3D Scopes Editor Script by Private Pirate v1.1.0
--
--========================================================
function on_game_start()
RegisterScriptCallback("on_key_press", on_key_press)
RegisterScriptCallback("actor_on_first_update", actor_on_first_update)
RegisterScriptCallback("on_option_change", on_option_change)
RegisterScriptCallback("save_state", save_state)
RegisterScriptCallback("load_state", load_state)
end
--;-- VARIABLES AND TABLES ---------------------------------------------------------------------------------------
local shader_parameters = {
["s3ds_reticle_size"] = {text = "sse_reticle_size", def = 4, typ = "track", index = 1, min = 0.5, max = 10, step = 0.1},
["s3ds_eye_relief"] = {text = "sse_eye_relief", def = 4, typ = "track", index = 2, min = 1, max = 10, step = 0.01},
["s3ds_exit_pupil"] = {text = "sse_exit_pupil", def = 0.3, typ = "track", index = 3, min = 0.1, max = 5, step = 0.01},
["s3ds_ffp"] = {text = "sse_ffp", def = 0, typ = "check", index = 4},
["s3ds_reflection_hue"] = {text = "sse_refl_hue", def = 0.65, typ = "track", index = 5, min = 0, max = 1, step = 0.01},
["s3ds_min_zoom_1x"] = {text = "sse_min_zoom", def = 0, typ = "check", index = 6},
["s3ds_image_type"] = {text = "sse_image_type", def = 0, typ = "radio", index = 7, content = {{"image_type_1",0}, {"image_type_2",1}, {"image_type_3",2}}},
["s3ds_reticle_type"] = {text = "sse_reticle_type", def = 0, typ = "track", index = 8, min = 0, max = 7, step = 1},
["s3ds_dirt_intensity"] = {text = "sse_lens_dirt", def = 0, typ = "track", index = 9, min = 0, max = 10, step = 0.1},
["s3ds_chroma_power"] = {text = "sse_chroma_power", def = 0, typ = "track", index = 10, min = 0, max = 0.2, step = 0.01},
["s3ds_lens_color"] = {text = "sse_lens_color", def = "1,1,1", typ = "radio", index = 11, content = {{"lens_none","1,1,1"}, {"lens_old_yellow","0.95,0.91,0.83"}, {"lens_russian_blue","0.93,0.96,1"}, {"lens_contrast_yellow","1,0.95,0.3"}}},
["ms_count"] = {text = "sse_reticle_count", def = 1, typ = "radio", index = 12, content = {{"ms_count_1",1}, {"ms_count_2",2}, {"ms_count_3",3}, {"ms_count_4",4}}},
["ms_colors"] = {text = "sse_ret_colors", def = "0,0,0,0", typ = "radio", index = 13, content = {{"no_clr","0,0,0,0"}, {"scope_black","0,0,0,1"}, {"scope_red","1,0.2,0.2,1"}, {"scope_red_dim","0.4,0.05,0.05,1"}}},
}
local data -- sorted shader_parameters table
local ext_val -- S3DS shader param preset of current weapon (only those who are actually in use, NOT IN CORRECT ORDER)
local ext_val_ms -- mark switch shader param preset of current weapon (only those who are actually in use, NOT IN CORRECT ORDER)
local curr_val = {} -- sorted version of ext_val
local cache = {} -- cache weapon specific Shader Parameter values
--general
local debug_mode = DEV_DEBUG or DEV_DEBUG_DEV
local keybind = shader_scopes_editor_mcm.get_config("keybind")
local copy_mode = shader_scopes_editor_mcm.get_config("copy_mode")
local ZOOM_FACTOR = z_3d_scopes_mcm.get_config("zoom_factor")
local NVG_BLUR = z_3d_scopes_mcm.get_config("nvg_blur")
local show_help_wnd = false
-- weapon related variables
local active_item
local is_wpn
local wpn
local section
local last_wpn
-- Utilities
local precision = 2 -- allowed numbers of zeroes
local functor = function(t,a,b) return t[a].index < t[b].index end
local m_floor = math.floor
local str_format = string.format
local lens_clr_index = shader_parameters["s3ds_lens_color"].index -- better than calling in functions
local ms_cnt_index = shader_parameters["ms_count"].index -- better than calling in functions
local ms_clr_index = shader_parameters["ms_colors"].index -- better than calling in functions
function shallow_copy(src) -- retains independence when passing values between arrays, otherwise changing src array changes dst array when src = dst
local dst = {}
for k, v in pairs(src) do
dst[k] = v
end
return dst
end
function conv_to_arr(str)
local arr = {}
for val in string.gmatch(str, "[^,]+") do
arr[#arr + 1] = tonumber(val)
end
return arr
end
--;-- MAIN FUNCTIONS ---------------------------------------------------------------------------------------------
function on_option_change()
keybind = shader_scopes_editor_mcm.get_config("keybind")
copy_mode = shader_scopes_editor_mcm.get_config("copy_mode")
ZOOM_FACTOR = z_3d_scopes_mcm.get_config("zoom_factor")
NVG_BLUR = z_3d_scopes_mcm.get_config("nvg_blur")
end
function save_state(m_data)
m_data.cache = cache
end
function load_state(m_data)
if (m_data.cache) then
cache = m_data.cache
end
end
function on_key_press(key)
if (not debug_mode) then
if (key == keybind) then
actor_menu.set_msg(1, game.translate_string("sse_no_dbg_msg"), 5)
end
return
end
active_item = db.actor:active_item()
is_wpn = IsWeapon(active_item)
wpn = is_wpn and active_item
if (wpn) then
wpn_section = wpn:section()
end
if (key == keybind) then
if (wpn) then
get_params(wpn)
show_ui()
actor_menu.set_msg(1, game.translate_string("sse_help_msg"), 2)
else
actor_menu.set_msg(1, game.translate_string("sse_no_wpn_msg"),5)
end
elseif (key == DIK_keys.DIK_K) then
printf("lens_clr_index = "..lens_clr_index)
printf("ms_cnt_index = "..ms_cnt_index)
printf("ms_clr_index = "..ms_clr_index)
printe("cache[wpn_section]")
for i, v in ipairs(cache[wpn_section]) do
printf(i.." : "..tostring(v))
end
end
end
-- sort shader_parameters table by index when read by game and write into new table "data"
function actor_on_first_update()
data = {
param = {},
text = {},
def = {},
typ = {},
index = {},
min = {},
max = {},
step = {},
content = {},
}
for key, v in spairs(shader_parameters, functor) do
data.param[#data.param + 1] = key
data.text[#data.text + 1] = v.text
data.def[#data.def + 1] = v.def
data.typ[#data.typ + 1] = v.typ
data.index[#data.index + 1] = v.index
data.min[#data.min + 1] = v.min or "nil" -- has to be filled otherwise order is not given anymore, nil doesn't work but "nil" does
data.max[#data.max + 1] = v.max or "nil"
data.step[#data.step + 1] = v.step or "nil"
data.content[#data.content + 1] = v.content or "nil"
end
end
-- get Shader Parameter preset values of active weapon, write into new array along with default values, called when UI opens
function get_params(wpn)
ext_val = z_3d_scopes.parse_parameters(wpn) --> NOT IN ORDER
ext_val_ms = z_mark_switch.parse_parameters(wpn) --> NOT IN ORDER
-- replace curr_val[i] with curr_val[key] to get array with preset + default param values
for i, key in ipairs(data.param) do
curr_val[i] = (ext_val[key] or ext_val_ms[key]) or data.def[i] --> COMPLETE AND IN CORRECT ORDER
end
cache_values()
end
-- cache (default) values of currently active weapon
function cache_values()
-- create new key with name of weapon section
if (not cache[wpn_section]) then
cache[wpn_section] = {}
end
-- check whether cache[wpn_section] contains values, if not fill with preset values
for i = 1, #curr_val do
if (not cache[wpn_section][i]) then
cache[wpn_section][i] = curr_val[i]
end
end
update_shader_on_open_ui()
end
-- update Shader Parameters when switching weapons and then reopening UI or when pasting copied values
function update_shader_on_open_ui()
-- Shader Parameter 1
if (cache[wpn_section][1] ~= curr_val[1] or
cache[wpn_section][2] ~= curr_val[2] or
cache[wpn_section][3] ~= curr_val[3] or
cache[wpn_section][4] ~= curr_val[4]) then
get_console():execute("s3ds_param_1 "..cache[wpn_section][1]..", "..cache[wpn_section][2]..", "..cache[wpn_section][3]..", "..cache[wpn_section][4])
end
-- Shader Parameter 2
if (cache[wpn_section][5] ~= curr_val[5] or
cache[wpn_section][6] ~= curr_val[6]) then
get_console():execute("s3ds_param_2 "..cache[wpn_section][5]..", 0, "..cache[wpn_section][6]..", "..(ZOOM_FACTOR or 1.5))
end
-- Shader Parameter 3
if (cache[wpn_section][7] ~= curr_val[7] or
cache[wpn_section][8] ~= curr_val[8] or
cache[wpn_section][9] ~= curr_val[9] or
cache[wpn_section][10] ~= curr_val[10]) then
get_console():execute("s3ds_param_3 "..cache[wpn_section][7]..", "..cache[wpn_section][8]..", "..cache[wpn_section][9]..", "..cache[wpn_section][10])
end
-- Shader Parameter 4
if (cache[wpn_section][11] ~= curr_val[11]) then
get_console():execute("s3ds_param_4 "..cache[wpn_section][11]..", "..(NVG_BLUR and 1 or 0))
end
-- Marks Switch Parameter 1
if (cache[wpn_section][12] ~= curr_val[12]) then
get_console():execute("markswitch_count "..cache[wpn_section][12])
end
-- Mark Switch Parameter 2
if (cache[wpn_section][13] ~= curr_val[13]) then
get_console():execute("markswitch_color "..cache[wpn_section][13])
end
end
--;-- EDITOR MENU UI ---------------------------------------------------------------------------------------------
GUI = nil -- instance, don't touch!
-- open UI Window
function show_ui()
if (not GUI) then
GUI = ShaderScopesEditor()
end
if (GUI and (not GUI:IsShown())) then
GUI:ShowDialog(true)
Register_UI("ShaderScopesEditor", "shader_scopes_editor", GUI)
end
end
class "ShaderScopesEditor" (CUIScriptWnd)
function ShaderScopesEditor:__init() super()
self:InitControls()
self:InitCallBacks()
end
function ShaderScopesEditor:__finalize()
end
function ShaderScopesEditor:InitControls()
self:SetWndRect(Frect():set(0,0,1024,768))
self:SetAutoDelete(true)
self.xml = CScriptXmlInit()
local xml = self.xml
xml:ParseFile("ui_shader_scopes_editor_16.xml")
-- UI Window
self.dialog = xml:InitStatic("SSE", self)
self.background = xml:InitStatic("SSE:background", self.dialog)
self.line_1_1 = xml:InitStatic("SSE:background:line_1_1", self.background)
self.line_1_2 = xml:InitStatic("SSE:background:line_1_2", self.background)
self.title = xml:InitTextWnd("SSE:background:title", self.background)
self.title:SetText(game.translate_string("sse_menu_title"))
self.line_2_1 = xml:InitStatic("SSE:background:line_2_1", self.background)
self.line_2_2 = xml:InitStatic("SSE:background:line_2_2", self.background)
-- Shader Parameter Description
self.desc = xml:InitTextWnd("SSE:desc", self.dialog)
self.desc:SetText(game.translate_string("sse_desc"))
self.main_wnd = xml:InitStatic("SSE:main_wnd", self.dialog)
-- tab selection and buttons
self.tab_select = xml:InitStatic("SSE:tab_select", self.dialog)
self.tab_1_bg = xml:InitStatic("SSE:tab_select:background_1", self.tab_select)
self.tab_1 = xml:Init3tButton("SSE:tab_select:tab_1", self.tab_select)
self.tab_1:TextControl():SetText(game.translate_string("sse_tab_1"))
self:Register(self.tab_1, "tab_1")
self.tab_2_bg = xml:InitStatic("SSE:tab_select:background_2", self.tab_select)
self.tab_2_bg:Show(false)
self.tab_2 = xml:Init3tButton("SSE:tab_select:tab_2", self.tab_select)
self.tab_2:TextControl():SetText(game.translate_string("sse_tab_2"))
self:Register(self.tab_2, "tab_2")
-- bottom line
self.line_3 = xml:InitStatic("SSE:line_3", self.dialog)
-- S3DS param windows (scroll view) ---------------------------------------
self.s3ds_wnd = xml:InitScrollView("SSE:scroll_view", self.dialog)
self.s3ds_wnd:Clear()
-- parameter windows
self.wnd = {}
self.value = {}
for i = 1, lens_clr_index do
local _st = xml:InitStatic("SSE:window", nil)
self.wnd[i] = {}
self.wnd[i].window = _st
-- Shader Parameter name, reference images
self.wnd[i].title = xml:InitTextWnd("SSE:window:title", _st)
self.wnd[i].title:SetText(game.translate_string(data.text[i]))
-- self.wnd[i].tex_1 = xml:InitStatic("SSE:window:texture_1", _st)
-- self.wnd[i].tex_2 = xml:InitStatic("SSE:window:texture_2", _st)
self:Register_Btn_Reset(i, xml, _st)
self.value[i] = cache[wpn_section][i]
-- trackbars
if (data.typ[i] == "track") then
self:Register_Trackbar(i, xml, _st)
-- checkboxes
elseif (data.typ[i] == "check") then
self:Register_Check(i, xml, _st)
-- multiple checkboxes
elseif (data.typ[i] == "radio") then
self:Register_Radio_Check(i, xml, _st)
end
self.wnd[i].devider = xml:InitStatic("SSE:window:devider", _st)
if (data.param[i] == "s3ds_lens_color") then
self:Add_Color_Sliders(i, xml, _st)
end
self.s3ds_wnd:AddWindow(_st, true)
_st:SetAutoDelete(true)
end
-- Mark Switch param window -----------------------------------------------
self.ms_wnd = xml:InitStatic("SSE:ms_wnd", self.dialog)
for i = ms_cnt_index, (#data.param) do
local _st = xml:InitStatic("SSE:window", nil)
self.wnd[i] = {}
self.wnd[i].window = _st
local pos = self.wnd[i].window:GetWndPos()
local offset = self.wnd[1].window:GetHeight()
self.wnd[i].window:SetWndPos(vector2():set(pos.x, pos.y + (i - ms_cnt_index) * offset))
self.wnd[i].title = xml:InitTextWnd("SSE:window:title", _st)
self.wnd[i].title:SetText(game.translate_string(data.text[i]))
self:Register_Btn_Reset(i, xml, _st)
self.value[i] = cache[wpn_section][i]
self:Register_Radio_Check(i, xml, _st)
if (data.param[i] == "ms_colors") then
self:Add_Color_Sliders(i, xml, _st)
end
self.wnd[i].devider = xml:InitStatic("SSE:window:devider", _st)
_st:SetAutoDelete(true)
self.ms_wnd:AttachChild(_st)
end
self.ms_wnd:Show(false)
-- hint window on hover over window title
self.hint_wnd = utils_ui.UIHint(self)
-- help window with instructions and info
self.help_wnd = xml:InitStatic("help_wnd", self)
self.help_wnd:SetAutoDelete(false)
self.help_text = xml:InitTextWnd("help_wnd:text_wnd", self.help_wnd)
self.help_text:SetText(game.translate_string("sse_help_text"))
self.help_text:AdjustHeightToText()
self.help_wnd:Show(false)
-- Buttons
self.copy_cache = {} -- saves copied values
self.btn_reset_all = xml:Init3tButton("SSE:btn_reset_all", self.dialog)
self:Register(self.btn_reset_all, "btn_reset_all")
self.btn_reset_all:TextControl():SetText(game.translate_string("sse_btn_reset_all"))
self.btn_resume = xml:Init3tButton("SSE:btn_resume", self.dialog)
self:Register(self.btn_resume, "btn_resume")
self.btn_resume:TextControl():SetText(game.translate_string("sse_btn_resume"))
self.btn_copy = xml:Init3tButton("SSE:btn_copy", self.dialog)
self:Register(self.btn_copy, "btn_copy")
self.btn_copy:TextControl():SetText(game.translate_string("sse_btn_copy"))
self.btn_paste = xml:Init3tButton("SSE:btn_paste", self.dialog)
self:Register(self.btn_paste, "btn_paste")
self.btn_paste:TextControl():SetText(game.translate_string("sse_btn_paste"))
self.btn_apply = xml:Init3tButton("SSE:btn_apply", self.dialog)
self:Register(self.btn_apply, "btn_apply")
self.btn_apply:TextControl():SetText(game.translate_string("sse_btn_apply"))
end
-----------------------
-- Ctrl Init Functions
-----------------------
function ShaderScopesEditor:Register_Btn_Reset(i, xml, handler)
local btn_reset_id = "btn_reset_"..i
self.wnd[i][btn_reset_id] = xml:Init3tButton("SSE:window:btn_reset", handler)
self:Register(self.wnd[i][btn_reset_id], btn_reset_id)
self.wnd[i][btn_reset_id]:TextControl():SetText(game.translate_string("sse_btn_reset"))
local _wrapper = function(handler)
self:OnButton_Reset(i)
end
self:AddCallback(btn_reset_id, ui_events.BUTTON_CLICKED, _wrapper, self)
end
function ShaderScopesEditor:Register_Trackbar(i, xml, handler)
self.wnd[i].trackbar = xml:InitTrackBar("SSE:window:trackbar", handler)
-- assign current Shader Parameter values to trackbars when initiating UI
self.value[i] = clamp(self.value[i], data.min[i], data.max[i])
self.wnd[i].trackbar:SetOptFBounds(data.min[i], data.max[i])
self.wnd[i].trackbar:SetFValue(self.value[i])
self.wnd[i].trackbar:SetStep(data.step[i])
-- number display next to trackbar
self.wnd[i].value = xml:InitTextWnd("SSE:window:track_value", handler)
self.wnd[i].value:SetText(self.value[i])
end
function ShaderScopesEditor:Register_Check(i, xml, handler)
local check_id = "checkbox_"..i
self.wnd[i][check_id] = xml:InitCheck("SSE:window:checkbox", handler)
if (self.value[i] == 1) then
self.wnd[i][check_id]:SetCheck(true)
else
self.wnd[i][check_id]:SetCheck(false)
end
self:Register(self.wnd[i][check_id], check_id)
local _wrapper = function(handler)
self:OnButton_Check(i, check_id)
end
self:AddCallback(check_id, ui_events.BUTTON_CLICKED, _wrapper, self)
end
function ShaderScopesEditor:Register_Radio_Check(i, xml, handler)
local count = #data.content[i] -- count entries
local offset = m_floor(self.wnd[i].window:GetWidth()/count)
for j = 1, count do
-- checkboxes
local radio_check_id = "radio_check_"..i.."_"..j
self.wnd[i][radio_check_id] = xml:InitCheck("SSE:window:radio_check", handler)
local pos = self.wnd[i][radio_check_id]:GetWndPos()
self.wnd[i][radio_check_id]:SetWndPos(vector2():set(pos.x + offset*(j-1 + 0.5) - 17, pos.y))
-- compare values set initial states of radio check buttons
local set_check
if (self.value[i] ~= data.content[i][j][2]) then
set_check = false
else
set_check = true
end
self.wnd[i][radio_check_id]:SetCheck(set_check)
-- text windows
local radio_text_id = "radio_text_"..i.."_"..j
self.wnd[i][radio_text_id] = xml:InitTextWnd("SSE:window:radio_text", handler)
self.wnd[i][radio_text_id]:SetText(game.translate_string("sse_lst_"..data.content[i][j][1]))
pos = self.wnd[i][radio_text_id]:GetWndPos()
self.wnd[i][radio_text_id]:SetWndPos(vector2():set(pos.x + offset*(j-1 + 0.5) - 17, pos.y))
self:Register(self.wnd[i][radio_check_id], radio_check_id)
local _wrapper = function(_st)
self:OnRadio_Check(radio_check_id, i, j)
end
self:AddCallback(radio_check_id, ui_events.BUTTON_CLICKED, _wrapper, self)
end
end
function ShaderScopesEditor:Add_Color_Sliders(i, xml, handler)
local size = {}
size.w = self.wnd[i].window:GetWidth()
size.h = self.wnd[i].window:GetHeight()
self.wnd[i].window:SetWndSize(vector2():set(size.w, 2*size.h))
-- convert color value string to array to assign values
self.value[i] = conv_to_arr(self.value[i])
-- init custom trackbars
self.wnd[i].trackbar = {}
self.wnd[i].color = {}
self.wnd[i].value = {}
local colors = {"R", "G", "B"}
for j = 1, 3 do
self.wnd[i].trackbar[j] = xml:InitTrackBar("SSE:ms_wnd:trackbar", handler)
-- assign current Shader Parameter values to trackbars when initiating UI
self.value[i][j] = clamp(self.value[i][j], 0, 1)
self.wnd[i].trackbar[j]:SetOptFBounds(0, 1)
self.wnd[i].trackbar[j]:SetFValue(self.value[i][j])
self.wnd[i].trackbar[j]:SetStep(0.01)
-- color letter and number display next to trackbar
self.wnd[i].color[j] = xml:InitTextWnd("SSE:window:track_value", handler)
self.wnd[i].color[j]:SetText(colors[j])
self.wnd[i].value[j] = xml:InitTextWnd("SSE:window:track_value", handler)
self.wnd[i].value[j]:SetText(self.value[i][j])
local track_pos = self.wnd[i].trackbar[j]:GetWndPos()
local value_pos = self.wnd[i].value[j]:GetWndPos()
self.wnd[i].color[j]:SetWndPos(vector2():set(value_pos.x - 250, value_pos.y + 25*(j-1) + 40))
self.wnd[i].trackbar[j]:SetWndPos(vector2():set(track_pos.x, track_pos.y + 25*(j-1) + 40))
self.wnd[i].value[j]:SetWndPos(vector2():set(value_pos.x, value_pos.y + 25*(j-1) + 40))
end
end
--------------------
-- Button Callbacks
--------------------
function ShaderScopesEditor:InitCallBacks()
self:AddCallback("tab_1", ui_events.BUTTON_CLICKED, self.OnTab_S3DS, self)
self:AddCallback("tab_2", ui_events.BUTTON_CLICKED, self.OnTab_MS, self)
self:AddCallback("btn_reset_all", ui_events.BUTTON_CLICKED, self.OnButton_Reset_All, self)
self:AddCallback("btn_resume", ui_events.BUTTON_CLICKED, self.OnButton_Resume, self)
self:AddCallback("btn_copy", ui_events.BUTTON_CLICKED, self.OnButton_Copy, self)
self:AddCallback("btn_paste", ui_events.BUTTON_CLICKED, self.OnButton_Paste, self)
self:AddCallback("btn_apply", ui_events.BUTTON_CLICKED, self.Save_Params, self)
end
function ShaderScopesEditor:OnButton_Reset(i)
self.value[i] = curr_val[i]
self:Update_Ctrl(self.value)
self:Update_Shader(i)
self:Send_Msg(game.translate_string("sse_btn_reset_msg"), 2)
end
-- show S3DS window
function ShaderScopesEditor:OnTab_S3DS()
if (not self.s3ds_wnd:IsShown()) then
self.s3ds_wnd:Show(true)
self.tab_1_bg:Show(true)
self.ms_wnd:Show(false)
self.tab_2_bg:Show(false)
end
end
-- show Mark Switch window
function ShaderScopesEditor:OnTab_MS()
if (not self.ms_wnd:IsShown()) then
self.s3ds_wnd:Show(false)
self.tab_1_bg:Show(false)
self.ms_wnd:Show(true)
self.tab_2_bg:Show(true)
end
end
function ShaderScopesEditor:OnButton_Check(i, check_id)
local val = self.wnd[i][check_id]:GetCheck()
if (val) then
val = 1
else
val = 0
end
if (val ~= self.value[i]) then
self.value[i] = val
self:Update_Shader(i)
end
end
function ShaderScopesEditor:OnRadio_Check(radio_check_id, i, j)
-- turn other check buttons off when pressing a button
local val = self.wnd[i][radio_check_id]:GetCheck()
if (val) then
for n = 1, #data.content[i] do
local id = "radio_check_"..i.."_"..n
if (n ~= j) then
self.wnd[i][id]:SetCheck(false)
end
end
self.value[i] = data.content[i][j][2]
self:Update_Shader(i)
else
self.wnd[i][radio_check_id]:SetCheck(true)
end
-- update custom color sliders
if (i == lens_clr_index or i == ms_clr_index) then
data.content[i][j][2] = conv_to_arr(data.content[i][j][2])
for k = 1, 3 do
self.wnd[i].trackbar[k]:SetFValue(data.content[i][j][2][k])
self.wnd[i].value[k]:SetText(data.content[i][j][2][k])
end
data.content[i][j][2] = table.concat(data.content[i][j][2], ",")
end
end
-- discard all changes and apply Shader Parameter preset values to active weapon
function ShaderScopesEditor:OnButton_Reset_All()
cache[wpn_section] = {}
self:Update_Ctrl(curr_val)
-- reinitiate cache values of active weapon
cache[wpn_section] = shallow_copy(curr_val)
z_3d_scopes.update_shader(wpn)
z_mark_switch.update_shader(wpn, z_mark_switch.parse_parameters(wpn))
self:Send_Msg(game.translate_string("sse_btn_reset_all_msg"), 2)
end
-- discard all changes and close UI (reopening UI brings back changed values)
function ShaderScopesEditor:OnButton_Resume()
z_3d_scopes.update_shader(wpn)
z_mark_switch.update_shader(wpn, z_mark_switch.parse_parameters(wpn))
GUI:HideDialog()
GUI:Show(false)
Unregister_UI("ShaderScopesEditor")
self:Send_Msg(game.translate_string("sse_btn_resume_msg"), 5)
end
function ShaderScopesEditor:OnButton_Copy()
self.copy_cache = {} -- empty cache
if (copy_mode == 1) then
for i, v in pairs(cache[wpn_section]) do
if (v ~= curr_val[i]) then
self.copy_cache[i] = v
end
end
self:Send_Msg(game.translate_string("sse_btn_copy_msg_1"), 2)
else
self.copy_cache = cache[wpn_section]
self:Send_Msg(game.translate_string("sse_btn_copy_msg_2"), 2)
end
end
function ShaderScopesEditor:OnButton_Paste()
if (not next(self.copy_cache)) then
self:Send_Msg(game.translate_string("sse_btn_paste_msg_1"), 2)
return
end
-- shallow_copy() is necessary, otherwise changing values in copied section changes values in pasted section
if (copy_mode == 1) then
for i, v in pairs(shallow_copy(self.copy_cache)) do
cache[wpn_section][i] = v
end
else
cache[wpn_section] = shallow_copy(self.copy_cache)
end
self:Update_Ctrl(cache[wpn_section])
update_shader_on_open_ui()
self:Send_Msg(game.translate_string("sse_btn_paste_msg_2"), 2)
end
-- Show hint message on button press
function ShaderScopesEditor:Send_Msg(str, dur)
printf("3D Shader Scopes Editor: "..str)
actor_menu.set_msg(1, str, dur)
end
---------------------------------
-- Update UI and 3D Scope Shader
---------------------------------
function ShaderScopesEditor:Update_Ctrl(arr)
for i, val in ipairs(arr) do
if (data.typ[i] == "track") then
self.value[i] = clamp(val, data.min[i], data.max[i])
self.wnd[i].trackbar:SetFValue(val)
self.wnd[i].value:SetText(val)
elseif (data.typ[i] == "check") then
local check_id = "checkbox".."_"..i
self.value[i] = val
if (val == 1) then
self.wnd[i][check_id]:SetCheck(true)
else
self.wnd[i][check_id]:SetCheck(false)
end
elseif (data.typ[i] == "radio") then
self.value[i] = val
for n = 1, #data.content[i] do
local id = "radio_check_"..i.."_"..n
if (data.content[i][n][2] == self.value[i]) then
self.wnd[i][id]:SetCheck(true)
else
self.wnd[i][id]:SetCheck(false)
end
end
end
-- custom color sliders
if (i == lens_clr_index or i == ms_clr_index) then
for j = 1, 3 do
if (type(self.value[i]) == "string") then
self.value[i] = conv_to_arr(self.value[i])
end
if (type(val) == "string") then
val = conv_to_arr(val)
end
self.value[i][j] = clamp(val[j], 0, 1)
self.wnd[i].trackbar[j]:SetFValue(val[j])
self.wnd[i].value[j]:SetText(val[j])
end
val = table.concat(val, ",")
self.value[i] = table.concat(self.value[i], ",")
end
end
end
function ShaderScopesEditor:Update()
CUIScriptWnd.Update(self)
-- check active weapon to update values in UI on weapon switch
if (not last_wpn or last_wpn ~= wpn_section) then
last_wpn = wpn_section
self:Update_Ctrl(cache[wpn_section])
return
end
-- show hint on hover (from ui_options.script)
for i,ctrl in ipairs(self.wnd) do
if ctrl.title:IsCursorOverWindow() then
local str = data.text[i].."_desc"
local str_t = game.translate_string(str)
if (str ~= str_t) then
self.hint_wnd:Update(str_t)
end
return
end
end
self.hint_wnd:Update()
-- hack to simulate tracing method for trackbar value changes (from ui_ctrl_lighting.script)
for i,ctrl in ipairs(self.wnd) do
if (data.typ[i] == "track") then
if ctrl.trackbar:IsCursorOverWindow() then
local val = round_idp(ctrl.trackbar:GetFValue(), precision) -- round value from UI controls
if (val ~= self.value[i]) then
self.value[i] = val
self.wnd[i].value:SetText(val)
self:Update_Shader(i)
end
end
end
end
-- custom color sliders
for i = lens_clr_index, ms_clr_index do
if (i ~= ms_cnt_index) then
for j = 1, 3 do
if (self.wnd[i].trackbar[j]:IsCursorOverWindow()) then
local val = round_idp(self.wnd[i].trackbar[j]:GetFValue(), precision) -- round value from UI controls
if (type(self.value[i]) == "string") then
self.value[i] = conv_to_arr(self.value[i])
end
if (val ~= self.value[i][j]) then
self.value[i][j] = val
self.wnd[i].value[j]:SetText(val)
self.value[i] = table.concat(self.value[i], ",")
self:Update_Shader(i)
end
end
end
end
end
-- toggle help window
if (self.show_help_wnd) then
self.help_wnd:Show(true)
else
self.help_wnd:Show(false)
end
end
-- apply Shader Parameter values and update cache
function ShaderScopesEditor:Update_Shader(i)
if (self.value[i] ~= cache[wpn_section][i]) then
-- Shader Parameter 1
if (i <= 4) then
get_console():execute("s3ds_param_1 "..self.value[1]..", "..self.value[2]..", "..self.value[3]..", "..self.value[4])
-- Shader Parameter 2
elseif (i == 5 or i == 6) then
get_console():execute("s3ds_param_2 "..self.value[5]..", 0, "..self.value[6]..", "..(ZOOM_FACTOR or 1.5))
-- Shader Parameter 3
elseif (i >= 7 and i <= 10) then
get_console():execute("s3ds_param_3 "..self.value[7]..", "..self.value[8]..", "..self.value[9]..", "..self.value[10])
-- Shader Parameter 4
elseif (i == 11) then
get_console():execute("s3ds_param_4 "..self.value[11]..", "..(NVG_BLUR and 1 or 0))
-- Marks Switch Parameter 1
elseif (i == 12) then
get_console():execute("markswitch_count "..self.value[12])
-- Mark Switch Parameter 2
elseif (i == 13) then
get_console():execute("markswitch_color "..self.value[13])
end
end
-- update cache
cache[wpn_section][i] = self.value[i]
end
-- close UI
function ShaderScopesEditor:OnKeyboard(dik, keyboard_action)
-- close UI Window
if (keyboard_action == ui_events.WINDOW_KEY_PRESSED) then
if (dik == DIK_keys.DIK_ESCAPE) then
GUI:HideDialog()
GUI:Show(false)
Unregister_UI("ShaderScopesEditor")
actor_menu.set_msg(1, game.translate_string("sse_escape_msg"),5)
elseif (dik == DIK_keys.DIK_H) then
show_help_wnd = not show_help_wnd
self.show_help_wnd = show_help_wnd
end
end
end
-- save changed Shader Parameter values to cache_dbg.ltx
function ShaderScopesEditor:Save_Params()
local ini_cc = ui_debug_launcher.ini_cc
self.save_cache = {}
self.save_cache[wpn_section] = {}
for i = 1, #data.param do
if (cache[wpn_section][i] ~= curr_val[i]) then
self.save_cache[wpn_section][i] = {}
self.save_cache[wpn_section][i][1] = data.param[i]
if (type(cache[wpn_section][i]) == "string") then
for j, cont in ipairs(data.content[i]) do
if (cache[wpn_section][i] == tostring(cont[2])) then
self.save_cache[wpn_section][i][2] = data.content[i][j][1]
break
else
self.save_cache[wpn_section][i][2] = tostring(cache[wpn_section][i].."(custom_color, set_custom_name)")
end
end
else
self.save_cache[wpn_section][i][2] = cache[wpn_section][i]
end
end
end
if (not next(self.save_cache[wpn_section])) then
self:Send_Msg(str_format(game.translate_string("sse_btn_apply_msg_1"), wpn_section), 2)
else
local par, val -- parameter name, parameter value
for sec,v in pairs(self.save_cache) do
for i,w in pairs(v) do
if (w) then
par = w[1]
val = w[2]
ini_cc:w_value(sec, par, val)
end
end
end
ini_cc:save()
self:Send_Msg(str_format(game.translate_string("sse_btn_apply_msg_2"), wpn_section), 2)
end
end