1720 lines
51 KiB
Plaintext
1720 lines
51 KiB
Plaintext
|
|
||
|
--[[
|
||
|
Script by: Tronex
|
||
|
Engine support by: Rezy
|
||
|
|
||
|
Added: 2019/6/1
|
||
|
Last Edit: 2020/3/23
|
||
|
Weather Editor 2.0
|
||
|
|
||
|
Weather editor allows you to change weather values in real-time. Minute precision.
|
||
|
The GUI is interactive and easy to use, with ability to modify or create new weather files.
|
||
|
Edited values are temporarly cached for the weathers, hours and minutes you worked on. You can return to them in case you turned off the editor (Avoid exiting or reloading when you have unsaved values).
|
||
|
In (Viewer) mode, you can witness weather changes by the time slider.
|
||
|
|
||
|
Keybinds:
|
||
|
• Up Arrow: select previous parameter.
|
||
|
• Down Arrow: select next parameter.
|
||
|
• Left Arrow: reduce\rotate value of selected parameter.
|
||
|
• Right Arrow: increase\rotate value of selected parameter.
|
||
|
• LShift (hold): x10 value step.
|
||
|
• LAlt (hold): x50 value step.
|
||
|
• Q: previous hour.
|
||
|
• A: next hour.
|
||
|
• W: previous minute.
|
||
|
• S: next minute.
|
||
|
• E: increase selected parameter value.
|
||
|
• D: reduce selected parameter value.
|
||
|
• R: increase selected group value (all parameters within).
|
||
|
• F: reduce selected group value (all parameters within).
|
||
|
• T: next moment.
|
||
|
• G: previous moment.
|
||
|
|
||
|
• C: copy select paramter value.
|
||
|
• C + CTRL: copy current moment settings.
|
||
|
• V: paste/apply copied parameter value.
|
||
|
• V + CTRL: paste/apply to current moment settings.
|
||
|
• Z: viewer mode.
|
||
|
• Delete: Reset current modified moment.
|
||
|
• Delete + CTRL: Reset all modified moments.
|
||
|
• H: toggle hint window.
|
||
|
• Esc or Home: turn off editor.
|
||
|
--]]
|
||
|
|
||
|
local parameters = {
|
||
|
-- Type: 0 = string | 1 = number | 2 = 3d vector | 3 = 4d vector |
|
||
|
["ambient"] = { typ = 0, def = {""}, indx = 1 , ini= "environment\\ambients.ltx" },
|
||
|
["ambient_color"] = { typ = 2, def = {0,0,0}, indx = 2 , min = 0, max = 1, step = 0.001 },
|
||
|
["clouds_color"] = { typ = 3, def = {0,0,0,0}, indx = 3 , min = 0, max = 1, step = 0.001 },
|
||
|
["clouds_texture"] = { typ = 0, def = {""}, indx = 4 , empty_value= true },
|
||
|
["far_plane"] = { typ = 1, def = {0}, indx = 5 , min = 200, max = 1500, step = 1 },
|
||
|
["fog_color"] = { typ = 2, def = {0,0,0}, indx = 6 , min = 0, max = 1, step = 0.001 },
|
||
|
["fog_density"] = { typ = 1, def = {0}, indx = 7 , min = 0, max = 1, step = 0.01 },
|
||
|
["fog_distance"] = { typ = 1, def = {0}, indx = 8 , min = 0, max = 1500, step = 1 },
|
||
|
["hemisphere_color"] = { typ = 3, def = {0,0,0,0}, indx = 9 , min = 0, max = 1, step = 0.001 },
|
||
|
["rain_density"] = { typ = 1, def = {0}, indx = 10, min = 0, max = 1, step = 0.01 },
|
||
|
["rain_color"] = { typ = 2, def = {0,0,0}, indx = 11, min = 0, max = 1, step = 0.001 },
|
||
|
["sky_color"] = { typ = 2, def = {0,0,0}, indx = 12, min = 0, max = 1, step = 0.001 },
|
||
|
["sky_rotation"] = { typ = 1, def = {0}, indx = 13, min = 0, max = 360, step = 0.005 },
|
||
|
["sky_texture"] = { typ = 4, def = {"",""}, indx = 14 , path= "sky\\" },
|
||
|
["sun"] = { typ = 0, def = {""}, indx = 15 , ini= "environment\\suns.ltx" , empty_value= true },
|
||
|
["sun_color"] = { typ = 2, def = {0,0,0}, indx = 16, min = 0, max = 5, step = 0.001 },
|
||
|
-- ["sun_longitude"] = { typ = 1, def = {0}, indx = 17, min = 0, max = 360, step = 1 },
|
||
|
-- ["sun_altitude"] = { typ = 1, def = {0}, indx = 18, min = 0, max = 360, step = 1 },
|
||
|
["sun_shafts_intensity"] = { typ = 1, def = {0}, indx = 19, min = 0, max = 1, step = 0.01 },
|
||
|
["thunderbolt_collection"] = { typ = 0, def = {""}, indx = 20 , ini= "environment\\thunderbolt_collections.ltx" , empty_value= true },
|
||
|
["thunderbolt_duration"] = { typ = 1, def = {0}, indx = 21, min = 0, max = 1, step = 0.01 },
|
||
|
["thunderbolt_period"] = { typ = 1, def = {0}, indx = 22, min = 0, max = 1000, step = 1 },
|
||
|
["water_intensity"] = { typ = 1, def = {0}, indx = 23, min = 0, max = 1, step = 0.01 },
|
||
|
["wind_velocity"] = { typ = 1, def = {0}, indx = 24, min = 0, max = 1000, step = 1 },
|
||
|
["tree_amplitude_intensity"] = { typ = 1, def = {0}, indx = 25, min = 0, max = 1, step = 0.01 },
|
||
|
["wind_direction"] = { typ = 1, def = {0}, indx = 26, min = 0, max = 360, step = 1 },
|
||
|
|
||
|
["bloom_threshold"] = { typ = 1, def = {0}, indx = 50 , min = 1, max = 100, step = 0.01 },
|
||
|
["bloom_exposure"] = { typ = 1, def = {0}, indx = 51 , min = 0, max = 100, step = 0.01 },
|
||
|
["bloom_sky_intensity"] = { typ = 1, def = {0}, indx = 52 , min = 0, max = 100, step = 0.01 },
|
||
|
}
|
||
|
|
||
|
local dir = "environment\\weathers\\"
|
||
|
local precision = 6 -- allowed number of zeros
|
||
|
local clr_list = {
|
||
|
["def"] = GetARGB(255,200,200,200),
|
||
|
["temp"] = GetARGB(255,255,100,100),
|
||
|
["saved"] = GetARGB(255,100,255,100),
|
||
|
}
|
||
|
|
||
|
local string_find = string.find
|
||
|
local string_gsub = string.gsub
|
||
|
local func_small = function(t,a,b) return a < b end
|
||
|
|
||
|
-- Keybinds
|
||
|
local jump_1 = 1
|
||
|
local jump_2 = 10
|
||
|
local jump_3 = 50
|
||
|
local D_JUMP2 = DIK_keys.DIK_LSHIFT
|
||
|
local D_JUMP3 = DIK_keys.DIK_LCONTROL
|
||
|
|
||
|
local D_HOUR_ADD = DIK_keys.DIK_Q
|
||
|
local D_HOUR_SUB = DIK_keys.DIK_A
|
||
|
|
||
|
local D_MIN_ADD = DIK_keys.DIK_W
|
||
|
local D_MIN_SUB = DIK_keys.DIK_S
|
||
|
|
||
|
local D_MOMENT_ADD = DIK_keys.DIK_E
|
||
|
local D_MOMENT_SUB = DIK_keys.DIK_D
|
||
|
|
||
|
local D_VAL_ADD = DIK_keys.DIK_R
|
||
|
local D_VAL_SUB = DIK_keys.DIK_F
|
||
|
|
||
|
local D_VALG_ADD = DIK_keys.DIK_T
|
||
|
local D_VALG_SUB = DIK_keys.DIK_G
|
||
|
|
||
|
local D_COPY = DIK_keys.DIK_C
|
||
|
local D_PASTE = DIK_keys.DIK_V
|
||
|
|
||
|
local D_MOVE_UP = DIK_keys.DIK_UP
|
||
|
local D_MOVE_DOWN = DIK_keys.DIK_DOWN
|
||
|
local D_MOVE_LEFT = DIK_keys.DIK_LEFT
|
||
|
local D_MOVE_RIGHT = DIK_keys.DIK_RIGHT
|
||
|
|
||
|
local D_VIEWER = DIK_keys.DIK_Z
|
||
|
local D_CLEAR = DIK_keys.DIK_DELETE
|
||
|
local D_HELP = DIK_keys.DIK_H
|
||
|
|
||
|
|
||
|
-------------------------------------------------------------------
|
||
|
GUI = nil -- instance, don't touch
|
||
|
function start(owner)
|
||
|
-- Hide the owner
|
||
|
if owner then
|
||
|
if (owner:IsShown()) then
|
||
|
owner:HideDialog()
|
||
|
owner:Show(false)
|
||
|
end
|
||
|
else
|
||
|
hide_hud_inventory()
|
||
|
end
|
||
|
|
||
|
if (not GUI) then
|
||
|
GUI = WeatherEditor(owner)
|
||
|
end
|
||
|
|
||
|
if (GUI) and (not GUI:IsShown()) then
|
||
|
GUI:ShowDialog(true)
|
||
|
GUI:Refresh()
|
||
|
|
||
|
Register_UI("WeatherEditor","ui_debug_weather")
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
-------------------------------------------------------------------
|
||
|
class "WeatherEditor" (CUIScriptWnd)
|
||
|
|
||
|
function WeatherEditor:__init(owner) super()
|
||
|
self.owner = owner
|
||
|
self.debug = true
|
||
|
|
||
|
self.help = false
|
||
|
self.select = 1
|
||
|
self.select_g = 1
|
||
|
self.jump = jump_1
|
||
|
|
||
|
-- Indexing
|
||
|
self.idx = 0 -- number of indexes
|
||
|
self.idx_g = {} -- index [per count]
|
||
|
self.idx_i = {} -- inner index [per index]
|
||
|
self.idx_p = {} -- count [per par]
|
||
|
self.name = {} -- parameter name [per index]
|
||
|
self.type = {} -- parameter type [per index]
|
||
|
self.parent = {} -- parent parameter [per index]
|
||
|
self.list = {} -- parameter list [line] = true [per index]
|
||
|
self.list_n = {} -- parameter list [order] = line [per index]
|
||
|
self.list_i = 1 -- to trace list values
|
||
|
self.folder = {} -- parameter list [line] = true [per index]
|
||
|
self.folder_last = {} -- to trace last selected folder
|
||
|
|
||
|
-- current time
|
||
|
self.c_weather = level.get_weather()
|
||
|
self.c_hour = math.floor(level.get_time_hours())
|
||
|
self.c_minute = math.floor(level.get_time_minutes())
|
||
|
|
||
|
-- Storage
|
||
|
self.range = {}
|
||
|
self.memo = {}
|
||
|
self.copy = {}
|
||
|
self.copy_1 = {}
|
||
|
|
||
|
-- Viewer
|
||
|
self.vw_i = {}
|
||
|
self.vw_val = 1
|
||
|
self.vw_width = 0
|
||
|
self.vw_pos = 0
|
||
|
self.vw_autoplay = false
|
||
|
self.vw_tg = 0
|
||
|
self.vw_g_step = 100 -- [ms] autoplay speed (1 min per time step )
|
||
|
self.vw_marks = {}
|
||
|
self.vw_ruler_start = false
|
||
|
self.vw_ruler_min = {
|
||
|
[15] = true,
|
||
|
[30] = true,
|
||
|
[45] = true,
|
||
|
}
|
||
|
|
||
|
-- Weather files
|
||
|
self.weather_files = {}
|
||
|
local fileList = getFS():file_list_open("$game_config$", dir, bit_or(FS.FS_ListFiles, FS.FS_RootOnly))
|
||
|
local count = fileList and fileList:Size() or 0
|
||
|
if count > 0 then
|
||
|
for i = 1, count do
|
||
|
local file_name_full = fileList:GetAt(i - 1)
|
||
|
local file_name = file_name_full:sub(1, -5)
|
||
|
local file_ext = file_name_full:sub(-4, -1)
|
||
|
if file_name and starts_with(file_name,"w_") and (file_ext == ".ltx") then
|
||
|
self.weather_files[#self.weather_files + 1] = file_name
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
self:InitControls()
|
||
|
self:InitCallBacks()
|
||
|
|
||
|
self:Reset(true)
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:__finalize()
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:InitControls()
|
||
|
self:SetWndRect (Frect():set(0,0,1024,768))
|
||
|
self:SetAutoDelete(true)
|
||
|
|
||
|
self.xml = self.owner and self.owner.xml or CScriptXmlInit()
|
||
|
|
||
|
local xml = self.xml
|
||
|
if (not self.owner) then
|
||
|
xml:ParseFile ("ui_debug_launcher.xml")
|
||
|
end
|
||
|
|
||
|
self.dialog = xml:InitStatic("dbg_weather_editor", self)
|
||
|
|
||
|
self.frame = xml:InitFrame("dbg_weather_editor:frame", self.dialog)
|
||
|
self.cap = xml:InitStatic("dbg_weather_editor:cap",self.dialog)
|
||
|
|
||
|
-- Select weather file
|
||
|
self.cap_weather = xml:InitStatic("dbg_weather_editor:cap_weather",self.dialog)
|
||
|
|
||
|
self.list_weather = xml:InitComboBox("dbg_weather_editor:list_weather", self.dialog)
|
||
|
self.list_weather:SetAutoDelete(true)
|
||
|
self:Register(self.list_weather, "list_weather")
|
||
|
|
||
|
-- Select time
|
||
|
self.cap_time = xml:InitStatic("dbg_weather_editor:cap_time",self.dialog)
|
||
|
|
||
|
self.input_hour = xml:InitEditBox("dbg_weather_editor:input_hour", self.dialog)
|
||
|
self:Register(self.input_hour,"input_hour")
|
||
|
|
||
|
self.input_minute = xml:InitEditBox("dbg_weather_editor:input_minute", self.dialog)
|
||
|
self:Register(self.input_minute,"input_minute")
|
||
|
|
||
|
-- Buttons
|
||
|
self.dialog_btn = xml:InitStatic("dbg_weather_editor:buttons",self.dialog)
|
||
|
|
||
|
-- Copy params
|
||
|
self.btn_copy = xml:Init3tButton("dbg_weather_editor:buttons:btn_copy", self.dialog_btn)
|
||
|
self:Register(self.btn_copy, "btn_copy")
|
||
|
|
||
|
-- Paste params
|
||
|
self.btn_paste = xml:Init3tButton("dbg_weather_editor:buttons:btn_paste", self.dialog_btn)
|
||
|
self:Register(self.btn_paste, "btn_paste")
|
||
|
|
||
|
-- View
|
||
|
self.btn_view = xml:Init3tButton("dbg_weather_editor:buttons:btn_view", self.dialog_btn)
|
||
|
self:Register(self.btn_view, "btn_view")
|
||
|
|
||
|
-- Save
|
||
|
self.btn_save = xml:Init3tButton("dbg_weather_editor:buttons:btn_save", self.dialog_btn)
|
||
|
self:Register(self.btn_save, "btn_save")
|
||
|
|
||
|
-- Resume
|
||
|
self.btn_resume = xml:Init3tButton("dbg_weather_editor:buttons:btn_resume", self.dialog_btn)
|
||
|
self:Register(self.btn_resume, "btn_resume")
|
||
|
|
||
|
-- Clear
|
||
|
self.btn_clear = xml:Init3tButton("dbg_weather_editor:buttons:btn_clear", self.dialog_btn)
|
||
|
self:Register(self.btn_clear, "btn_clear")
|
||
|
|
||
|
-- Help
|
||
|
self.btn_help = xml:Init3tButton("dbg_weather_editor:buttons:btn_help", self.dialog_btn)
|
||
|
self:Register(self.btn_help, "btn_help")
|
||
|
|
||
|
-- Exit
|
||
|
self.btn_exit = xml:Init3tButton("dbg_weather_editor:buttons:btn_exit", self.dialog_btn)
|
||
|
self:Register(self.btn_exit, "btn_exit")
|
||
|
|
||
|
-- Name new preset
|
||
|
self.input_preset = xml:InitEditBox("dbg_weather_editor:input_preset", self.dialog)
|
||
|
self.input_preset:SetText("Enter new file name...")
|
||
|
--self:Register(self.input_preset,"input_preset")
|
||
|
|
||
|
-- Line
|
||
|
xml:InitStatic("dbg_weather_editor:line",self.dialog)
|
||
|
|
||
|
-- Parameters
|
||
|
self.par = {} -- input box [per index]
|
||
|
self.par_cap = {} -- parameter cap [per count]
|
||
|
self.par_hl = {} -- highlight box [per index]
|
||
|
|
||
|
self.scroll_par = xml:InitScrollView("dbg_weather_editor:scroll_par", self.dialog)
|
||
|
self.scroll_par:Clear()
|
||
|
|
||
|
self.st = {}
|
||
|
local cnt = 0
|
||
|
local functor = function(t,a,b) return t[a].indx < t[b].indx end
|
||
|
for par,v in spairs(parameters,functor) do
|
||
|
cnt = cnt + 1
|
||
|
|
||
|
self.st[cnt] = xml:InitStatic("dbg_weather_editor:tmp_par", nil)
|
||
|
|
||
|
self.idx_g[cnt] = {}
|
||
|
|
||
|
self.par_cap[cnt] = xml:InitTextWnd("dbg_weather_editor:op_par:cap", self.st[cnt])
|
||
|
self.par_cap[cnt]:SetText(par)
|
||
|
|
||
|
-- Multi boxes for vectors
|
||
|
local typ = v.typ
|
||
|
local idx = ((typ == 2) and 3) or ((typ == 3) and 4) or ((typ == 4) and 2) or 1
|
||
|
for i=1,idx do
|
||
|
|
||
|
-- Tracing
|
||
|
local ext = self:GetStringByType(i,typ)
|
||
|
self.idx = self.idx + 1
|
||
|
self.idx_g[cnt][i] = self.idx
|
||
|
self.idx_i[self.idx] = i
|
||
|
self.idx_p[par] = cnt
|
||
|
self.name[self.idx] = par .. ext
|
||
|
self.type[self.idx] = typ
|
||
|
self.parent[self.idx] = par
|
||
|
|
||
|
-- Parameter element and hightlight texture
|
||
|
if self:IsList(typ) then
|
||
|
self.par[self.idx] = xml:InitComboBox("dbg_weather_editor:op_par:list" .. ext, self.st[cnt])
|
||
|
self.par_hl[self.idx] = xml:InitStatic("dbg_weather_editor:op_par:hl_list" .. ext, self.st[cnt])
|
||
|
else
|
||
|
self.par[self.idx] = xml:InitEditBox("dbg_weather_editor:op_par:input" .. ext, self.st[cnt])
|
||
|
self.par_hl[self.idx] = xml:InitStatic("dbg_weather_editor:op_par:hl" .. ext, self.st[cnt])
|
||
|
end
|
||
|
|
||
|
-- Hightlight last selected parameter
|
||
|
if (self.idx ~= self.select) then
|
||
|
self.par_hl[self.idx]:Show(false)
|
||
|
end
|
||
|
|
||
|
local ii = self.idx
|
||
|
local _wrapper = function(handler) -- we need wrapper in order to pass ctrl to method
|
||
|
self:On_Param(ii)
|
||
|
end
|
||
|
self:Register(self.par[self.idx], "par_" .. self.idx)
|
||
|
self:AddCallback("par_" .. self.idx, self:IsList(typ) and ui_events.LIST_ITEM_SELECT or ui_events.EDIT_TEXT_COMMIT, _wrapper, self)
|
||
|
end
|
||
|
|
||
|
self.scroll_par:AddWindow(self.st[cnt], true)
|
||
|
self.st[cnt]:SetAutoDelete(false)
|
||
|
end
|
||
|
|
||
|
-- Weather viewer
|
||
|
self.dialog_v = xml:InitStatic("dbg_weather_viewer",self)
|
||
|
self.vw_frame = xml:InitFrame("dbg_weather_viewer:frame", self.dialog_v)
|
||
|
self.vw_scroll = xml:InitScrollView("dbg_weather_viewer:scroll", self.dialog_v)
|
||
|
self.vw_track = xml:InitTrackBar("dbg_weather_viewer:track", self.dialog_v)
|
||
|
self.vw_time = xml:InitTextWnd("dbg_weather_viewer:time", self.dialog_v)
|
||
|
self.vw_cap_autoplay = xml:InitStatic("dbg_weather_viewer:playing",self.dialog_v)
|
||
|
self.vw_btn_play = xml:Init3tButton("dbg_weather_viewer:btn_play", self.dialog_v)
|
||
|
self.vw_btn_pause = xml:Init3tButton("dbg_weather_viewer:btn_pause", self.dialog_v)
|
||
|
|
||
|
self.vw_width = self.vw_track:GetWidth()
|
||
|
self.vw_pos = self.vw_track:GetWndPos()
|
||
|
self:Register(self.vw_btn_play, "btn_play")
|
||
|
self:Register(self.vw_btn_pause, "btn_pause")
|
||
|
self.dialog_v:Show(false)
|
||
|
self.vw_cap_autoplay:Show(false)
|
||
|
--self.vw_btn_play:Show(false)
|
||
|
--self.vw_btn_pause:Show(false)
|
||
|
|
||
|
local is_wide = utils_xml.is_widescreen()
|
||
|
self.width = (device().width) - self.dialog:GetWidth()
|
||
|
self.hight = (device().height)
|
||
|
self.msg_width = is_wide and (self.width * 0.8) or self.width
|
||
|
|
||
|
-- Message boxes
|
||
|
self.message_box_save = CUIMessageBoxEx()
|
||
|
self:Register(self.message_box_save, "mb_save")
|
||
|
|
||
|
-- Message Window
|
||
|
self.msg_wnd = xml:InitFrame("hint_wnd:background",self)
|
||
|
self.msg_wnd:SetAutoDelete(false)
|
||
|
self.msg_wnd_text = xml:InitTextWnd("hint_wnd:text",self.msg_wnd)
|
||
|
self.msg_wnd_text:SetTextAlignment(2)
|
||
|
|
||
|
self.msg_wnd:Show(false)
|
||
|
self.msg_wnd:SetColor(GetARGB(255,0,0,0))
|
||
|
|
||
|
-- Help Window
|
||
|
self.help_wnd = xml:InitFrame("help_wnd:background",self)
|
||
|
self.help_wnd:SetAutoDelete(false)
|
||
|
self.help_wnd_text = xml:InitTextWnd("help_wnd:text",self.help_wnd)
|
||
|
--self.help_wnd_text:SetTextAlignment(2)
|
||
|
self.help_wnd_text:SetText(game.translate_string("st_ui_dbg_weather_about"))
|
||
|
self.help_wnd_text:AdjustHeightToText()
|
||
|
self.help_wnd_text:SetWndSize(vector2():set(self.msg_width, self.help_wnd_text:GetHeight()+10))
|
||
|
self.help_wnd_text:SetWndPos(vector2():set(20,10))
|
||
|
|
||
|
self.help_wnd:Show(false)
|
||
|
self.help_wnd:SetWndSize(vector2():set(self.msg_width, 700))
|
||
|
self.help_wnd:SetWndPos(vector2():set( self.dialog:GetWidth() , 1 ))
|
||
|
self.help_wnd:SetColor(GetARGB(255,0,0,0))
|
||
|
|
||
|
-- Hint Window
|
||
|
self.hint_wnd = xml:InitFrame("hint_wnd:background",self)
|
||
|
self.hint_wnd:SetAutoDelete(false)
|
||
|
self.hint_wnd_text = xml:InitTextWnd("hint_wnd:text",self.hint_wnd)
|
||
|
self.hint_wnd:Show(false)
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:InitCallBacks()
|
||
|
self:AddCallback("list_weather", ui_events.LIST_ITEM_SELECT, self.On_Weather, self)
|
||
|
|
||
|
self:AddCallback("input_hour", ui_events.EDIT_TEXT_COMMIT, self.On_Time, self)
|
||
|
self:AddCallback("input_minute", ui_events.EDIT_TEXT_COMMIT, self.On_Time, self)
|
||
|
|
||
|
self:AddCallback("btn_copy", ui_events.BUTTON_CLICKED, self.OnBTN_Copy, self)
|
||
|
self:AddCallback("btn_paste", ui_events.BUTTON_CLICKED, self.OnBTN_Paste, self)
|
||
|
self:AddCallback("btn_view", ui_events.BUTTON_CLICKED, self.Viewer_Start, self)
|
||
|
self:AddCallback("btn_save", ui_events.BUTTON_CLICKED, self.OnBTN_Save, self)
|
||
|
self:AddCallback("btn_resume", ui_events.BUTTON_CLICKED, self.OnBTN_Resume, self)
|
||
|
self:AddCallback("btn_clear", ui_events.BUTTON_CLICKED, self.OnBTN_Clear, self)
|
||
|
self:AddCallback("btn_exit", ui_events.BUTTON_CLICKED, self.OnBTN_Exit, self)
|
||
|
self:AddCallback("btn_help", ui_events.BUTTON_CLICKED, self.OnBTN_Help, self)
|
||
|
|
||
|
self:AddCallback("btn_play", ui_events.BUTTON_CLICKED, self.Viewer_Play, self)
|
||
|
self:AddCallback("btn_pause", ui_events.BUTTON_CLICKED, self.Viewer_Pause, self)
|
||
|
|
||
|
self:AddCallback("mb_save", ui_events.MESSAGE_BOX_YES_CLICKED, self.SaveToFile, self)
|
||
|
self:AddCallback("mb_save", ui_events.MESSAGE_BOX_NO_CLICKED, self.Discard, self)
|
||
|
self:AddCallback("mb_save", ui_events.MESSAGE_BOX_OK_CLICKED, self.Discard, self)
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:Reset(force)
|
||
|
|
||
|
-- Fill weather file list
|
||
|
self.list_weather:ClearList()
|
||
|
for i=1,#self.weather_files do
|
||
|
local file = self.weather_files[i]
|
||
|
self.list_weather:AddItem(file, i)
|
||
|
self:Print("Reset | self.list_weather:AddItem(%s, %s)",file,i)
|
||
|
end
|
||
|
|
||
|
-- Set up current time
|
||
|
self.list_weather:SetText(self.c_weather)
|
||
|
self.input_hour:SetText(self.c_hour)
|
||
|
self.input_minute:SetText(self.c_minute)
|
||
|
|
||
|
if (not force) then
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- Fill all string parameter lists
|
||
|
for i=1,self.idx do
|
||
|
if (self.type[i] == 0) then
|
||
|
local par = self.parent[i]
|
||
|
self.par[i]:ClearList()
|
||
|
|
||
|
local path = parameters[par].ini
|
||
|
if path then
|
||
|
local ini = ini_file(path)
|
||
|
if ini then
|
||
|
local cnt = {}
|
||
|
if parameters[par].empty_value then
|
||
|
self:AddToList(par, i, cnt, "")
|
||
|
end
|
||
|
ini:section_for_each( function(section)
|
||
|
self:AddToList(par, i, cnt, section)
|
||
|
end)
|
||
|
|
||
|
end
|
||
|
|
||
|
elseif parameters[par].empty_value then
|
||
|
local cnt = {}
|
||
|
self:AddToList(par, i, cnt, "")
|
||
|
end
|
||
|
|
||
|
elseif (self.type[i] == 4) then
|
||
|
local par = self.parent[i]
|
||
|
local path = parameters[par].path
|
||
|
if path and (not self.folder[par]) then -- only once, which is first list
|
||
|
self.folder[par] = {}
|
||
|
local folderList = getFS():file_list_open("$textures$", path, bit_or(FS.FS_ListFolders, FS.FS_RootOnly))
|
||
|
local count1 = folderList and folderList:Size() or 0
|
||
|
if count1 > 0 then
|
||
|
local cnt = {}
|
||
|
for c = 1, count1 do
|
||
|
local folder_name = folderList:GetAt(c - 1)
|
||
|
if folder_name then
|
||
|
local folder_path = folder_name
|
||
|
self:Print("Reset | Filling path [%s] | Folder = %s", par, folder_path)
|
||
|
self.folder[par][folder_path] = {}
|
||
|
self:AddToList(par, i, cnt, folder_path)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
for folder_path,t in pairs(self.folder[par]) do
|
||
|
local fileList = getFS():file_list_open("$textures$", path .. folder_path, bit_or(FS.FS_ListFiles, FS.FS_RootOnly))
|
||
|
local count = fileList and fileList:Size() or 0
|
||
|
if count > 0 then
|
||
|
for c = 1, count do
|
||
|
local file_name_full = fileList:GetAt(c - 1)
|
||
|
local file_name = file_name_full:sub(1, -5)
|
||
|
local file_ext = file_name_full:sub(-4, -1)
|
||
|
if file_name and (not string_find(file_name,"#small")) and (file_ext == ".dds") then
|
||
|
self:Print("Reset | Filling path [%s] | Folder = %s , File: %s", par, folder_path, file_name)
|
||
|
self.folder[par][folder_path][file_name] = true
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:Refresh(clear)
|
||
|
self:PauseEngine(true)
|
||
|
|
||
|
|
||
|
if (not self.memo[self.c_weather]) then
|
||
|
local fl = self.c_weather
|
||
|
local ltx_name = dir .. fl .. ".ltx"
|
||
|
local ltx = ini_file(ltx_name)
|
||
|
if ltx then
|
||
|
self:Print("Refresh | Reading LTX (%s)", ltx_name)
|
||
|
self.memo[fl] = {}
|
||
|
|
||
|
-- Fill defined moments
|
||
|
ltx:section_for_each(function(sec)
|
||
|
local h, m = self:StringToTime(sec)
|
||
|
self:Print("Refresh | Reading section [%s] | hour: %s - minute: %s", sec, h, m)
|
||
|
|
||
|
if (not self.memo[fl][h]) then self.memo[fl][h] = {} end
|
||
|
self.memo[fl][h][m] = { defined = true } -- "defined" indicate that this moment is a defined section
|
||
|
for par,v in pairs(parameters) do
|
||
|
|
||
|
local val = self:ParseFromString(ltx, sec, par, v.typ)
|
||
|
|
||
|
-- SSS 22 Change - If the value is NIL... Use v.def
|
||
|
if (val[1] == nil) then
|
||
|
val[1] = v.def[1]
|
||
|
end
|
||
|
|
||
|
self.memo[fl][h][m][par] = val
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
|
||
|
|
||
|
self.range = self:GetTimeRange(self.memo[fl])
|
||
|
end
|
||
|
end
|
||
|
self.input_hour:SetText(self.c_hour)
|
||
|
self.input_minute:SetText(self.c_minute)
|
||
|
|
||
|
-- Lerp non-existing moments
|
||
|
local memo = self:CurrentMoment()
|
||
|
if (not memo) then
|
||
|
memo = self:LerpMoment(self.c_weather, self.c_hour, self.c_minute)
|
||
|
if (not memo) then
|
||
|
self:Print("Refresh | can't lerp new moment for file: %s - hour: %s - minute: %s", self.c_weather, self.c_hour, self.c_minute)
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Clear any temp moments near this moment
|
||
|
if clear then
|
||
|
self:ClearMomentsInRange(self.c_weather, self.c_hour, self.c_minute)
|
||
|
end
|
||
|
|
||
|
-- Adjusting text color
|
||
|
local defined = memo.defined
|
||
|
if (defined == true) then
|
||
|
self.cap_time:SetTextureColor( clr_list["saved"] )
|
||
|
--self.cap_time:TextControl():SetTextColor( clr_list["saved"] )
|
||
|
elseif (defined == false) then
|
||
|
self.cap_time:SetTextureColor( clr_list["temp"] )
|
||
|
--self.cap_time:TextControl():SetTextColor( clr_list["temp"] )
|
||
|
else
|
||
|
self.cap_time:SetTextureColor( clr_list["def"] )
|
||
|
--self.cap_time:TextControl():SetTextColor( clr_list["def"] )
|
||
|
end
|
||
|
|
||
|
-- Apply weather values in-game
|
||
|
for par,v in pairs(parameters) do
|
||
|
self:Apply(par, v.typ, memo)
|
||
|
end
|
||
|
weather.sun_time(self.c_hour, self.c_minute)
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:Update()
|
||
|
CUIScriptWnd.Update(self)
|
||
|
|
||
|
if (self.msg_wnd_timer and time_global() > self.msg_wnd_timer) then
|
||
|
self.msg_wnd_timer = nil
|
||
|
self.msg_wnd:Show(false)
|
||
|
end
|
||
|
|
||
|
self.help_wnd:Show( self.help )
|
||
|
|
||
|
-- Viewer mode
|
||
|
if self.dialog_v:IsShown() then
|
||
|
-- Player input
|
||
|
if self.vw_autoplay or self.vw_track:IsCursorOverWindow() then
|
||
|
local val = self.vw_track:GetFValue()
|
||
|
val = math.floor(val)
|
||
|
if (val ~= self.vw_val) then
|
||
|
self.vw_val = val
|
||
|
local h,m = self:Viewer_Value()
|
||
|
if h and m then
|
||
|
self.c_hour = h
|
||
|
self.c_minute = m
|
||
|
self:Refresh()
|
||
|
self:Viewer_Update()
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Auto playing
|
||
|
if self.vw_autoplay and (time_global() > self.vw_tg + self.vw_g_step) then
|
||
|
self.vw_tg = time_global()
|
||
|
local val = self.vw_track:GetFValue()
|
||
|
val = math.floor(val) + 1
|
||
|
val = val > #self.vw_i and 0 or val
|
||
|
self.vw_track:SetFValue( val )
|
||
|
end
|
||
|
|
||
|
-- Hint for markers
|
||
|
for cnt,ele in pairs(self.vw_marks) do
|
||
|
if ele and ele:IsCursorOverWindow() then
|
||
|
local t = self.vw_i[cnt]
|
||
|
local str = self:TimeToString(t.h, t.m)
|
||
|
local ln = (t.defined and "Saved" or "New")
|
||
|
self:SetHint(ln .. " \\n" .. str, t.defined and true or false)
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
self.hint_wnd:Show(false)
|
||
|
end
|
||
|
|
||
|
-- Viewer
|
||
|
function WeatherEditor:Viewer_Play()
|
||
|
self.vw_autoplay = true
|
||
|
self.vw_cap_autoplay:Show(true)
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:Viewer_Pause()
|
||
|
self.vw_autoplay = false
|
||
|
self.vw_cap_autoplay:Show(false)
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:Viewer_Exit()
|
||
|
self:Viewer_Pause()
|
||
|
self.dialog_v:Show(false)
|
||
|
self.dialog:Show(true)
|
||
|
self:Refresh()
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:Viewer_Value()
|
||
|
local point = self.vw_track:GetFValue()
|
||
|
local t = self.vw_i[ math.floor(point) ]
|
||
|
if t then
|
||
|
return t.h, t.m
|
||
|
else
|
||
|
--printf(" can't get table of %s", point)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:Viewer_Update()
|
||
|
self.vw_time:SetText( self:TimeToString( self.c_hour , self.c_minute ) )
|
||
|
|
||
|
local memo = self:CurrentMoment()
|
||
|
local defined = memo and memo.defined
|
||
|
self.vw_time:SetTextColor( ((defined == true) and clr_list["saved"]) or ((defined == false) and clr_list["temp"]) or clr_list["def"] )
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:Viewer_Start()
|
||
|
self.vw_scroll:Clear()
|
||
|
local xml = self.xml
|
||
|
local _st = xml:InitStatic("dbg_weather_viewer:tmp", nil)
|
||
|
empty_table(self.vw_i)
|
||
|
--empty_table(self.vw_marks)
|
||
|
if (not self.vw_ruler) then
|
||
|
self.vw_ruler_start = true
|
||
|
self.vw_ruler = xml:InitStatic("dbg_weather_viewer:tmp", nil)
|
||
|
end
|
||
|
|
||
|
-- Lerping for all moments
|
||
|
local cnt = 0
|
||
|
local cnt_tot = 24 * 60
|
||
|
local hh = self.c_hour
|
||
|
local mm = self.c_minute
|
||
|
local memos = self.memo[self.c_weather]
|
||
|
for h=0,23 do
|
||
|
for m=0,59 do
|
||
|
cnt = cnt + 1
|
||
|
self.vw_i[cnt] = { h = h , m = m }
|
||
|
if (h == hh) and (m == mm) then
|
||
|
point = cnt
|
||
|
end
|
||
|
if not (memos[h] and memos[h][m]) then -- look for undefined moments
|
||
|
local ts, te = self:GetNearestMoment(memos, h, m)
|
||
|
local ps = ts and memos[ts.h] and memos[ts.h][ts.m]
|
||
|
local pe = te and memos[te.h] and memos[te.h][te.m]
|
||
|
if ps and pe then
|
||
|
if (not memos[h]) then memos[h] = {} end
|
||
|
if (not memos[h][m]) then memos[h][m] = {} end
|
||
|
memos[h][m] = self:Lerp(h, m, ts, te, ps, pe)
|
||
|
end
|
||
|
|
||
|
-- Mark saved moments
|
||
|
elseif (memos[h][m].defined ~= nil) then
|
||
|
local defined = memos[h][m].defined
|
||
|
self.vw_i[cnt].defined = defined
|
||
|
local pos = self.vw_width * (cnt / cnt_tot)
|
||
|
self.vw_marks[cnt] = xml:InitStatic("dbg_weather_viewer:marker",_st)
|
||
|
self.vw_marks[cnt]:SetTextureColor( defined and clr_list["saved"] or clr_list["temp"] )
|
||
|
self.vw_marks[cnt]:SetWndPos(vector2():set( pos , 0 ))
|
||
|
end
|
||
|
|
||
|
-- Ruler minutes
|
||
|
if self.vw_ruler_start and self.vw_ruler_min[m] then
|
||
|
local pos = self.vw_width * (cnt / cnt_tot)
|
||
|
local mark = xml:InitStatic("dbg_weather_viewer:marker_min",self.vw_ruler)
|
||
|
mark:SetWndPos(vector2():set( pos , 0 ))
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Ruler hours
|
||
|
if self.vw_ruler_start then
|
||
|
local pos = self.vw_width * (cnt / cnt_tot)
|
||
|
local mark = xml:InitStatic("dbg_weather_viewer:marker_hr",self.vw_ruler)
|
||
|
mark:SetWndPos(vector2():set( pos , 0 ))
|
||
|
end
|
||
|
end
|
||
|
self.vw_scroll:AddWindow(_st, true)
|
||
|
self.vw_scroll:AddWindow(self.vw_ruler, true)
|
||
|
_st:SetAutoDelete(true)
|
||
|
self.vw_ruler:SetAutoDelete(false)
|
||
|
self.vw_ruler_start = false
|
||
|
|
||
|
self.vw_track:SetOptFBounds(1, #self.vw_i)
|
||
|
self.vw_track:SetStep( 1 )
|
||
|
self.vw_track:SetFValue( point )
|
||
|
self.vw_val = point
|
||
|
self:Viewer_Update()
|
||
|
|
||
|
self.dialog:Show(false)
|
||
|
self.dialog_v:Show(true)
|
||
|
end
|
||
|
|
||
|
-- Callbacks
|
||
|
function WeatherEditor:On_Weather()
|
||
|
local cid = self.list_weather:CurrentID()
|
||
|
cid = cid == 0 and 1 or cid
|
||
|
self.c_weather = self.weather_files[cid]
|
||
|
if not (self.c_weather and self.c_weather ~= "") then
|
||
|
self:Print("On_Weather | ERROR can't get weather file name [%s] from the list | ID: %s", self.c_weather, cid)
|
||
|
end
|
||
|
|
||
|
level.set_weather(self.c_weather,true)
|
||
|
self:Refresh()
|
||
|
self:MSG("Selected weather file: %s", self.c_weather)
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:On_Time(h, m)
|
||
|
|
||
|
-- Get hour
|
||
|
h = h or tonumber(self.input_hour:GetText() or "")
|
||
|
if (not h) then
|
||
|
self.input_hour:SetText(self.c_hour)
|
||
|
return
|
||
|
end
|
||
|
h = (h > 23 and 23) or (h < 0 and 0) or h
|
||
|
self.c_hour = h
|
||
|
|
||
|
-- Get minute
|
||
|
m = m or tonumber(self.input_minute:GetText() or "")
|
||
|
if (not m) then
|
||
|
self.input_minute:SetText(self.c_hour)
|
||
|
return
|
||
|
end
|
||
|
m = (m > 59 and 59) or (m < 0 and 0) or m
|
||
|
self.c_minute = m
|
||
|
|
||
|
self:Refresh()
|
||
|
self:MSG("Selected time [%s] of file: %s", self:TimeToString(h,m), self.c_weather)
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:On_Param(idx, val, ignore)
|
||
|
local val = val or self.par[idx]:GetText()
|
||
|
local typ = self.type[idx]
|
||
|
|
||
|
local i = self.idx_i[idx]
|
||
|
local par = self.parent[idx]
|
||
|
|
||
|
self:Print("On_Param | idx: %s - i: %s - val: %s - typ: %s - par: %s", idx, i, val, typ, par)
|
||
|
|
||
|
if self:IsInvalidValue(idx,typ,val) then
|
||
|
-- Restore old value
|
||
|
local memo = self:CurrentMoment()
|
||
|
if memo and memo[par][i] then
|
||
|
self.par[idx]:SetText( memo[par][i] )
|
||
|
end
|
||
|
|
||
|
self:MSG("%c[pda_red]Error with input for parameter (%s)", self.name[idx])
|
||
|
return
|
||
|
end
|
||
|
|
||
|
if self:IsList(typ) then
|
||
|
val = val or ""
|
||
|
else
|
||
|
val = tonumber(val)
|
||
|
val = clamp(val, parameters[par].min, parameters[par].max)
|
||
|
val = round_idp(val, precision)
|
||
|
end
|
||
|
|
||
|
local memo = self:CurrentMoment()
|
||
|
if (not memo) then
|
||
|
self:Print("On_Param | Can't find cache for file: %s - hour: %s - minute: %s", self.c_weather, self.c_hour, self.c_minute)
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- Store value, mark as modified moment
|
||
|
memo[par][i] = val
|
||
|
if (memo.defined == nil) then
|
||
|
memo.defined = false
|
||
|
end
|
||
|
|
||
|
self.par[idx]:SetText(val)
|
||
|
|
||
|
if (not ignore) then
|
||
|
self:Refresh(true)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:OnBTN_Copy()
|
||
|
local memo = self:CurrentMoment()
|
||
|
if (not memo) then
|
||
|
self:Print("OnBTN_Copy | Can't find cache for file: %s - hour: %s - minute: %s", self.c_weather, self.c_hour, self.c_minute)
|
||
|
return
|
||
|
end
|
||
|
|
||
|
self.copy = dup_table(memo)
|
||
|
self.copy.defined = false
|
||
|
self:MSG("Copied values of file: %s - hour: %s - minute: %s", self.c_weather, self.c_hour, self.c_minute)
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:OnBTN_Paste()
|
||
|
if is_empty(self.copy) then
|
||
|
self:MSG("%c[pda_red]Nothing is copied yet!")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local w = self.c_weather
|
||
|
local h = self.c_hour
|
||
|
local m = self.c_minute
|
||
|
if self.memo[w] and self.memo[w][h] and self.memo[w][h][m] then
|
||
|
self.memo[w][h][m] = dup_table(self.copy)
|
||
|
self:Refresh(true)
|
||
|
else
|
||
|
self:Print("OnBTN_Paste | Can't find cache for file: %s - hour: %s - minute: %s", w, h, m)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:OnBTN_Copy_Param()
|
||
|
local memo = self:CurrentMoment()
|
||
|
if (not memo) then
|
||
|
self:Print("OnBTN_Copy_Param | Can't find cache for file: %s - hour: %s - minute: %s", self.c_weather, self.c_hour, self.c_minute)
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local idx = self.select
|
||
|
if (not idx) then
|
||
|
self:MSG("No parameter is selected to copy")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local par = self.parent[idx]
|
||
|
local i = self.idx_i[idx]
|
||
|
local val = memo[par][i]
|
||
|
if (not val) then
|
||
|
self:Print("OnBTN_Copy_Param | No value is found for parameter [%s]", par)
|
||
|
return
|
||
|
end
|
||
|
|
||
|
self.copy_1.par = par
|
||
|
self.copy_1.idx = idx
|
||
|
self.copy_1.val = type(val) == "table" and dup_table(val) or val
|
||
|
|
||
|
self:MSG("Copied value (%s) from parameter", val, par)
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:OnBTN_Paste_Param()
|
||
|
local memo = self:CurrentMoment()
|
||
|
if (not memo) then
|
||
|
self:Print("OnBTN_Paste_Param | Can't find cache for file: %s - hour: %s - minute: %s", self.c_weather, self.c_hour, self.c_minute)
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local val = self.copy_1.val
|
||
|
if (not val) then
|
||
|
self:MSG("No value is copied yet")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local par = self.copy_1.par
|
||
|
local idx = self.copy_1.idx
|
||
|
self:On_Param(idx, val)
|
||
|
|
||
|
self:MSG("Pasted value (%s) for parameter", val, par)
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:OnBTN_Save()
|
||
|
|
||
|
local is_new = false
|
||
|
local file_name = self.input_preset:GetText()
|
||
|
if not (file_name and file_name ~= "") then
|
||
|
file_name = self.c_weather
|
||
|
else
|
||
|
local str_w = string.sub(file_name,1,2)
|
||
|
local is_w = (str_w == "w_")
|
||
|
if not (is_w) then
|
||
|
--self:MSG("%c[pda_red]Incorrect name pattern!\\n%c[ui_gray_1]Naming pattern: w_(custom_name)")
|
||
|
self.message_box_save:InitMessageBox("message_box_ok")
|
||
|
self.message_box_save:SetText( strformat( game.translate_string("st_ui_dbg_weather_save_msg_error") , file_name ) )
|
||
|
self.message_box_save:ShowDialog(true)
|
||
|
return
|
||
|
end
|
||
|
|
||
|
is_new = true
|
||
|
for i=1,#self.weather_files do
|
||
|
local file = self.weather_files[i]
|
||
|
if file == file_name then
|
||
|
is_new = false
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
file_name = dir .. file_name .. ".ltx"
|
||
|
local str = game.translate_string(is_new and "st_ui_dbg_weather_save_msg_new" or "st_ui_dbg_weather_save_msg_old")
|
||
|
self.message_box_save:InitMessageBox("message_box_yes_no")
|
||
|
self.message_box_save:SetText( strformat( str , file_name ) )
|
||
|
self.message_box_save:ShowDialog(true)
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:OnBTN_Resume()
|
||
|
self:PauseEngine(false)
|
||
|
self:Close()
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:OnBTN_Help()
|
||
|
self.help = (not self.help)
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:OnBTN_Clear()
|
||
|
self.memo[self.c_weather] = nil
|
||
|
|
||
|
self:Refresh()
|
||
|
self:MSG("Cleared memory and all modified moments!")
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:OnBTN_Clear_Moment()
|
||
|
local memo = self:CurrentMoment()
|
||
|
if (not memo) then
|
||
|
self:Print("OnBTN_Clear_Moment | Can't find cache for file: %s - hour: %s - minute: %s", self.c_weather, self.c_hour, self.c_minute)
|
||
|
return
|
||
|
end
|
||
|
|
||
|
if (memo.defined == false) then
|
||
|
self.memo[self.c_weather][self.c_hour][self.c_minute] = nil
|
||
|
|
||
|
self:Refresh(true)
|
||
|
self:MSG("Reset moment for file: %s - hour: %s - minute: %s", self.c_weather, self.c_hour, self.c_minute)
|
||
|
else
|
||
|
self:MSG("Can't reset unmodified moment[%s:%s]", self.c_hour, self.c_minute)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:OnBTN_Exit()
|
||
|
self:Close()
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:OnKeyboard(dik, keyboard_action)
|
||
|
local res = CUIScriptWnd.OnKeyboard(self,dik,keyboard_action)
|
||
|
if (res == false) then
|
||
|
local bind = dik_to_bind(dik)
|
||
|
if keyboard_action == ui_events.WINDOW_KEY_RELEASED then
|
||
|
if (dik == D_JUMP3) or (dik == D_JUMP2) then
|
||
|
self.jump = jump_1
|
||
|
end
|
||
|
|
||
|
elseif keyboard_action == ui_events.WINDOW_KEY_PRESSED then
|
||
|
if (dik == D_JUMP3) then
|
||
|
self.jump = jump_3
|
||
|
|
||
|
elseif (dik == D_JUMP2) then
|
||
|
self.jump = jump_2
|
||
|
|
||
|
elseif (dik == D_VAL_ADD) then
|
||
|
self:SwitchValue(true)
|
||
|
|
||
|
elseif (dik == D_VAL_SUB) then
|
||
|
self:SwitchValue(false)
|
||
|
|
||
|
elseif (dik == D_VALG_ADD) then
|
||
|
self:SwitchValueGroup(true)
|
||
|
|
||
|
elseif (dik == D_VALG_SUB) then
|
||
|
self:SwitchValueGroup(false)
|
||
|
|
||
|
elseif (dik == D_MOVE_UP) then
|
||
|
self:SwitchParam(false, true)
|
||
|
|
||
|
elseif (dik == D_MOVE_DOWN) then
|
||
|
self:SwitchParam(true, true)
|
||
|
|
||
|
elseif (dik == D_MOVE_RIGHT) then
|
||
|
self:SwitchParam(true, false)
|
||
|
|
||
|
elseif (dik == D_MOVE_LEFT) then
|
||
|
self:SwitchParam(false, false)
|
||
|
|
||
|
elseif (dik == D_HOUR_ADD) then
|
||
|
local h = self.c_hour + (self.jump == jump_2 and 3 or self.jump == jump_2 and 6 or 1)
|
||
|
self:On_Time( self:ReviseTime(h, self.c_minute) )
|
||
|
|
||
|
elseif (dik == D_HOUR_SUB) then
|
||
|
local h = self.c_hour - (self.jump == jump_2 and 3 or self.jump == jump_2 and 6 or 1)
|
||
|
self:On_Time( self:ReviseTime(h, self.c_minute) )
|
||
|
|
||
|
elseif (dik == D_MIN_ADD) then
|
||
|
local m = self.c_minute + (self.jump == jump_2 and 5 or self.jump == jump_2 and 10 or 1)
|
||
|
self:On_Time( self:ReviseTime(self.c_hour, m) )
|
||
|
|
||
|
elseif (dik == D_MIN_SUB) then
|
||
|
local m = self.c_minute - (self.jump == jump_2 and 5 or self.jump == jump_2 and 10 or 1)
|
||
|
self:On_Time( self:ReviseTime(self.c_hour, m) )
|
||
|
|
||
|
elseif (dik == D_MOMENT_ADD) or (dik == D_MOMENT_SUB) then
|
||
|
local ts, te = self:GetNearestMoment(self.memo[self.c_weather], self.c_hour, self.c_minute)
|
||
|
if (dik == D_MOMENT_ADD) and te.h and te.m then
|
||
|
self:On_Time( self:ReviseTime(te.h, te.m) )
|
||
|
elseif (dik == D_MOMENT_SUB) and ts.h and ts.m then
|
||
|
self:On_Time( self:ReviseTime(ts.h, ts.m) )
|
||
|
end
|
||
|
|
||
|
elseif (dik == D_COPY) then
|
||
|
if self.jump == jump_3 then
|
||
|
self:OnBTN_Copy()
|
||
|
else
|
||
|
self:OnBTN_Copy_Param()
|
||
|
end
|
||
|
|
||
|
elseif (dik == D_PASTE) then
|
||
|
if self.jump == jump_3 then
|
||
|
self:OnBTN_Paste()
|
||
|
else
|
||
|
self:OnBTN_Paste_Param()
|
||
|
end
|
||
|
|
||
|
elseif (dik == D_VIEWER) and (not self.dialog_v:IsShown()) then
|
||
|
self:Viewer_Start()
|
||
|
|
||
|
elseif (dik == D_CLEAR) then
|
||
|
if self.jump == jump_3 then
|
||
|
self:OnBTN_Clear()
|
||
|
else
|
||
|
self:OnBTN_Clear_Moment()
|
||
|
end
|
||
|
|
||
|
elseif (dik == D_HELP) then
|
||
|
self:OnBTN_Help()
|
||
|
|
||
|
elseif (dik == DIK_keys.DIK_ESCAPE) then
|
||
|
if self.dialog_v:IsShown() then
|
||
|
self:Viewer_Exit()
|
||
|
else
|
||
|
self:Close()
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
return res
|
||
|
end
|
||
|
|
||
|
-- Functionality
|
||
|
function WeatherEditor:CurrentMoment()
|
||
|
local w = self.c_weather
|
||
|
local h = self.c_hour
|
||
|
local m = self.c_minute
|
||
|
return self.memo[w] and self.memo[w][h] and self.memo[w][h][m]
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:Apply(par, typ, memo)
|
||
|
|
||
|
local val = memo[par][1]
|
||
|
if (not val) then
|
||
|
self:Print("Apply | MISSING VALUE | par: %s - typ: %s", par, typ)
|
||
|
return
|
||
|
end
|
||
|
|
||
|
if (not self:IsList(typ)) and (type(val) ~= "number") then
|
||
|
self:Print("Apply | INCORRECNT VALUE TYPE | par: %s - typ: %s", par, typ)
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local cnt = self.idx_p[par]
|
||
|
|
||
|
if self:IsList(typ) then
|
||
|
local path = parameters[par].path or ""
|
||
|
local str = val
|
||
|
self.par[ self.idx_g[cnt][1] ]:SetText(val)
|
||
|
if (typ == 4) then
|
||
|
self:Reset_FolderList(self.idx_g[cnt][1], par, val, memo[par][2])
|
||
|
|
||
|
local val_2 = memo[par][2]
|
||
|
self.par[ self.idx_g[cnt][2] ]:SetText(val_2)
|
||
|
str = val .. val_2
|
||
|
end
|
||
|
weather.set_value_string(par, path .. str)
|
||
|
|
||
|
elseif (typ == 1) then
|
||
|
weather.set_value_numric(par,val)
|
||
|
self.par[ self.idx_g[cnt][1] ]:SetText(val)
|
||
|
elseif (typ == 2) then
|
||
|
local val_2 = memo[par][2]
|
||
|
local val_3 = memo[par][3]
|
||
|
if (type(val_2) == "number") and (type(val_3) == "number") then
|
||
|
weather.set_value_vector(par, val, val_2, val_3)
|
||
|
self.par[ self.idx_g[cnt][1] ]:SetText(val)
|
||
|
self.par[ self.idx_g[cnt][2] ]:SetText(val_2)
|
||
|
self.par[ self.idx_g[cnt][3] ]:SetText(val_3)
|
||
|
end
|
||
|
elseif (typ == 3) then
|
||
|
local val_2 = memo[par][2]
|
||
|
local val_3 = memo[par][3]
|
||
|
local val_4 = memo[par][4]
|
||
|
if (type(val_2) == "number") and (type(val_3) == "number") and (type(val_4) == "number") then
|
||
|
weather.set_value_vector(par, val, val_2, val_3, val_4)
|
||
|
self.par[ self.idx_g[cnt][1] ]:SetText(val)
|
||
|
self.par[ self.idx_g[cnt][2] ]:SetText(val_2)
|
||
|
self.par[ self.idx_g[cnt][3] ]:SetText(val_3)
|
||
|
self.par[ self.idx_g[cnt][4] ]:SetText(val_4)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:LerpMoment(f, h, m)
|
||
|
local ts, te = self:GetNearestMoment(self.memo[f], h, m)
|
||
|
local ps = ts and self.memo[f][ts.h] and self.memo[f][ts.h][ts.m]
|
||
|
local pe = te and self.memo[f][te.h] and self.memo[f][te.h][te.m]
|
||
|
if ps and pe then
|
||
|
if (not self.memo[f][h]) then self.memo[f][h] = {} end
|
||
|
if (not self.memo[f][h][m]) then self.memo[f][h][m] = {} end
|
||
|
self.memo[f][h][m] = self:Lerp(h, m, ts, te, ps, pe)
|
||
|
self:Print("LerpMoment | file: %s - hour: %s - minute: %s", f, h, m)
|
||
|
return self.memo[f][h][m]
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:Lerp(h, m, ts, te, ps, pe)
|
||
|
local t = {}
|
||
|
local min_range = ((te.h - ts.h) * 60) + (te.m - ts.m)
|
||
|
local min_mid = ((h - ts.h) * 60) + (m - ts.m)
|
||
|
local min_ratio = min_mid/min_range
|
||
|
|
||
|
--local par = "ambient_color"
|
||
|
--local v = parameters[par]
|
||
|
for par,v in pairs(parameters) do
|
||
|
t[par] = {}
|
||
|
for i=1,#ps[par] do
|
||
|
if self:IsList(v.typ) then
|
||
|
t[par][i] = ps[par][i]
|
||
|
else
|
||
|
local val = ps[par][i] + ((pe[par][i] - ps[par][i]) * min_ratio)
|
||
|
t[par][i] = round_idp(val, precision)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
return t
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:ClearMomentsInRange(f, hh, mm)
|
||
|
local ts, te = self:GetNearestMoment(self.memo[f], hh, mm)
|
||
|
local h1 = ts.h
|
||
|
local h2 = te.h
|
||
|
local m_t = {}
|
||
|
|
||
|
if (h1 == h2) then
|
||
|
m_t[h1] = { s = ts.m , e = te.m }
|
||
|
else
|
||
|
for h = h1, h2 do
|
||
|
m_t[h] = (h == h1) and { s = ts.m , e = 59 } or (h == h2) and { s = 0 , e = te.m } or { s = 0 , e = 59 }
|
||
|
end
|
||
|
end
|
||
|
|
||
|
for h = h1, h2 do
|
||
|
for m = m_t[h].s, m_t[h].e do
|
||
|
local memo = self.memo[f][h] and self.memo[f][h][m]
|
||
|
if memo and memo.defined == nil then
|
||
|
if (h ~= hh) or (h == hh and m ~= mm) then
|
||
|
self.memo[f][h][m] = nil
|
||
|
self:Print("ClearMomentsInRange | for [%s][%s][%s] | [%s][%s] is cleared", f, hh, mm, h, m)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:GetTimeRange(t)
|
||
|
local s,e = {},{}
|
||
|
for h,v in spairs(t, func_small) do
|
||
|
for m,vv in spairs(v, func_small) do
|
||
|
if (vv.defined == true) then
|
||
|
if (not s.h) then
|
||
|
s.h = h
|
||
|
s.m = m
|
||
|
end
|
||
|
e.h = h
|
||
|
e.m = m
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
self:Print("GetTimeRange | START: h(%s) m(%s) | END: h(%s) m(%s)", s.h, s.m, e.h, e.m )
|
||
|
return { s=s , e=e }
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:GetNearestMoment(t, hh, mm)
|
||
|
local ts, te = { h = 0 , m = 0 }, { h = 23 , m = 59 }
|
||
|
local v, found
|
||
|
|
||
|
-- Searching for nearest previous moment
|
||
|
for h=0,hh do
|
||
|
for m=0,59 do
|
||
|
v = t[h] and t[h][m]
|
||
|
if (v and v.defined ~= nil) and ((h < hh) or (h == hh and m < mm)) then
|
||
|
ts.h = h
|
||
|
ts.m = m
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Searching for nearest next moment
|
||
|
for h=hh,23 do
|
||
|
for m=0,59 do
|
||
|
v = t[h] and t[h][m]
|
||
|
if (v and v.defined ~= nil) and ((h > hh) or (h == hh and m > mm)) then
|
||
|
found = true
|
||
|
te.h = h
|
||
|
te.m = m
|
||
|
end
|
||
|
if found then break end
|
||
|
end
|
||
|
if found then break end
|
||
|
end
|
||
|
|
||
|
-- Rotate on range limit
|
||
|
if (ts.h == 0) and (ts.m == 0) then
|
||
|
ts = dup_table(self.range.e)
|
||
|
end
|
||
|
if (te.h == 23) and (te.m == 59) then
|
||
|
te = dup_table(self.range.s)
|
||
|
end
|
||
|
|
||
|
--self:Print("GetNearestMoment h(%s) m(%s) | previous: h(%s) m(%s) | next: h(%s) m(%s)", hh, mm, ts.h, ts.m, te.h, te.m )
|
||
|
return ts, te
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:SwitchParam(state, vert)
|
||
|
|
||
|
local function get_param_index(state, vert)
|
||
|
|
||
|
--// Vertical movement - Move between parameters
|
||
|
if vert then
|
||
|
local jumps = ((self.jump == jump_3) and 3) or ((self.jump == jump_2) and 2) or 1
|
||
|
|
||
|
if state then
|
||
|
self.select_g = self.select_g + jumps
|
||
|
else
|
||
|
self.select_g = self.select_g - jumps
|
||
|
end
|
||
|
|
||
|
if (self.select_g > #self.idx_g) then
|
||
|
self.select_g = 1
|
||
|
elseif (self.select_g < 1) then
|
||
|
self.select_g = #self.idx_g
|
||
|
end
|
||
|
|
||
|
return self.idx_g[self.select_g][1]
|
||
|
|
||
|
--// Horizental movement - Move inside a parameter
|
||
|
else
|
||
|
local group = self.idx_g[self.select_g]
|
||
|
if group then
|
||
|
local first = group[1]
|
||
|
local last = group[#group]
|
||
|
if state and (self.select < last) then
|
||
|
self.select = self.select + 1
|
||
|
elseif (not state) and (self.select > first) then
|
||
|
self.select = self.select - 1
|
||
|
end
|
||
|
else
|
||
|
printe("! group doesn't exist for selecte_g: %s", self.select_g)
|
||
|
end
|
||
|
return self.select
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Move highlight
|
||
|
self.par_hl[self.select]:Show(false)
|
||
|
self.select = get_param_index(state, vert)
|
||
|
self.par_hl[self.select]:Show(true)
|
||
|
|
||
|
-- Scroll to highlighted button
|
||
|
self:ScrollToElement(self.select)
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:SwitchValue(state, idx, ignore)
|
||
|
local idx = idx or self.select
|
||
|
local par = self.parent[idx]
|
||
|
local i = self.idx_i[idx]
|
||
|
local typ = self.type[idx]
|
||
|
local memo = self:CurrentMoment()
|
||
|
local val = memo[par][i]
|
||
|
|
||
|
local val_n
|
||
|
if (not self:IsList(typ)) then
|
||
|
local min_val = parameters[par].min
|
||
|
local max_val = parameters[par].max
|
||
|
local step = parameters[par].step * self.jump
|
||
|
val = state and (val + step) or (val - step)
|
||
|
val_n = clamp(val, min_val, max_val)
|
||
|
else
|
||
|
if not (self.list_n[idx]) then
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local index
|
||
|
local list = self.list_n[idx]
|
||
|
for i=1,#list do
|
||
|
if list[i] == val then
|
||
|
index = i
|
||
|
break
|
||
|
end
|
||
|
end
|
||
|
if (not index) then
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local list_size = #list
|
||
|
index = state and (index + 1) or (index - 1)
|
||
|
if index > list_size then
|
||
|
index = 1
|
||
|
elseif index < 1 then
|
||
|
index = list_size
|
||
|
end
|
||
|
|
||
|
local txt = list[index]
|
||
|
if self:IsInvalidValue(idx, 0, txt) then
|
||
|
self:MSG("%c[pda_red]Invalid path/section for parameter (%s)", self.name[idx])
|
||
|
return
|
||
|
end
|
||
|
|
||
|
val_n = txt
|
||
|
end
|
||
|
|
||
|
if val_n then
|
||
|
self:On_Param(idx, val_n, ignore)
|
||
|
else
|
||
|
self:MSG("%c[pda_red]No value can be set for (%s)",self.name[idx])
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:SwitchValueGroup(state)
|
||
|
local group = self.idx_g[self.select_g]
|
||
|
local size = (#group > 3) and 3 or #group -- no need for alpha value
|
||
|
for i=1,size do
|
||
|
self:SwitchValue(state, group[i], true)
|
||
|
end
|
||
|
self:Refresh(true)
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:ReviseTime(h,m)
|
||
|
if m > 59 then
|
||
|
m = m - 60
|
||
|
h = h + 1
|
||
|
elseif m < 0 then
|
||
|
m = m + 60
|
||
|
h = h - 1
|
||
|
end
|
||
|
|
||
|
if h > 23 then
|
||
|
h = h - 24
|
||
|
elseif h < 0 then
|
||
|
h = h + 24
|
||
|
end
|
||
|
|
||
|
return h, m
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:HasChanges()
|
||
|
local cnt = 0
|
||
|
for h,v1 in pairs(self.memo[self.c_weather]) do
|
||
|
for m,v2 in pairs(v1) do
|
||
|
if v2.defined == false then
|
||
|
cnt = cnt + 1
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
return cnt
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:SaveToFile()
|
||
|
local is_new = false
|
||
|
local file_name = self.input_preset:GetText()
|
||
|
if not (file_name and file_name ~= "") then
|
||
|
file_name = self.c_weather
|
||
|
else
|
||
|
local str_w = string.sub(file_name,1,2)
|
||
|
local is_w = (str_w == "w_")
|
||
|
if not (is_w) then
|
||
|
self:MSG("%c[pda_red]Incorrect name pattern!\\n%c[ui_gray_1]Naming pattern: w_(custom_name)")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
is_new = true
|
||
|
for i=1,#self.weather_files do
|
||
|
local file = self.weather_files[i]
|
||
|
if file == file_name then
|
||
|
is_new = false
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
local path = dir .. file_name .. ".ltx"
|
||
|
|
||
|
local ltx = ini_file_ex(path, true)
|
||
|
if (not ltx) then
|
||
|
self:MSG("%c[pda_red]No file found or created!")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local modified = false
|
||
|
for h,v1 in spairs(self.memo[self.c_weather], func_small) do
|
||
|
for m,v2 in spairs(v1, func_small) do
|
||
|
if is_new and (v2.defined == true) or (v2.defined == false) then
|
||
|
for par,v in pairs(parameters) do
|
||
|
if v2[par] then
|
||
|
local val
|
||
|
if (v.typ == 2) then
|
||
|
val = v2[par][1] .. "," .. v2[par][2] .. "," .. v2[par][3]
|
||
|
elseif (v.typ == 3) then
|
||
|
val = v2[par][1] .. "," .. v2[par][2] .. "," .. v2[par][3] .. "," .. v2[par][4]
|
||
|
elseif (v.typ == 4) then
|
||
|
val = (v.path or "") .. v2[par][1] .. v2[par][2]
|
||
|
else
|
||
|
val = v2[par][1]
|
||
|
end
|
||
|
|
||
|
local section = self:TimeToString(h,m)
|
||
|
ltx:w_value(section, par, val)
|
||
|
modified = true
|
||
|
self:Print("OnBTN_Save | new file? %s - file name: %s | section: %s - parameter: %s - value: %s", is_new, path, section, par, val)
|
||
|
else
|
||
|
self:Print("OnBTN_Save | ERROR can't find modified parameter value [%s]", par)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if (not modified) then
|
||
|
self:MSG("Saved%sfile: nothing is modified for [%s] yet?", is_new and " new " or " ", file_name)
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- Save to ltx
|
||
|
ltx:save()
|
||
|
self:MSG("Saved%sfile: %s\\nCheck it under weather's directory: %s", is_new and " new " or " ", file_name, dir)
|
||
|
|
||
|
-- Force reloading file and clearning all temp values
|
||
|
if (is_new) then
|
||
|
self.memo[self.c_weather] = nil
|
||
|
local id = #self.weather_files + 1
|
||
|
self.weather_files[id] = file_name
|
||
|
self:Reset()
|
||
|
-- self.list_weather:SetCurrentID(id)
|
||
|
self.list_weather:SetCurrentIdx(id)
|
||
|
self:On_Weather()
|
||
|
else
|
||
|
self.memo[self.c_weather] = nil
|
||
|
self:Refresh()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:Discard()
|
||
|
end
|
||
|
|
||
|
-- Utilities
|
||
|
local indx_str = {
|
||
|
[1] = "_r",
|
||
|
[2] = "_g",
|
||
|
[3] = "_b",
|
||
|
[4] = "_a",
|
||
|
}
|
||
|
function WeatherEditor:GetStringByType(indx,typ)
|
||
|
if (typ == 0) or (typ == 1) then
|
||
|
return ""
|
||
|
else
|
||
|
return indx_str[indx]
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:IsList(typ)
|
||
|
return (typ == 0) or (typ == 4)
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:AddToList(par, indx, cnt, value)
|
||
|
cnt[#cnt + 1] = true
|
||
|
self.par[indx]:AddItem(value, #cnt)
|
||
|
|
||
|
if (not self.list[indx]) then self.list[indx] = {} end
|
||
|
if (not self.list_n[indx]) then self.list_n[indx] = {} end
|
||
|
|
||
|
self.list[indx][value] = true
|
||
|
self.list_n[indx][#self.list_n[indx] + 1] = value
|
||
|
self:Print("Reset | Filling list [%s] | self.list[%s] = %s", par, indx, value)
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:Reset_FolderList(indx, par, val, val_2)
|
||
|
self:Print("Reset | Reset_FolderList | indx: %s - par: %s - val: %s - val_2: %s", indx, par, val, val_2)
|
||
|
|
||
|
indx = indx + 1 -- we need the child list (files)
|
||
|
local folder = self.folder[par][val]
|
||
|
if folder and self.par[indx] and (val ~= self.folder_last[par]) then
|
||
|
self.folder_last[par] = val
|
||
|
self.par[indx]:ClearList()
|
||
|
empty_table(self.list[indx])
|
||
|
empty_table(self.list_n[indx])
|
||
|
|
||
|
local cnt = {}
|
||
|
for file_name,_ in pairs(folder) do
|
||
|
self:AddToList(par, indx, cnt, file_name)
|
||
|
end
|
||
|
|
||
|
local val_f = self.list_n[indx][1]
|
||
|
self.par[indx]:SetText(val_f or "")
|
||
|
|
||
|
if (not self.list[indx][val_2]) then
|
||
|
local memo = self:CurrentMoment()
|
||
|
memo[par][2] = self.list_n[indx][1]
|
||
|
self:Print("Reset | Reset_FolderList | file %s\\%s doesn't exist, use first path %s\\%s", val, val_2, val, memo[par][2])
|
||
|
end
|
||
|
self:Print("Reset | Reset_FolderList | updated self.par[%s] = %s", indx, val_f)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:StringToTime(str)
|
||
|
local t = str_explode(str,":")
|
||
|
return tonumber(t[1]), tonumber(t[2])
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:TimeToString(h,m)
|
||
|
if h < 10 then
|
||
|
h = "0" .. h
|
||
|
end
|
||
|
if m < 10 then
|
||
|
m = "0" .. m
|
||
|
end
|
||
|
return (h .. ":" .. m .. ":00")
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:ParseFromString(ltx, sec, par, typ)
|
||
|
local t = parse_list(ltx, sec, par)
|
||
|
if typ == 4 and t[1] then
|
||
|
local p = str_explode(t[1],"\\")
|
||
|
local file = p[#p] or ""
|
||
|
local folder = ""
|
||
|
for i=1,#p-1 do
|
||
|
folder = folder .. p[i] .. "\\"
|
||
|
end
|
||
|
folder = string_gsub(folder, parameters[par].path, "")
|
||
|
t = { folder , file }
|
||
|
|
||
|
elseif (not self:IsList(typ)) then
|
||
|
for i=1,#t do
|
||
|
t[i] = tonumber(t[i])
|
||
|
end
|
||
|
elseif (not t[1]) then
|
||
|
t[1] = ""
|
||
|
end
|
||
|
return t
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:IsInvalidValue(idx, typ, val)
|
||
|
|
||
|
-- Strings
|
||
|
if self:IsList(typ) then
|
||
|
if val == "" then
|
||
|
return false -- it's ok for strings to be empty
|
||
|
elseif val and self.list[idx][val] then
|
||
|
return false
|
||
|
else
|
||
|
return true -- value that doesn't exist in the list
|
||
|
end
|
||
|
|
||
|
-- Numbers
|
||
|
elseif not (val and val ~= "" and tonumber(val)) then
|
||
|
return true -- not number
|
||
|
end
|
||
|
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:ScrollToElement(idx)
|
||
|
if (not idx) then
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local par = self.parent[idx]
|
||
|
local cnt = self.idx_p[par]
|
||
|
local ele = idx and self.st[cnt]
|
||
|
if (not ele) then
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local h = self.scroll_par:GetHeight()
|
||
|
local curr_pos = self.scroll_par:GetCurrentScrollPos()
|
||
|
local ele_pos = ele:GetWndPos().y
|
||
|
if (ele_pos < curr_pos) or (ele_pos >= curr_pos + h) then
|
||
|
self.scroll_par:SetScrollPos( clamp(ele_pos, self.scroll_par:GetMinScrollPos(), self.scroll_par:GetMaxScrollPos()) )
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Final
|
||
|
function WeatherEditor:PauseEngine(state)
|
||
|
-- When we want to work on Weather Editor, then engine must stop calculating weather changes by time
|
||
|
|
||
|
if (state == true) and (not weather.is_paused()) then
|
||
|
weather.pause(true)
|
||
|
|
||
|
elseif (state == false) and (weather.is_paused()) then
|
||
|
weather.pause(false)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:Close()
|
||
|
self:HideDialog()
|
||
|
self:Show(false)
|
||
|
|
||
|
Unregister_UI("WeatherEditor")
|
||
|
|
||
|
if (level.present()) then
|
||
|
printf("- main_menu off")
|
||
|
exec_console_cmd("main_menu off")
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:SetHint(text,cl)
|
||
|
if (text == "") then
|
||
|
return
|
||
|
end
|
||
|
self.hint_wnd:Show(true)
|
||
|
self.hint_wnd_text:SetText(text)
|
||
|
self.hint_wnd_text:AdjustHeightToText()
|
||
|
self.hint_wnd_text:SetTextColor( (cl == true and clr_list["saved"]) or (cl == false and clr_list["temp"]) or clr_list["def"] )
|
||
|
|
||
|
local w = self.hint_wnd:GetWidth()
|
||
|
w = w >= 96 and w or 96
|
||
|
local h = self.hint_wnd_text:GetHeight()+44
|
||
|
h = h >= 96 and h or 96
|
||
|
self.hint_wnd:SetWndSize(vector2():set(w,h))
|
||
|
|
||
|
local pos = GetCursorPosition()
|
||
|
pos.y = pos.y - self.hint_wnd:GetHeight()
|
||
|
pos.x = pos.x - self.hint_wnd:GetWidth()
|
||
|
self.hint_wnd:SetWndPos(pos)
|
||
|
|
||
|
FitInRect(self.hint_wnd,Frect():set(0,0,1024,768),0,100)
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:MSG(fmt,...)
|
||
|
local str = strformat(fmt,...)
|
||
|
|
||
|
self.msg_wnd:Show(true)
|
||
|
self.msg_wnd_text:SetText(str)
|
||
|
self.msg_wnd_text:AdjustHeightToText()
|
||
|
self.msg_wnd_text:SetWndSize(vector2():set(self.msg_width, self.msg_wnd_text:GetHeight()+10))
|
||
|
self.msg_wnd_text:SetWndPos(vector2():set(0,20))
|
||
|
|
||
|
self.msg_wnd:SetWndSize(vector2():set(self.msg_width, self.msg_wnd_text:GetHeight()+44))
|
||
|
self.msg_wnd:SetWndPos(vector2():set( self.dialog:GetWidth() , (self.hight - self.msg_wnd:GetHeight()) ))
|
||
|
|
||
|
self.msg_wnd_timer = time_global() + 4000
|
||
|
end
|
||
|
|
||
|
function WeatherEditor:Print(fmt, ...)
|
||
|
if self.debug then
|
||
|
printf("WeatherEditor | " .. fmt, ...)
|
||
|
end
|
||
|
end
|