Code:
local _G = _G
local internal = debug.getregistry()
local msg = debug.Message
local floor = math.floor
local RGB = color.RGB
local print = print
local Message = Message
local type = type
local unpack = unpack
local error = error
local pairs = pairs
local sortpairs = sortpairs
local next = next
local ipairs = ipairs
local tonumber = tonumber
local tostring = tostring
local tostring2 = tostring2
local rawget = rawget
local rawset = rawset
local getmetatable = getmetatable
local setmetatable = setmetatable
local setmetatableW = internal.setmetatableW
local getfenv = getfenv
local setfenv = setfenv
local pcall = pcall
local assert = assert
local format = string.format
local string_lower = string.lower
local string_find = string.find
local table_copy = table.copy
local table_concat = table.concat
local ScreenWidth = ScreenWidth
local ScreenHeight = ScreenHeight
local GetKeyState = internal.GetKeyState
local d_dialogs = dialogs
local d_new = dialogs.new
local d_Text = dialogs.Text
local d_Button = dialogs.Button
local d_Pcx = dialogs.Pcx
local d_ScrollBar = dialogs.ScrollBar
local d_AlignH = dialogs.AlignH
local d_AlignV = dialogs.AlignV
local d_AlignLayers = dialogs.AlignLayers
local d_CheckGroup = dialogs.CheckGroup
local d_CheckBox = dialogs.CheckBox
local d_Frame = dialogs.Frame
local d_MainMenuButton = dialogs.MainMenuButton
local dofile = dofile
----------- No globals from this point ------------
local _NOGLOBALS
---------------------------------------------------
local OptionMods = internal.OptionMods
local OptionDefs = internal.OptionDefs
-- local ErmDefs = {}
-- local Defaults = {}
--local Options = internal.Options
local BlueStyle = nil
local FillColor = BlueStyle and RGB(20, 20, 54) or RGB(102, 72, 54)
local BorderLColor = BlueStyle and RGB(99, 113, 173) or 33574
local BorderSColor = BlueStyle and RGB(16, 32, 74) or 10434
local ItemFont --= "Small.fnt"
local CaptionFont = "MedFont.fnt"
local DlgF = {mod = "wog", cat = 1}
local function ModTagClick(t, cmd)
local g = t.Owner
local all = g[g.AllIndex]
local upd = {[t] = true}
if t == g.Cur or cmd.X < t.X + 22 then -- change check state
upd[t] = true
local last = t.IsOn
t.IsOn = not last
if t == all then -- 'All' item
if last then
for i = 2, g.Count do
local it = g[i]
upd[it] = (it.IsOn ~= last[i - 1] or nil)
it.IsOn = last[i - 1]
end
else
last = {}
t.IsOn = last
for i = 2, g.Count do
local it = g[i]
last[i - 1] = it.IsOn
upd[it] = not it.IsOn or nil
it.IsOn = true
end
end
elseif all and all.IsOn then -- normal item
all.IsOn = false
upd[all] = true
end
else -- select
if g.Cur and t ~= g.Cur then
local btn = g.Cur.Items.Button
btn.Frame = 0
btn:Redraw()
end
t.Items.Button.Frame = 1
g.Cur = t
end
for it in pairs(upd) do
local btn = it.Items.Button
btn.File = it.CheckDefs[it.IsOn and 2 or 1]
btn:Redraw()
end
g:OnStateChanged()
end
local function BuildDlg()
return d_new(table_copy(DlgF, {ExpandWidth = 1, ExpandHeight = 1,
Border = true,
BorderHint = true,
PlayerColor = BlueStyle and 1,
ShowLongHints = true,
DropShadow = false,
BackgroundPcx = BlueStyle and "DiBoxBlu.pcx",
OnKeyUp = function(t, cmd)
cmd.CloseDialog = cmd.Key == 1
end,
d_AlignV{Name = "Outer",
Width = ScreenWidth, Height = ScreenHeight, Margin = 25, SpaceY = 10, MarginTop = 28, MarginBottom = 45,
AlignX = 0.5, AlignY = 0.5,
-- d_Text{Text = "WoGify Options", Font = "BigFont.fnt", Color = 19},
-- 12,
d_AlignH{ExpandWidth = 1, ExpandHeight = 1, SpaceX = 6,
d_AlignV{ExpandHeight = 1, SpaceX = 1, Width = 210, SpaceY = 4, AlignX = 0.5,
d_Text{Name = "ModsCaption", Font = CaptionFont, Color = 19, ExpandWidth = 1,
Text = "Mods", Hint = "Mods List", LongHint = "MODS LIST\n\nInfo",
}, -- !!! localize
d_AlignH{ExpandWidth = 1,
d_CheckGroup{Name = "ModsGroup",
BorderHeight = 8,
-- Texts = {"In The Wake Of Gods", "Horn Of The Abyss", "Master Of Puppets"},
Border = true,
--CloseDialog = true,
ExpandWidth = 1, MarginTop = -1, MarginBottom = -1,
-- MinWidth = 0, ItemsAutoHeight = true,
--ScrollBar = "Scroll",
Radio = true,
FillColor = FillColor,
BorderLColor = BorderLColor,
BorderSColor = BorderSColor,
Font = ItemFont,
-- States = 1,
-- OnClick = ModTagClick,
OnClick = function(it)
local dlg = it.Parent
dlg.mod = dlg.mods[it.Index]
dlg.NoRedraw = true
dlg:updateCats()
dlg.NoRedraw = false
dlg:Redraw()
end
},
d_ScrollBar{Name = "ScrollMods", ExpandHeight = 1, Blue = BlueStyle},
},
17,
d_Text{Name = "CatsCaption", Font = CaptionFont, Color = 19, ExpandWidth = 1, Visible = false,
Text = "Category", Hint = "Categories list", LongHint = "CATEGORIES LIST\n\nInfo",
}, -- !!! localize
d_AlignH{ExpandWidth = 1, ExpandHeight = 1,
d_CheckGroup{Name = "CatsGroup",
BorderHeight = 8,
-- Texts = {"All!", "Combat", "Interface", "Stupid", "Multiplayer"},
Border = true,
--CloseDialog = true,
ExpandWidth = 1, MarginTop = -1, MarginBottom = -1,
ScrollBar = "ScrollCats",
Radio = true,
FillColor = FillColor,
BorderLColor = BorderLColor,
BorderSColor = BorderSColor,
Font = ItemFont,
OnClick = function(it)
local dlg = it.Parent
dlg.cat = it.Index
dlg.NoRedraw = true
dlg:updateOptions()
dlg.NoRedraw = false
dlg:Redraw()
end
-- AllIndex = 1,
},
d_ScrollBar{Name = "ScrollCats", ExpandHeight = 1, Visible = false, Blue = BlueStyle},
},
},
d_AlignV{Name = "OptionsOuter", ExpandWidth = 1, ExpandHeight = 1, MinWidth = 0,
d_AlignH{Name = "Options",
ExpandWidth = 1, ExpandHeight = 1, SpaceX = 3, SpaceY = 0,
MinWidth = 0,
ScrollBar = "Scroll",
FullPageScroll = true,
},
d_ScrollBar{Name = "Scroll", CatchKeys = true, ExpandWidth = 1, Visible = false, Blue = BlueStyle},
},
},
d_AlignH{SpaceX = 16,
d_AlignLayers{AlignX = 0.5, AlignY = 0.5,
d_Pcx{File = "box64x30.pcx"},
d_Button{Name = "OK", File = "iokay.def", CloseDialog = true, Id = 30722, HotKey = 28},
},
d_AlignLayers{AlignX = 0.5, AlignY = 0.5,
d_Pcx{File = "box64x30.pcx"},
d_Button{File = "icancel.def", CloseDialog = true, Id = 30721, HotKey = 1},
},
},
},
}, true))
end
function DlgF.OnRightClick(dlg, cmd)
local it = cmd.Item
local h = it and (it.LongHint or it.Hint)
if h ~= nil and h ~= "" then
cmd.DefaultAction = false
if GetKeyState(0x10) < 0 or GetKeyState(0x11) < 0 or GetKeyState(0x12) < 0 then
Message(h)
else
Message(h, 4)
end
end
if cmd.Item then
local h = it.LongHint or it.Hint
end
end
local function UpdateColor(group)
for i = 1, group.Count do
local it = group.Items[i]
it.TextColor = it.On and 1 or 10
end
end
local function UpdateCheckColor(it)
it.TextColor = it.On and 1 or 10
end
function DlgF.clickItem(dlg, it, def, valIndex)
if not it.Active then -- safeguard
return
end
local v = it.On
if valIndex then
v = def.Values[valIndex].Value
-- UpdateColor(it.Owner)
-- else
-- UpdateCheckColor(it)
end
-- dlg:Redraw()
internal.SetupOptions(internal.NewOptionsTable{[def.Name] = v})
end
function DlgF.checkOptionValue(dlg, option, value)
return internal.CurOptions.Active[option] == value
end
function DlgF.updateAll(dlg)
local group = dlg.Items.ModsGroup
local scroll = dlg.Items.ScrollMods
local texts = {}
local hints = {}
local lhints = {}
local mods = {}
local i = 1
local sel = 1
for mod, defs in sortpairs(OptionMods) do
local opt = OptionDefs[mod..".Enabled"]
texts[i] = opt.Text
hints[i] = opt.Hint or texts[i]
lhints[i] = opt.LongHint
mods[i] = mod
if mod == dlg.mod then
sel = i
end
i = i + 1
end
local h = scroll.Height + dlg.Items.ScrollCats.Height
group.Texts = texts
group.Hints = hints
group.LongHints = lhints
if texts[1] then
group.Items[sel].On = true
dlg.mod = mods[sel]
end
dlg.mods = mods
local need = group.Height > 1/2*h
if need then
group.AutoHeight = false
local h = (scroll.Height + dlg.Items.ScrollCats)*2/5
local it = group[1]
group.Height = h - h % (it.Items.Text:GetHeight(0x7FFF) + it.BorderHeight)
-- !!! scroll to selected item
end
scroll.Visible = need
scroll.Active = need
group.Owner:Realign()
group.Owner.Owner:Realign()
dlg:updateCats()
end
function DlgF.updateCats(dlg)
UpdateColor(dlg.Items.ModsGroup)
dlg.cat = 1
local CatList = OptionMods[dlg.mod]
if not CatList then
return
end
local group = dlg.Items.CatsGroup
local scroll = dlg.Items.ScrollCats
local texts = {}
local hints = {}
local lhints = {}
for i, cat in ipairs(CatList) do
local cat = cat[0] or {}
texts[i] = cat.Text
hints[i] = cat.Hint or texts[i]
lhints[i] = cat.LongHint
end
group.Count = 0
group.AutoHeight = true
group.Texts = texts
group.Hints = hints
group.LongHints = lhints
if not texts[2] then
group.Count = 0
else
group.Items[1].On = true
end
local need = group.Height > scroll.Height
if need then
group.AutoHeight = false
group.Height = scroll.Height
end
scroll.Visible = need
scroll.Active = need
dlg.Items.CatsCaption.Visible = group.Count > 0
dlg:updateOptions()
end
function DlgF.updateOptions(dlg)
UpdateColor(dlg.Items.CatsGroup)
local options = OptionMods[dlg.mod][dlg.cat]
local BaseCaption = OptionDefs[dlg.mod..".Enabled"].Text
local Aligner = dlg.Items.Options
for i = #Aligner, 1, -1 do
Aligner[i]:Delete()
end
local FullItemWidth = 265
local GroupMargin = 2
local ItemBorderHeight = 6
local ItemWidth = FullItemWidth - GroupMargin*2
local ItemHeight
local ColWidth = FullItemWidth + Aligner.SpaceX
local CaptionSpace1 = 10 + GroupMargin
local CaptionSpace2 = 5 + GroupMargin
local CaptionHeight
do
local title = d_Text{Font = CaptionFont}
title:NeedSize()
CaptionHeight = title.Height + CaptionSpace2
local item = d_CheckBox{BorderHeight = ItemBorderHeight}
item:NeedSize()
ItemHeight = item.Height
end
local MinGroupOneLineCount = 3
local MinGroupCount = 2
local MinGroupHeight = ItemHeight*2.5
local ColHeight = Aligner.Height - GroupMargin
local MinColHeight = floor(Aligner.Height/2) + CaptionSpace1
local function GetColCount(list, colH, y)
local n = 1
for i, it in ipairs(list) do
y = y + it.H
if y > colH then
y, n = 0, n + 1
end
end
return n
end
local function PlaceItem(x, y, it)
it.X, it.Y = x + Aligner.X, y + Aligner.Y
it.StaticAlign = true
Aligner:AddItem(it)
end
local function PlaceGroup(x, y, group)
for i, it in ipairs(group) do
PlaceItem(it.X + x, it.Y + y, it)
end
end
local function PlaceBorder(x, y)
y = y - GroupMargin
local t = {
d_Frame{Width = FullItemWidth, Color = FillColor, Fill = true},
d_Frame{Width = FullItemWidth - 1, Color = BorderSColor},
d_Frame{Width = FullItemWidth - 1, Color = BorderLColor},
y
}
PlaceItem(x, y, t[1])
PlaceItem(x + 1, y + 1, t[2])
PlaceItem(x, y, t[3])
return t
end
local function SetBorderEnd(t, y)
if t then
local h = y + GroupMargin - t[4]
t[1].Height = h
t[2].Height = h - 1
t[3].Height = h - 1
end
end
local function PlaceItems(x, y, titleBase, list)
local title = d_Text(table_copy(titleBase))
title:NeedSize()
local titleH = title.Height + CaptionSpace2
local colH = ColHeight - titleH
if y >= MinColHeight and GetColCount(list, colH, y) > GetColCount(list, colH, 0) then
x, y = x + ColWidth, 0
end
local border
local NeedTitle = true
for i, it in ipairs(list) do
if y + it.H > colH then
SetBorderEnd(border, y + titleH)
x, y = x + ColWidth, 0
NeedTitle = true
end
if NeedTitle then
PlaceItem(x, y, title or d_Text(table_copy(titleBase)))
title, NeedTitle = nil, false
border = PlaceBorder(x, y + titleH)
end
PlaceGroup(x + GroupMargin, y + titleH, it)
y = y + it.H
end
SetBorderEnd(border, y + titleH)
return x, y + CaptionSpace1 + titleH
end
local function AddItem(g, it)
it.Y = g.H + it.Y
g.H = it.Y + it.Height
g[#g + 1] = it
end
local x, y = 0, 0
for ia, a in ipairs(options or {}) do
local list = {}
local group
local NeedHeight, NeedCount = MinGroupHeight, MinGroupCount
for _, b in ipairs(a) do
local item
if b.Text or not b.Values then
item = d_CheckBox{X = 0, Y = 0, Width = ItemWidth, BorderHeight = ItemBorderHeight,
Text = b.Text, Hint = b.Hint or b.Text, LongHint = b.LongHint, Font = ItemFont,
On = not dlg:checkOptionValue(b.Name, false),
OnClick = function(it, cmd)
return dlg:clickItem(it, b)
end,
}
-- UpdateCheckColor(item)
item:NeedSize()
end
if group and (NeedHeight > 0 or NeedCount > 0) then
NeedCount = NeedCount - 1
if item then
NeedHeight = NeedHeight - item.Height
end
else
group = {H = 0}
list[#list + 1] = group
end
if item then
AddItem(group, item)
end
if b.Values then
NeedHeight, NeedCount = 0, 0
local texts, hints, lhints = {}, {}, {}
for i, c in ipairs(b.Values) do
texts[i] = c.Text
hints[i] = c.Hint or c.Text
lhints[i] = c.LongHint
end
local cg = d_CheckGroup{BorderHeight = ItemBorderHeight, Radio = true,
Texts = texts, Hints = hints, LongHints = lhints, Width = ItemWidth, Font = ItemFont,
OnClick = function(it, cmd)
return dlg:clickItem(it, b, it.Index)
end,
}
for i = 1, #texts do
cg.Items[i].On = dlg:checkOptionValue(b.Name, b.Values[i].Value)
end
-- UpdateColor(cg)
cg:NeedSize()
AddItem(group, cg)
end
end
if #list > 0 then
local a0 = a[0] or {}
x, y = PlaceItems(x, y, {Text = a0.Text or BaseCaption, Hint = a0.Hint, LongHint = a0.LongHint,
Font = CaptionFont, Color = 19, Width = FullItemWidth}, list)
end
end
local PageW = Aligner.Width - (Aligner.Width + Aligner.SpaceX) % ColWidth
local n = x / (PageW + Aligner.SpaceX) --ColWidth
for i = 0, n do
Aligner:AddItem(d_AlignV{Width = PageW})--FullItemWidth})
end
local scroll = dlg.Items.Scroll
scroll.Tick = 0
Aligner:Realign()
scroll.Active = scroll.TicksCount > 1
scroll.Visible = scroll.TicksCount > 1
end
function DlgF.OnShow(dlg)
if internal.context ~= "map" then
dlg:Redraw()
Message("{Some Info.}\nE.g. Ctrl + Right Click opens permanent info window.\nAlt + Right Click and Shift + Right Click do the same.", 4)
end
end
local function d_WogOptions(readonly)
local dlg = BuildDlg()
dlg.Items.Outer:NeedSize()
if readonly then
dlg.Items.Options.Active = false
dlg.IgnoreFlags = true
end
dlg:updateAll()
local r = dlg:Show() == 30722
return r
end
d_dialogs.WogOptions = d_WogOptions
local function BtnClick(it, cmd)
if internal.context == "map" then
internal.CopyFromWogOptions()
return d_WogOptions(true)
end
local last = internal.CurOptions
internal.CurOptions = internal.CopyOptionsTable(internal.BaseOptions)
if d_WogOptions() then
internal.BaseOptions = internal.CopyOptionsTable(internal.CurOptions)
internal.CopyToWogOptions()
internal.SaveOptions()
internal.event("OptionsChanged")
else
internal.CurOptions = last
end
end
function internal.events.ShowDialog(t)
local info = t.ClassPtr == 0x641720
if info or t.ClassPtr == 0x641CBC then
t:Add(d_MainMenuButton{Name = "WogOptions", X = (info and 619 or 622), Y = (info and 99 or 105), File = "ZWogOpt.def", OnClick = BtnClick})
end
end
-- function _G.Q(...)
-- dofile[[c:\_WoG\wog359\trunk\Lua\options dialog.lua]]
-- return d_WogOptions(...)
-- end
--[[
mem.hookfunction(0x4B4F00, 1, 5, function(d, def, this, c, buf, x, y, color)
if x >= 0 and x <= ScreenWidth and y >= 0 and y <= ScreenHeight then
return def(this, c, buf, x, y, color)
end
end)
]]