SHOW:
|
|
- or go back to the newest paste.
1 | -- Usage: | |
2 | -- spinner = CreateSpinner(parent) | |
3 | -- spinner:SetTexture('texturePath') | |
4 | -- spinner:SetBlendMode('blendMode') | |
5 | -- spinner:SetVertexColor(r, g, b) | |
6 | -- spinner:SetClockwise(boolean) -- true to fill clockwise, false to fill counterclockwise | |
7 | -- spinner:SetReverse(boolean) -- true to empty the bar instead of filling it | |
8 | -- spinner:SetValue(percent) -- value between 0 and 1 to fill the bar to | |
9 | ||
10 | -- Some math stuff | |
11 | local cos, sin, pi2, halfpi = math.cos, math.sin, math.rad(360), math.rad(90) | |
12 | local function Transform(tx, x, y, angle, aspect) -- Translates texture to x, y and rotates about its center | |
13 | local c, s = cos(angle), sin(angle) | |
14 | local y, oy = y / aspect, 0.5 / aspect | |
15 | local ULx, ULy = 0.5 + (x - 0.5) * c - (y - oy) * s, (oy + (y - oy) * c + (x - 0.5) * s) * aspect | |
16 | local LLx, LLy = 0.5 + (x - 0.5) * c - (y + oy) * s, (oy + (y + oy) * c + (x - 0.5) * s) * aspect | |
17 | local URx, URy = 0.5 + (x + 0.5) * c - (y - oy) * s, (oy + (y - oy) * c + (x + 0.5) * s) * aspect | |
18 | local LRx, LRy = 0.5 + (x + 0.5) * c - (y + oy) * s, (oy + (y + oy) * c + (x + 0.5) * s) * aspect | |
19 | tx:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy) | |
20 | end | |
21 | ||
22 | -- Permanently pause our rotation animation after it starts playing | |
23 | local function OnPlayUpdate(self) | |
24 | self:SetScript('OnUpdate', nil) | |
25 | self:Pause() | |
26 | end | |
27 | ||
28 | local function OnPlay(self) | |
29 | self:SetScript('OnUpdate', OnPlayUpdate) | |
30 | end | |
31 | ||
32 | local function SetValue(self, value) | |
33 | -- Correct invalid ranges, preferably just don't feed it invalid numbers | |
34 | if value > 1 then value = 1 | |
35 | elseif value < 0 then value = 0 end | |
36 | ||
37 | -- Reverse our normal behavior | |
38 | if self._reverse then | |
39 | value = 1 - value | |
40 | end | |
41 | ||
42 | -- Determine which quadrant we're in | |
43 | local q, quadrant = self._clockwise and (1 - value) or value -- 4 - floor(value / 0.25) | |
44 | if q >= 0.75 then | |
45 | quadrant = 1 | |
46 | elseif q >= 0.5 then | |
47 | quadrant = 2 | |
48 | elseif q >= 0.25 then | |
49 | quadrant = 3 | |
50 | else | |
51 | quadrant = 4 | |
52 | end | |
53 | ||
54 | - | -- Show/hide necessary textures if we need to |
54 | + | |
55 | self._quadrant = quadrant | |
56 | -- Show/hide necessary textures if we need to | |
57 | if self._clockwise then | |
58 | for i = 1, 4 do | |
59 | self._textures[i]:SetShown(i < quadrant) | |
60 | end | |
61 | else | |
62 | for i = 1, 4 do | |
63 | self._textures[i]:SetShown(i > quadrant) | |
64 | end | |
65 | end | |
66 | -- Move scrollframe/wedge to the proper quadrant | |
67 | self._scrollframe:SetAllPoints(self._textures[quadrant]) | |
68 | - | -- Move scrollframe/wedge to the proper quadrant |
68 | + | |
69 | - | self._scrollframe:SetAllPoints(self._textures[quadrant]) |
69 | + | |
70 | -- Rotate the things | |
71 | local rads = value * pi2 | |
72 | if not self._clockwise then rads = -rads + halfpi end | |
73 | Transform(self._wedge, -0.5, -0.5, rads, self._aspect) | |
74 | self._rotation:SetRadians(-rads) | |
75 | end | |
76 | ||
77 | local function SetClockwise(self, clockwise) | |
78 | self._clockwise = clockwise | |
79 | end | |
80 | ||
81 | local function SetReverse(self, reverse) | |
82 | self._reverse = reverse | |
83 | end | |
84 | ||
85 | local function OnSizeChanged(self, width, height) | |
86 | self._wedge:SetSize(width, height) -- it's important to keep this texture sized correctly | |
87 | self._aspect = width / height -- required to calculate the texture coordinates | |
88 | end | |
89 | ||
90 | -- Creates a function that calls a method on all textures at once | |
91 | local function CreateTextureFunction(func, self, ...) | |
92 | return function(self, ...) | |
93 | for i = 1, 4 do | |
94 | local tx = self._textures[i] | |
95 | tx[func](tx, ...) | |
96 | end | |
97 | self._wedge[func](self._wedge, ...) | |
98 | end | |
99 | end | |
100 | ||
101 | -- Pass calls to these functions on our frame to its textures | |
102 | local TextureFunctions = { | |
103 | SetTexture = CreateTextureFunction('SetTexture'), | |
104 | SetBlendMode = CreateTextureFunction('SetBlendMode'), | |
105 | SetVertexColor = CreateTextureFunction('SetVertexColor'), | |
106 | } | |
107 | ||
108 | local function CreateSpinner(parent) | |
109 | local spinner = CreateFrame('Frame', nil, parent) | |
110 | ||
111 | -- ScrollFrame clips the actively animating portion of the spinner | |
112 | local scrollframe = CreateFrame('ScrollFrame', nil, spinner) | |
113 | scrollframe:SetPoint('BOTTOMLEFT', spinner, 'CENTER') | |
114 | scrollframe:SetPoint('TOPRIGHT') | |
115 | spinner._scrollframe = scrollframe | |
116 | ||
117 | local scrollchild = CreateFrame('frame', nil, scrollframe) | |
118 | scrollframe:SetScrollChild(scrollchild) | |
119 | scrollchild:SetAllPoints(scrollframe) | |
120 | ||
121 | -- Wedge thing | |
122 | local wedge = scrollchild:CreateTexture() | |
123 | wedge:SetPoint('BOTTOMRIGHT', spinner, 'CENTER') | |
124 | spinner._wedge = wedge | |
125 | ||
126 | -- Top Right | |
127 | local trTexture = spinner:CreateTexture() | |
128 | trTexture:SetPoint('BOTTOMLEFT', spinner, 'CENTER') | |
129 | trTexture:SetPoint('TOPRIGHT') | |
130 | trTexture:SetTexCoord(0.5, 1, 0, 0.5) | |
131 | ||
132 | -- Bottom Right | |
133 | local brTexture = spinner:CreateTexture() | |
134 | brTexture:SetPoint('TOPLEFT', spinner, 'CENTER') | |
135 | brTexture:SetPoint('BOTTOMRIGHT') | |
136 | brTexture:SetTexCoord(0.5, 1, 0.5, 1) | |
137 | ||
138 | -- Bottom Left | |
139 | local blTexture = spinner:CreateTexture() | |
140 | blTexture:SetPoint('TOPRIGHT', spinner, 'CENTER') | |
141 | blTexture:SetPoint('BOTTOMLEFT') | |
142 | blTexture:SetTexCoord(0, 0.5, 0.5, 1) | |
143 | ||
144 | -- Top Left | |
145 | local tlTexture = spinner:CreateTexture() | |
146 | tlTexture:SetPoint('BOTTOMRIGHT', spinner, 'CENTER') | |
147 | tlTexture:SetPoint('TOPLEFT') | |
148 | tlTexture:SetTexCoord(0, 0.5, 0, 0.5) | |
149 | ||
150 | -- /4|1\ -- Clockwise texture arrangement | |
151 | -- \3|2/ -- | |
152 | ||
153 | spinner._textures = {trTexture, brTexture, blTexture, tlTexture} | |
154 | spinner._quadrant = nil -- Current active quadrant | |
155 | spinner._clockwise = true -- fill clockwise | |
156 | spinner._reverse = false -- Treat the provided value as its inverse, eg. 75% will display as 25% | |
157 | spinner._aspect = 1 -- aspect ratio, width / height of spinner frame | |
158 | spinner:HookScript('OnSizeChanged', OnSizeChanged) | |
159 | ||
160 | for method, func in pairs(TextureFunctions) do | |
161 | spinner[method] = func | |
162 | end | |
163 | ||
164 | spinner.SetClockwise = SetClockwise | |
165 | spinner.SetReverse = SetReverse | |
166 | spinner.SetValue = SetValue | |
167 | ||
168 | local group = wedge:CreateAnimationGroup() | |
169 | local rotation = group:CreateAnimation('Rotation') | |
170 | spinner._rotation = rotation | |
171 | rotation:SetDuration(0) | |
172 | rotation:SetEndDelay(1) | |
173 | rotation:SetOrigin('BOTTOMRIGHT', 0, 0) | |
174 | group:SetScript('OnPlay', OnPlay) | |
175 | group:Play() | |
176 | ||
177 | return spinner | |
178 | end | |
179 | ||
180 | ---------- | |
181 | -- Demo | |
182 | ---------- | |
183 | ||
184 | local spinner1 = CreateSpinner(UIParent) | |
185 | spinner1:SetPoint('BOTTOMRIGHT', UIParent, 'CENTER', -2, 2) | |
186 | spinner1:SetSize(64, 64) | |
187 | spinner1:SetTexture('interface/icons/inv_mushroom_11') | |
188 | ||
189 | spinner1:SetClockwise(false) | |
190 | spinner1:SetReverse(false) | |
191 | ||
192 | local spinner2 = CreateSpinner(UIParent) | |
193 | spinner2:SetPoint('BOTTOMLEFT', UIParent, 'CENTER', 2, 2) | |
194 | spinner2:SetSize(64, 64) | |
195 | spinner2:SetTexture('interface/icons/inv_mushroom_11') | |
196 | ||
197 | spinner2:SetClockwise(true) | |
198 | spinner2:SetReverse(false) | |
199 | ||
200 | local spinner3 = CreateSpinner(UIParent) | |
201 | spinner3:SetPoint('TOPRIGHT', UIParent, 'CENTER', -2, -2) | |
202 | spinner3:SetSize(64, 64) | |
203 | spinner3:SetTexture('interface/icons/inv_mushroom_11') | |
204 | ||
205 | spinner3:SetClockwise(true) | |
206 | spinner3:SetReverse(true) | |
207 | ||
208 | local spinner4 = CreateSpinner(UIParent) | |
209 | spinner4:SetPoint('TOPLEFT', UIParent, 'CENTER', 2, -2) | |
210 | spinner4:SetSize(64, 64) | |
211 | spinner4:SetTexture('interface/icons/inv_mushroom_11') | |
212 | ||
213 | spinner4:SetClockwise(false) | |
214 | spinner4:SetReverse(true) | |
215 | ||
216 | local f = CreateFrame('frame') | |
217 | local timespent = 0 | |
218 | f:SetScript('OnUpdate', function(self, elapsed) | |
219 | timespent = timespent + elapsed | |
220 | if timespent >= 3 then | |
221 | timespent = 0 | |
222 | end | |
223 | ||
224 | local value = timespent / 3 | |
225 | spinner1:SetValue(value) | |
226 | spinner2:SetValue(value) | |
227 | spinner3:SetValue(value) | |
228 | spinner4:SetValue(value) | |
229 | end) |