Repository navigation
Expand file tree
/
Copy pathLayout.lua
More file actions
180 lines (161 loc) · 6.58 KB
/
Copy pathLayout.lua
File metadata and controls
180 lines (161 loc) · 6.58 KB
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
local ADDON, ns = ...
-- Where a button stands and how large the bar is.
--
-- === What is pure here ===
--
-- All of it. A button's place in the grid is arithmetic with a right answer,
-- and an error in it is visible only by staring: the button lands a pixel off
-- and that becomes noticeable a week later.
--
-- The five cases the "buttons / per row" pair exists for are checked one by
-- one: a single row, an even division, a short last row, one per row, and all
-- twelve in a line.
local Layout = {}
ns.Layout = Layout
-- Limits. The numbers are not the game's native sizes but the bounds of sense:
-- a button under twenty shows no icon, one over eighty does not fit twelve to
-- a row on an ordinary screen.
local SIZE_MIN, SIZE_MAX = 20, 80
local PAD_MIN, PAD_MAX = 0, 32
local ROW_MIN, ROW_MAX = 1, 12
Layout.SIZE_MIN, Layout.SIZE_MAX = SIZE_MIN, SIZE_MAX
Layout.PAD_MIN, Layout.PAD_MAX = PAD_MIN, PAD_MAX
Layout.ROW_MIN, Layout.ROW_MAX = ROW_MIN, ROW_MAX
--- A number within bounds.
--
-- Pure. Rubbish means the default rather than zero: the value comes from the
-- saved variables, which collect anything over the years, and a bar with
-- zero-sized buttons is one the player can never bring back - it cannot be
-- seen or pressed.
--
-- @param value any
-- @param min number
-- @param max number
-- @param fallback number
-- @return number
function Layout.Clamp(value, min, max, fallback)
local number = tonumber(value)
if number == nil or number ~= number then return fallback end
if number < min then return min end
if number > max then return max end
return number
end
--- The place of the button with this index.
--
-- Counted from the bar's top left corner, as the engine counts: x to the
-- right, y downwards and therefore negative.
--
-- === Which way the grid grows ===
--
-- Down and right, as in the game, and that is the default. But a bar placed at
-- the right edge of the screen growing rightwards leaves the screen: the
-- player sees three buttons of twelve and does not know where the rest went.
-- The same at the bottom edge growing down. So the direction is a setting, as
-- in Bartender, rather than our decision on the player's behalf.
--
-- Growth left and up is the same grid with the sign reversed: button one stays
-- at the anchor and the rest go the other way.
--
-- @param index any button index, from one
-- @param perRow any buttons per row
-- @param padding any gap between buttons
-- @param size any button side
-- @param hgrowth any "LEFT" or "RIGHT" (default)
-- @param vgrowth any "UP" or "DOWN" (default)
-- @return number x
-- @return number y
function Layout.Position(index, perRow, padding, size, hgrowth, vgrowth)
local number = math.floor(Layout.Clamp(index, 1, 120, 1))
local row = math.floor(Layout.Clamp(perRow, ROW_MIN, ROW_MAX, ROW_MAX))
local gap = Layout.Clamp(padding, PAD_MIN, PAD_MAX, 6)
local side = Layout.Clamp(size, SIZE_MIN, SIZE_MAX, 36)
local step = side + gap
local column = (number - 1) % row
local line = math.floor((number - 1) / row)
local x = column * step
if hgrowth == "LEFT" then x = -x end
local y = line * step
if vgrowth ~= "UP" then y = -y end
return x, y
end
--- The bar's size for this many buttons.
--
-- Computed on the same step as a button's place, and that is not repetition
-- but a requirement: a bar whose size is computed by a rule of its own will
-- sooner or later drift from the buttons on it, and drift silently - an empty
-- strip appears at the edge or the last button sticks out.
--
-- @param count any how many buttons
-- @param perRow any buttons per row
-- @param padding any gap
-- @param size any button side
-- @return number width
-- @return number height
function Layout.Extent(count, perRow, padding, size)
local many = math.floor(Layout.Clamp(count, 0, 120, 0))
local row = math.floor(Layout.Clamp(perRow, ROW_MIN, ROW_MAX, ROW_MAX))
local gap = Layout.Clamp(padding, PAD_MIN, PAD_MAX, 6)
local side = Layout.Clamp(size, SIZE_MIN, SIZE_MAX, 36)
if many <= 0 then return side, side end
local columns = many < row and many or row
local lines = math.ceil(many / row)
return columns * side + (columns - 1) * gap,
lines * side + (lines - 1) * gap
end
--============================================================================
-- Alpha
--============================================================================
--- The bar's alpha right now.
--
-- === Why a fading bar ===
--
-- A bar the player rarely uses with the mouse takes up room all the time.
-- Bartender lets it fade to barely visible and light up under the mouse, and
-- that is the only way to keep a sixth bar on screen without covering the
-- battlefield with it.
--
-- Pure, and the only place this is decided. The rule is simple: fading not
-- asked for - the alpha is as it was; asked for and the mouse is on the bar -
-- the same; asked for and no mouse - the faded one.
--
-- The faded alpha never goes down to zero. A bar that is completely invisible
-- gets lost: the player does not know where to look for it with the mouse and
-- finds it by a random movement. So the lower bound is not zero but barely
-- visible.
--
-- @param settings any bar settings
-- @param over any whether the mouse is on the bar
-- @return number alpha from zero to one
function Layout.FadeAlpha(settings, over)
if type(settings) ~= "table" then return 1 end
local full = Layout.Clamp(settings.alpha, 0, 1, 1)
if settings.fade ~= true then return full end
if over then return full end
local faded = Layout.Clamp(settings.fadeAlpha, 0.05, 1, 0.15)
if faded > full then return full end
return faded
end
--- Whether an empty slot is visible.
--
-- === Why show the empty ===
--
-- An empty button is the place the player drops a spell onto with the mouse.
-- Hiding it would take that place away: there is nowhere to drop, and a bar
-- with three of twelve slots filled looks like a bar of three buttons.
--
-- But showing them always will not do either: a row of empty squares at the
-- bottom of the screen is what Bartender added a setting for, not decoration.
--
-- So the grid shows in two cases: the player asked to see it always, or they
-- are holding a spell on the cursor right now. The second is not politeness: a
-- spell with nowhere to drop returns to its place, and that looks like
-- "dragging does not work".
--
-- @param grid any whether the player asked to see empty ones
-- @param dragging any whether the player is holding a spell
-- @return boolean
function Layout.GridShown(grid, dragging)
if grid == true then return true end
if dragging == true then return true end
return false
end