-
Notifications
You must be signed in to change notification settings - Fork 2
/
skins.lua
473 lines (423 loc) · 12.3 KB
/
skins.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
---@class XLootAddon
local XLoot = select(2, ...)
local lib = {
skins = {},
masque_tweaks = {},
}
XLoot.Skin = lib
local L = XLoot.L
local print = print
-- Custom skins
-- To add your own, simply make XLoot a dependency then call XLoot:RegisterSkin(name, skin_table)
-- skin_table being a table with these keys:
-- [required] texture - Path to texture
-- [optional] name - Shown in UI, name provided to RegisterSkin used by default
-- [optional] size, size_highlight
-- [optional] row_spacing
-- [optional] frame_color_*, loot_color_* -- See above
-- [optional] color_mod - Multiplier for border quality colors
-- [optional] padding, padding_highlight - Padding refers to how far outward (or inward) the border should be offset from the frame
-- Tweaking Masque skins
-- To keep from having to change this file, call XLoot:RegisterMasqueTweak(skin_name, skin_table)
-- following the same rules as custom skins
-- Quick or temporary tweaks can be added to SKIN_TWEAKS.lua
-- Base skin template
lib.base = {
bar_texture = [[Interface\AddOns\XLoot\Textures\bar]],
color_mod = .75,
row_spacing = 2,
}
-- Skin registration
function XLoot:RegisterSkin(skin_name, skin_table)
setmetatable(skin_table, { __index = lib.base })
skin_table.key = skin_name
lib.skins[skin_name] = skin_table
end
-- Masque tweaks
function XLoot:RegisterMasqueTweak(masque_name, tweak_table)
lib.masque_tweaks[masque_name] = tweak_table
-- Apply to existing skins
if lib.skins[masque_name] then
for k, v in pairs(tweak_table) do
lib.skins[masque_name][k] = v
end
end
end
-- Skinning
local function subtable_insert(t, k, v)
if not t[k] then
t[k] = {}
end
table.insert(t[k], v)
end
do
local base = {
padding = 2,
size = 16,
layer = 'ARTWORK',
mode = 'BLEND',
r = 1,
g = 1,
b = 1,
a = 1
}
local types = {
highlight = {
mode = 'ADD',
layer = 'HIGHLIGHT',
texture = [[Interface\Buttons\ButtonHilight-Square]],
size = 8,
padding = 0,
r = .8,
g = .8,
b = .8,
a = .8
}
}
local mt = {
__index = function(t, k)
local ttype = rawget(t, 'type')
if ttype and types[ttype] and types[ttype][k] then
return types[ttype][k]
end
return base[k] or nil
end
}
local function meta(t)
return setmetatable(t, mt)
end
local function update_borders(frame, options, borders, r, g, b, a)
local padding = options.padding
local size = options.size/2
r = r or options.r
g = g or options.g
b = b or options.b
a = a or options.a
for pos, tex in ipairs(borders) do
-- Set texture options
tex:SetDrawLayer(options.layer)
tex:SetTexture(options.texture)
tex:SetBlendMode(options.mode)
tex:SetWidth(size)
tex:SetHeight(size)
tex:SetVertexColor(r, g, b, a)
-- Position texture
tex:ClearAllPoints()
if pos == 1 then
tex:SetTexCoord(0, 1/6, 0, 1/6)
tex:SetPoint("TOPLEFT", frame, "TOPLEFT", -padding, padding)
elseif pos == 2 then
tex:SetTexCoord(5/6, 1, 0, 1/6)
tex:SetPoint("TOPRIGHT", frame, "TOPRIGHT", padding, padding)
elseif pos == 3 then
tex:SetTexCoord(0, 1/6, 5/6, 1)
tex:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", -padding, -padding)
elseif pos == 4 then
tex:SetTexCoord(5/6, 1, 5/6, 1)
tex:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", padding, -padding)
elseif pos == 5 then
tex:SetTexCoord(1/6, 5/6, 0, 1/6)
tex:SetPoint("TOPLEFT", borders[1], "TOPRIGHT")
tex:SetPoint("TOPRIGHT", borders[2], "TOPLEFT")
elseif pos == 6 then
tex:SetTexCoord(1/6, 5/6, 5/6, 1)
tex:SetPoint("BOTTOMLEFT", borders[3], "BOTTOMRIGHT")
tex:SetPoint("BOTTOMRIGHT", borders[4], "BOTTOMLEFT")
elseif pos == 7 then
tex:SetTexCoord(0, 1/6, 1/6, 5/6)
tex:SetPoint("TOPLEFT", borders[1], "BOTTOMLEFT")
tex:SetPoint("BOTTOMLEFT", borders[3], "TOPLEFT")
elseif pos == 8 then
tex:SetTexCoord(5/6, 1, 1/6, 5/6)
tex:SetPoint("TOPRIGHT", borders[2], "BOTTOMRIGHT")
tex:SetPoint("BOTTOMRIGHT", borders[4], "TOPRIGHT")
end
end
end
local function create_borders(frame, options)
local borders = { }
for i = 1, 8 do
borders[i] = frame:CreateTexture()
end
update_borders(frame, options, borders)
return borders
end
local backdrop = {
bgFile = [[Interface\ChatFrame\ChatFrameBackground]], tile = true, tileSize = 16,
insets = {left = 3, right = 3, top = 3, bottom = 3},
}
local backdrop_empty = {
bgFile = ''
}
local bd_color = { 0, 0, 0, .9 }
local g_color = { .5, .5, .5, .6 }
-- Frame methods
-- https://www.wowace.com/projects/xloot/issues/205 is not reproducible, but user gets error reliably
local alphaworks = false
local function SetBorderColor(self, r, g, b, a)
for i, x in pairs(self._skin_borders) do
x:SetVertexColor(r, g, b, a or 1)
end
end
local function GetBorderColor(self)
return self._skin_borders[1]:GetVertexColor()
end
local function SetGradientColor(self, r, g, b, a)
self.gradient:SetGradient('VERTICAL', CreateColor(0.1, 0.1, 0.1, 0), CreateColor(r, g, b, a))
end
function lib:Gradient(frame)
local g = frame:CreateTexture(nil, 'BORDER')
frame.gradient = g
g:SetTexture([[Interface\ChatFrame\ChatFrameBackground]])
g:SetPoint('TOPLEFT', 3, -3)
g:SetPoint('BOTTOMRIGHT', -3, 3)
-- g:SetBlendMode'ADD'
frame.SetGradientColor = SetGradientColor
frame:SetGradientColor(unpack(g_color))
end
function lib:Backdrop(frame, opt_backdrop)
frame:SetBackdrop(opt_backdrop or backdrop)
frame:SetBackdropColor(unpack(bd_color))
end
-- Lib methods
-- Basic skin
function lib:Skin(frame, options)
-- Store options
frame._skin_options = meta(options)
-- Apply backdrop
if options.backdrop ~= false then
self:Backdrop(frame, type(options.backdrop) == 'table' and options.backdrop or nil)
end
-- Gradient
if options.gradient ~= false then
self:Gradient(frame)
end
-- Borders
frame._skin_borders = create_borders(frame, options)
frame.SetBorderColor = SetBorderColor
frame.GetBorderColor = GetBorderColor
end
function lib:SkinRaw(frame, options)
return create_borders(frame, meta(options)), SetBorderColor
end
function lib:UpdateSkin(frame, options, r, g, b, a)
frame._skin_options = meta(options)
update_borders(frame, options, frame._skin_borders, r, g, b, a)
end
-- Highlights
local function ShowHighlight(self, status)
for _, tex in ipairs(self._highlights) do
tex:Show()
end
end
local function HideHighlight(self)
for _, tex in ipairs(self._highlights) do
tex:Hide()
end
end
local function SetHighlightColor(self, r, g, b, a)
for _, tex in ipairs(self._highlights) do
tex:SetVertexColor(r, g, b, a)
end
end
local function GetHighlightColor(self)
return self._highlights[1]:GetVertexColor()
end
local highlight = { type = 'highlight' }
-- Add highlight borders to a frame
function lib:Highlight(frame, options)
-- Default options
options = meta(options or highlight)
frame._highlights = create_borders(frame, options)
frame._higlight_options = options
frame.ShowHighlight = ShowHighlight
frame.HideHighlight = HideHighlight
frame.SetHighlightColor = SetHighlightColor
frame.GetHighlightColor = GetHighlightColor
if options.layer ~= 'HIGHLIGHT' then
frame:HideHighlight()
end
end
function lib:UpdateHighlight(frame, options, r, g, b, a)
frame._higlight_options = meta(options)
update_borders(frame, options, frame._highlights, r, g, b, a)
end
end
-- Create a subset of skins to be applied
do
-- Merge current skin with set options
local function compile(data, name)
assert(data.sets[name], "Bad set name given to XLoot.Skin")
-- Return cached
if not data.compiled[name] then
data.compiled[name] = {}
elseif next(data.compiled[name]) then
return data.compiled[name]
end
-- Generate to cache
local out = data.compiled[name]
local skin = (data.SKIN and lib.skins[data.SKIN]) and lib.skins[data.SKIN] or lib.current
local set = data.sets[name]
-- Copy defaults
for k,v in pairs(lib.base) do
out[k] = v
end
-- Copy skin data
for k,v in pairs(skin) do
out[k] = v
end
-- Extract data for highlights
if skin.highlight
and set.type
and set.type == 'highlight'
and type(skin.highlight) == 'table' then
for k,v in pairs(skin.highlight) do
out[k] = v
end
-- Highlights shouldn't inherit default texture
if not skin.highlight.texture then
out.texture = nil
end
end
-- Apply set overrides
for k,v in pairs(set) do
out[k] = v
end
-- Apply metatable
setmetatable(out, getmetatable(skin))
return out
end
-- Re-compile and Re-apply all
local function Reskin(self)
local data = self._skin_data
-- Clear cache
for k,v in pairs(data.compiled) do
wipe(v)
end
-- Update skins
for set_name,frames in pairs(data.skinned) do
for i,frame in ipairs(frames) do
lib:UpdateSkin(frame, compile(data, set_name), frame:GetBorderColor())
end
end
-- Update highlights
for set_name,frames in pairs(data.highlighted) do
for i,frame in ipairs(frames) do
lib:UpdateHighlight(frame, compile(data, set_name), frame:GetHighlightColor())
end
end
return compile(data, data.default or next(data.sets))
end
local function Skin(self, frame, set_name)
local data = self._skin_data
set_name = set_name or data.default
local skin = compile(data, set_name)
lib:Skin(frame, skin)
subtable_insert(data.skinned, set_name, frame)
return skin
end
local function Highlight(self, frame, set_name)
local data = self._skin_data
set_name = set_name or data.default
lib:Highlight(frame, compile(data, set_name))
subtable_insert(data.highlighted, set_name, frame)
end
-- Embed required functions and create data set to skin multiple similar frames
XLoot.skinners = {}
function XLoot:MakeSkinner(target, sets, default_set)
if not default_set and not sets.default then
sets.default = {}
end
target._skin_data = {
skinned = {},
highlighted = {},
compiled = {},
sets = sets,
default = default_set or "default"
}
target.Reskin = Reskin
target.Skin = Skin
target.Highlight = Highlight
table.insert(XLoot.skinners, target)
return target
end
end
-------------------------------------------------------------------------------
-- Default skins
local svelte = {
name = ('|c2244dd22%s|r'):format(L.skin_svelte),
texture = [[Interface\AddOns\XLoot\Textures\border_svelte]],
}
local legacy = {
name = ('|c2244dd22%s|r'):format(L.skin_legacy),
row_spacing = 3,
texture = [[Interface\AddOns\XLoot\Textures\border_legacy]],
size = 16,
highlight = {
size = 12
},
color_mod = .85,
}
local smooth = {
name = ('|c2244dd22%s|r'):format(L.skin_smooth),
row_spacing = 3,
texture = [[Interface\AddOns\XLoot\Textures\border_smooth]],
size = 14,
padding = 1,
highlight = {
size = 6,
padding = -1
},
color_mod = .9,
}
-- Register default skins
XLoot:RegisterSkin('svelte', svelte)
XLoot:RegisterSkin('legacy', legacy)
XLoot:RegisterSkin('smooth', smooth)
-------------------------------------------------------------------------------
-- Index Masque skins later so we definitely catch all of them
function XLoot:SkinsOnInitialize()
-- Masque skins
local Masque = LibStub('Masque', true) or LibStub('LibButtonFacade', true)
if Masque and Masque.GetSkins then
-- Add available skins
local Masque_Skins = Masque:GetSkins()
if type(Masque_Skins) == 'table' then
for k, v in pairs(Masque_Skins) do
if k ~= 'Blizzard' and v.Normal.Texture then
local skin = { }
-- Guess at dimensions
if v.Icon.Height and v.Normal.Height then
skin.padding = (v.Normal.Height - v.Icon.Height) / 4
skin.row_spacing = v.Icon.Height / 16
skin.size = v.Icon.Height / 2
end
skin.texture = v.Normal.Texture
skin.name = ('|c22dddd22Masque:|r %s'):format(k)
-- Apply existing tweak
if lib.masque_tweaks[k] then
for mk,mv in pairs(lib.masque_tweaks[k]) do
skin[mk] = mv
end
end
-- Register
XLoot:RegisterSkin(k, skin)
end
end
else -- Warn about outdated Masque
print("XLoot: Use of masque skins requires the beta version of Masque.")
end
end
XLoot:ApplySkinTweaks()
-- Activate current skin
self:SetSkin(self.db.profile.skin)
end
-------------------------------------------------------------------------------
-- Skin access
function XLoot:SetSkin(name)
lib.current = lib.skins[lib.skins[name] and name or 'smooth']
end
--@do-not-package@
local AC = LibStub('AceConsole-2.0', true)
if AC then print = function(...) AC:PrintLiteral(...) end end
--@end-do-not-package@