View difference between Paste ID: 2ekWh40c and N2w3miBP
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)