try to track this thing down better
[QuestHelper.git] / arrow.lua
blob41d2067ea268ad8f1fddce7508c891820962c034
1 QuestHelper_File["arrow.lua"] = "Development Version"
2 QuestHelper_Loadtime["arrow.lua"] = GetTime()
4 --[[ This entire file is pretty liberally ganked from TomTom (and then modified) under the following license:
6 -------------------------------------------------------------------------
7 Copyright (c) 2006-2007, James N. Whitehead II
8 All rights reserved.
10 Redistribution and use in source and binary forms, with or without
11 modification, are permitted provided that the following conditions are
12 met:
14 * Redistributions of source code must retain the above copyright
15 notice, this list of conditions and the following disclaimer.
16 * Redistributions in binary form must reproduce the above
17 copyright notice, this list of conditions and the following
18 disclaimer in the documentation and/or other materials provided
19 with the distribution.
20 * The name or alias of the copyright holder may not be used to endorse
21 or promote products derived from this software without specific prior
22 written permission.
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 ---------------------------------------------------------------------------
37 Thanks, James! <3 ]]
39 local function ColorGradient(perc, ...)
40 local num = select("#", ...)
41 local hexes = type(select(1, ...)) == "string"
43 if perc == 1 then
44 return select(num-2, ...), select(num-1, ...), select(num, ...)
45 end
47 num = num / 3
49 local segment, relperc = math.modf(perc*(num-1))
50 local r1, g1, b1, r2, g2, b2
51 r1, g1, b1 = select((segment*3)+1, ...), select((segment*3)+2, ...), select((segment*3)+3, ...)
52 r2, g2, b2 = select((segment*3)+4, ...), select((segment*3)+5, ...), select((segment*3)+6, ...)
54 if not r2 or not g2 or not b2 then
55 return r1, g1, b1
56 else
57 return r1 + (r2-r1)*relperc,
58 g1 + (g2-g1)*relperc,
59 b1 + (b2-b1)*relperc
60 end
61 end
63 local wayframe = CreateFrame("Button", "QHArrowFrame", UIParent)
64 wayframe:SetPoint("CENTER", -300, 300)
65 wayframe:EnableMouse(true)
66 wayframe:SetMovable(true)
67 wayframe:SetUserPlaced(true)
68 wayframe:Hide()
70 wif = wayframe
72 -- Frame used to control the scaling of the title and friends
73 local titleframe = CreateFrame("Frame", nil, wayframe)
75 wayframe.title = titleframe:CreateFontString("OVERLAY", nil, "GameFontNormalSmall")
76 wayframe.status = titleframe:CreateFontString("OVERLAY", nil, "GameFontNormalSmall")
77 wayframe.tta = titleframe:CreateFontString("OVERLAY", nil, "GameFontNormalSmall")
78 wayframe.title:SetPoint("TOP", wayframe, "BOTTOM", 0, 0)
79 wayframe.status:SetPoint("TOP", wayframe.title, "BOTTOM", 0, 0)
80 wayframe.tta:SetPoint("TOP", wayframe.status, "BOTTOM", 0, 0)
81 local default_font_name, default_font_size, default_font_flags = wayframe.title:GetFont()
84 local r, g, b, a = wayframe.status:GetTextColor()
85 r, g, b = r - 0.2, g - 0.2, b - 0.2
86 wayframe.status:SetTextColor(r, g, b, a)
87 end
89 local OnUpdate
91 local function OnDragStart(self, button)
92 if not QuestHelper_Pref.arrow_locked then -- TODO TWEAKERY
93 self:StartMoving()
94 end
95 end
97 local function OnDragStop(self, button)
98 self:StopMovingOrSizing()
99 end
101 local function OnEvent(self, event, ...)
102 if event == "ZONE_CHANGED_NEW_AREA" and QuestHelper_Pref.arrow and not QuestHelper_Pref.hide then -- TODO TWEAKERY
103 self:Show()
104 OnUpdate(self, nil)
108 wayframe:SetScript("OnDragStart", OnDragStart)
109 wayframe:SetScript("OnDragStop", OnDragStop)
110 wayframe:RegisterForDrag("LeftButton")
111 wayframe:RegisterEvent("ZONE_CHANGED_NEW_AREA")
112 wayframe:SetScript("OnEvent", OnEvent)
114 wayframe.arrow = wayframe:CreateTexture("OVERLAY")
115 --wayframe.arrow:SetTexture("Interface\\AddOns\\QuestHelper\\arrow_image_down") -- if we don't do this, the image doesn't seem to end up cached. :blizzard:
116 wayframe.arrow:SetTexture("Interface\\AddOns\\QuestHelper\\arrow_image")
117 wayframe.arrow:SetAllPoints()
119 local active_point, arrive_distance, showDownArrow, point_title
120 active_point = {}
122 function QH_Arrow_Show()
123 wayframe:Show()
126 function QH_Arrow_Reset()
127 QuestHelper_Pref.arrow = true
128 wayframe:ClearAllPoints()
129 wayframe:SetPoint("CENTER", 0, 0)
130 QuestHelper_Pref.arrow_locked = false -- they're probably going to want to move it
131 QH_Arrow_Show()
134 function QH_Arrow_SetScale(scale)
135 if scale then
136 QuestHelper_Pref.arrow_arrowsize = scale
137 else
138 scale = QuestHelper_Pref.arrow_arrowsize
141 if not showDownArrow then
142 wayframe:SetHeight(42 * scale)
143 wayframe:SetWidth(56 * scale)
144 else
145 scale = scale * 0.8
146 wayframe:SetHeight(70 * scale)
147 wayframe:SetWidth(53 * scale)
150 QH_Arrow_SetScale()
152 function QH_Arrow_SetTextScale(scale)
153 wayframe.title:SetFont(default_font_name, default_font_size * scale, default_font_flags)
154 wayframe.status:SetFont(default_font_name, default_font_size * scale, default_font_flags)
155 wayframe.tta:SetFont(default_font_name, default_font_size * scale, default_font_flags)
156 QuestHelper_Pref.arrow_textsize = scale
157 --wayframe:SetScale(scale)
159 QH_Arrow_SetTextScale(QuestHelper_Pref.arrow_textsize or 1)
161 local function wpupdate(c, z, x, y, desc)
162 if c then
163 QuestHelper: Assert(z)
164 QuestHelper: Assert(x)
165 QuestHelper: Assert(y)
166 else
167 QuestHelper: Assert(not z)
168 QuestHelper: Assert(not x)
169 QuestHelper: Assert(not y)
171 active_point.c, active_point.z, active_point.x, active_point.y = c, z, x, y
172 wayframe.title:SetText(desc)
173 wayframe:Show()
174 OnUpdate(wayframe, nil)
177 QuestHelper:AddWaypointCallback(wpupdate)
179 local status = wayframe.status
180 local tta = wayframe.tta
181 local arrow = wayframe.arrow
182 local last_distance = 0
183 local tta_throttle = 0
184 local speed = 0
185 local speed_count = 0
187 OnUpdate = function(self, elapsed)
188 QuestHelper: Assert(self)
190 if not active_point.c or QuestHelper.collect_rc ~= active_point.c or QuestHelper.collect_delayed or QuestHelper.InBrokenInstance or not QuestHelper_Pref.arrow then
191 self:Hide()
192 return
195 local dist, dx, dy = QuestHelper.Astrolabe:ComputeDistance(QuestHelper.collect_rc, QuestHelper.collect_rz, QuestHelper.collect_rx, QuestHelper.collect_ry, active_point.c, active_point.z, active_point.x, active_point.y)
197 if dist then
198 status:SetText(QHFormat("DISTANCE", math.floor(dist + 0.5)))
199 else
200 status:SetText("")
203 -- Showing the arrival arrow?
204 if dist and dist <= 10 then
205 if not showDownArrow then
206 showDownArrow = true
207 QH_Arrow_SetScale()
208 arrow:SetTexture("Interface\\AddOns\\QuestHelper\\arrow_image_down")
209 arrow:SetVertexColor(0, 1, 0)
212 local cell = math.floor(mod(GetTime() * 20, 55)) -- 20 fps seems to be around the right number
214 local column = cell % 9
215 local row = floor(cell / 9)
217 local xstart = (column * 53) / 512
218 local ystart = (row * 70) / 512
219 local xend = ((column + 1) * 53) / 512
220 local yend = ((row + 1) * 70) / 512
221 arrow:SetTexCoord(xstart,xend,ystart,yend)
222 else
223 if showDownArrow then
224 showDownArrow = false
225 QH_Arrow_SetScale()
226 arrow:SetTexture("Interface\\AddOns\\QuestHelper\\arrow_image")
227 showDownArrow = false
230 local angle = atan2(-dx, -dy) / 360 * (math.pi * 2) -- degrees. seriously what
231 --if angle < 0 then angle = angle + math.pi * 2 end
232 local player = GetPlayerFacing()
233 angle = angle - player
235 local perc = math.abs((math.pi - math.abs(angle)) / math.pi)
236 if perc > 1 then perc = 2 - perc end -- siiigh
238 local gr,gg,gb = 0, 1, 0
239 local mr,mg,mb = 1, 1, 0
240 local br,bg,bb = 1, 0, 0
241 local r,g,b = ColorGradient(perc, br, bg, bb, mr, mg, mb, gr, gg, gb)
242 arrow:SetVertexColor(r,g,b)
245 local cell = floor(angle / (math.pi * 2) * 108 + 0.5) % 108
246 local column = cell % 9
247 local row = floor(cell / 9)
249 local xstart = (column * 56) / 512
250 local ystart = (row * 42) / 512
251 local xend = ((column + 1) * 56) / 512
252 local yend = ((row + 1) * 42) / 512
253 arrow:SetTexCoord(xstart,xend,ystart,yend)
256 -- Calculate the TTA every second (%01d:%02d)
258 --[[
259 if elapsed then
260 tta_throttle = tta_throttle + elapsed
262 if tta_throttle >= 1.0 then
263 -- Calculate the speed in yards per sec at which we're moving
264 local current_speed = (last_distance - dist) / tta_throttle
266 if last_distance == 0 then
267 current_speed = 0
270 if speed_count < 2 then
271 speed = (speed + current_speed) / 2
272 speed_count = speed_count + 1
273 else
274 speed_count = 0
275 speed = current_speed
278 if speed > 0 then
279 local eta = math.abs(dist / speed)
280 tta:SetFormattedText("%01d:%02d", eta / 60, eta % 60)
281 else
282 tta:SetText("")
285 last_distance = dist
286 tta_throttle = 0
292 wayframe:SetScript("OnUpdate", OnUpdate)
295 local function spacer()
296 local htex = QuestHelper:CreateIconTexture(item, 10)
297 htex:SetVertexColor(1, 1, 1, 0)
298 return htex
301 function QH_Arrow_PopulateMenu(menu)
302 local hide = QuestHelper:CreateMenuItem(menu, QuestHelper_Pref.arrow and QHText("QH_BUTTON_HIDE") or QHText("QH_BUTTON_SHOW"))
303 hide:SetFunction(function () QuestHelper:ToggleArrow() end)
304 --hide:AddTexture(spacer(), true)
305 --hide:AddTexture(spacer(), false)
307 local lock = QuestHelper:CreateMenuItem(menu, "Lock")
308 local ltex = QuestHelper:CreateIconTexture(item, 10)
309 lock:SetFunction(function () QuestHelper_Pref.arrow_locked = not QuestHelper_Pref.arrow_locked end)
310 lock:AddTexture(ltex, true)
311 lock:AddTexture(spacer(), false)
312 ltex:SetVertexColor(1, 1, 1, QuestHelper_Pref.arrow_locked and 1 or 0)
314 local scale = QuestHelper:CreateMenuItem(menu, "Arrow Scale")
315 local scale_menu = QuestHelper:CreateMenu()
316 scale:SetSubmenu(scale_menu)
317 scale:AddTexture(spacer(), true)
318 for i = 5, 15 do
319 local it = QuestHelper:CreateMenuItem(scale_menu, string.format("%d%%", i * 10))
320 local ix = i
321 it:SetFunction(function () QH_Arrow_SetScale(ix / 10) end)
322 local icon = QuestHelper:CreateIconTexture(item, 10)
323 if QuestHelper_Pref.arrow_arrowsize == ix / 10 then
324 icon:SetVertexColor(1, 1, 1, 1)
325 else
326 icon:SetVertexColor(1, 1, 1, 0)
328 it:AddTexture(icon)
331 local tscale = QuestHelper:CreateMenuItem(menu, "Text Scale")
332 local tscale_menu = QuestHelper:CreateMenu()
333 tscale:SetSubmenu(tscale_menu)
334 tscale:AddTexture(spacer(), true)
335 for i = 5, 15 do
336 local it = QuestHelper:CreateMenuItem(tscale_menu, string.format("%d%%", i * 10))
337 local ix = i
338 it:SetFunction(function () QH_Arrow_SetTextScale(ix / 10) end)
339 local icon = QuestHelper:CreateIconTexture(item, 10)
340 if QuestHelper_Pref.arrow_textsize == ix / 10 then
341 icon:SetVertexColor(1, 1, 1, 1)
342 else
343 icon:SetVertexColor(1, 1, 1, 0)
345 it:AddTexture(icon)
348 local reset = QuestHelper:CreateMenuItem(menu, QHText("SETTINGS_MENU_ARROW_RESET"))
349 reset:SetFunction(function () QH_Arrow_Reset() end)
352 local function WayFrame_OnClick(self, button)
353 local menu = QuestHelper:CreateMenu()
354 QuestHelper:CreateMenuTitle(menu, QHText("SETTINGS_ARROWLINK_ARROW"))
356 QH_Arrow_PopulateMenu(menu)
358 menu:ShowAtCursor()
361 wayframe:RegisterForClicks("RightButtonUp")
362 wayframe:SetScript("OnClick", WayFrame_OnClick)