--======================================================== -- -- 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