PageRenderTime 53ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/QuestHelper/arrow.lua

https://code.google.com/p/strongcwowinterface/
Lua | 375 lines | 240 code | 60 blank | 75 comment | 23 complexity | 427fc2616115c3411a13f3114fb744c7 MD5 | raw file
Possible License(s): Unlicense, LGPL-3.0, LGPL-2.1, BSD-3-Clause, GPL-2.0
  1. QuestHelper_File["arrow.lua"] = "1.1.5"
  2. QuestHelper_Loadtime["arrow.lua"] = GetTime()
  3. --[[ This entire file is pretty liberally ganked from TomTom (and then modified) under the following license:
  4. -------------------------------------------------------------------------
  5. Copyright (c) 2006-2007, James N. Whitehead II
  6. All rights reserved.
  7. Redistribution and use in source and binary forms, with or without
  8. modification, are permitted provided that the following conditions are
  9. met:
  10. * Redistributions of source code must retain the above copyright
  11. notice, this list of conditions and the following disclaimer.
  12. * Redistributions in binary form must reproduce the above
  13. copyright notice, this list of conditions and the following
  14. disclaimer in the documentation and/or other materials provided
  15. with the distribution.
  16. * The name or alias of the copyright holder may not be used to endorse
  17. or promote products derived from this software without specific prior
  18. written permission.
  19. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. ---------------------------------------------------------------------------
  31. Thanks, James! <3 ]]
  32. local function ColorGradient(perc, ...)
  33. local num = select("#", ...)
  34. local hexes = type(select(1, ...)) == "string"
  35. if perc == 1 then
  36. return select(num-2, ...), select(num-1, ...), select(num, ...)
  37. end
  38. num = num / 3
  39. local segment, relperc = math.modf(perc*(num-1))
  40. local r1, g1, b1, r2, g2, b2
  41. r1, g1, b1 = select((segment*3)+1, ...), select((segment*3)+2, ...), select((segment*3)+3, ...)
  42. r2, g2, b2 = select((segment*3)+4, ...), select((segment*3)+5, ...), select((segment*3)+6, ...)
  43. if not r2 or not g2 or not b2 then
  44. return r1, g1, b1
  45. else
  46. return r1 + (r2-r1)*relperc,
  47. g1 + (g2-g1)*relperc,
  48. b1 + (b2-b1)*relperc
  49. end
  50. end
  51. local wayframe = CreateFrame("Button", "QHArrowFrame", UIParent)
  52. wayframe:SetPoint("CENTER", -300, 300)
  53. wayframe:EnableMouse(true)
  54. wayframe:SetMovable(true)
  55. wayframe:SetUserPlaced(true)
  56. wayframe:Hide()
  57. wif = wayframe
  58. -- Frame used to control the scaling of the title and friends
  59. local titleframe = CreateFrame("Frame", nil, wayframe)
  60. wayframe.title = titleframe:CreateFontString("OVERLAY", nil, "GameFontNormalSmall")
  61. wayframe.status = titleframe:CreateFontString("OVERLAY", nil, "GameFontNormalSmall")
  62. wayframe.tta = titleframe:CreateFontString("OVERLAY", nil, "GameFontNormalSmall")
  63. wayframe.title:SetPoint("TOP", wayframe, "BOTTOM", 0, 0)
  64. wayframe.status:SetPoint("TOP", wayframe.title, "BOTTOM", 0, 0)
  65. wayframe.tta:SetPoint("TOP", wayframe.status, "BOTTOM", 0, 0)
  66. local default_font_name, default_font_size, default_font_flags = wayframe.title:GetFont()
  67. do
  68. local r, g, b, a = wayframe.status:GetTextColor()
  69. r, g, b = r - 0.2, g - 0.2, b - 0.2
  70. wayframe.status:SetTextColor(r, g, b, a)
  71. end
  72. local OnUpdate
  73. local function OnDragStart(self, button)
  74. if not QuestHelper_Pref.arrow_locked then -- TODO TWEAKERY
  75. self:StartMoving()
  76. end
  77. end
  78. local function OnDragStop(self, button)
  79. self:StopMovingOrSizing()
  80. end
  81. QH_Event("ZONE_CHANGED_NEW_AREA", function ()
  82. if QuestHelper_Pref.arrow and not QuestHelper_Pref.hide then -- TODO TWEAKERY
  83. wayframe:Show()
  84. OnUpdate()
  85. end
  86. end)
  87. QH_Hook(wayframe, "OnDragStart", OnDragStart)
  88. QH_Hook(wayframe, "OnDragStop", OnDragStop)
  89. wayframe:RegisterForDrag("LeftButton")
  90. wayframe.arrow = wayframe:CreateTexture("OVERLAY")
  91. --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:
  92. wayframe.arrow:SetTexture("Interface\\AddOns\\QuestHelper\\arrow_image")
  93. wayframe.arrow:SetAllPoints()
  94. local active_point, arrive_distance, showDownArrow, point_title
  95. active_point = {}
  96. function QH_Arrow_Show()
  97. wayframe:Show()
  98. end
  99. function QH_Arrow_Reset()
  100. QuestHelper_Pref.arrow = true
  101. wayframe:ClearAllPoints()
  102. wayframe:SetPoint("CENTER", 0, 0)
  103. QuestHelper_Pref.arrow_locked = false -- they're probably going to want to move it
  104. QH_Arrow_Show()
  105. end
  106. function QH_Arrow_SetScale(scale)
  107. if scale then
  108. QuestHelper_Pref.arrow_arrowsize = scale
  109. else
  110. scale = QuestHelper_Pref.arrow_arrowsize
  111. end
  112. if not showDownArrow then
  113. wayframe:SetHeight(42 * scale)
  114. wayframe:SetWidth(56 * scale)
  115. else
  116. scale = scale * 0.8
  117. wayframe:SetHeight(70 * scale)
  118. wayframe:SetWidth(53 * scale)
  119. end
  120. end
  121. function QH_Arrow_SetTextScale(scale)
  122. if scale then
  123. QuestHelper_Pref.arrow_textsize = scale
  124. else
  125. scale = QuestHelper_Pref.arrow_textsize
  126. end
  127. wayframe.title:SetFont(default_font_name, default_font_size * scale, default_font_flags)
  128. wayframe.status:SetFont(default_font_name, default_font_size * scale, default_font_flags)
  129. wayframe.tta:SetFont(default_font_name, default_font_size * scale, default_font_flags)
  130. end
  131. local function wpupdate(c, z, x, y, desc)
  132. if c then
  133. QuestHelper: Assert(z)
  134. QuestHelper: Assert(x)
  135. QuestHelper: Assert(y)
  136. else
  137. QuestHelper: Assert(not z)
  138. QuestHelper: Assert(not x)
  139. QuestHelper: Assert(not y)
  140. end
  141. active_point.c, active_point.z, active_point.x, active_point.y = c, z, x, y
  142. wayframe.title:SetText(desc)
  143. wayframe:Show()
  144. OnUpdate()
  145. end
  146. QuestHelper:AddWaypointCallback(wpupdate)
  147. local status = wayframe.status
  148. local tta = wayframe.tta
  149. local arrow = wayframe.arrow
  150. local last_distance = 0
  151. local tta_throttle = 0
  152. local speed = 0
  153. local speed_count = 0
  154. OnUpdate = function()
  155. local self = wayframe
  156. QuestHelper: Assert(self)
  157. 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
  158. self:Hide()
  159. return
  160. end
  161. self:Show()
  162. 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)
  163. local text = ""
  164. if dist then
  165. -- I had support for miles and kilometers, but decided that distances were rarely large
  166. -- enough to warrent it.
  167. if QuestHelper_Pref.metric then
  168. text = QHFormat("DISTANCE_METRES", math.floor(0.5+dist*0.9144))
  169. else
  170. text = QHFormat("DISTANCE_YARDS", math.floor(0.5 + dist))
  171. end
  172. end
  173. status:SetText(text)
  174. -- Showing the arrival arrow?
  175. if dist and dist <= 10 then
  176. if not showDownArrow then
  177. showDownArrow = true
  178. QH_Arrow_SetScale()
  179. arrow:SetTexture("Interface\\AddOns\\QuestHelper\\arrow_image_down")
  180. arrow:SetVertexColor(0, 1, 0)
  181. end
  182. local cell = math.floor(mod(GetTime() * 20, 55)) -- 20 fps seems to be around the right number
  183. local column = cell % 9
  184. local row = floor(cell / 9)
  185. local xstart = (column * 53) / 512
  186. local ystart = (row * 70) / 512
  187. local xend = ((column + 1) * 53) / 512
  188. local yend = ((row + 1) * 70) / 512
  189. arrow:SetTexCoord(xstart,xend,ystart,yend)
  190. else
  191. if showDownArrow then
  192. showDownArrow = false
  193. QH_Arrow_SetScale()
  194. arrow:SetTexture("Interface\\AddOns\\QuestHelper\\arrow_image")
  195. showDownArrow = false
  196. end
  197. local angle = atan2(-dx, -dy) / 360 * (math.pi * 2) -- degrees. seriously what
  198. --if angle < 0 then angle = angle + math.pi * 2 end
  199. local player = GetPlayerFacing()
  200. angle = angle - player
  201. local perc = math.abs((math.pi - math.abs(angle)) / math.pi)
  202. if perc > 1 then perc = 2 - perc end -- siiigh
  203. local gr,gg,gb = 0, 1, 0
  204. local mr,mg,mb = 1, 1, 0
  205. local br,bg,bb = 1, 0, 0
  206. local r,g,b = ColorGradient(perc, br, bg, bb, mr, mg, mb, gr, gg, gb)
  207. arrow:SetVertexColor(r,g,b)
  208. local cell = floor(angle / (math.pi * 2) * 108 + 0.5) % 108
  209. local column = cell % 9
  210. local row = floor(cell / 9)
  211. local xstart = (column * 56) / 512
  212. local ystart = (row * 42) / 512
  213. local xend = ((column + 1) * 56) / 512
  214. local yend = ((row + 1) * 42) / 512
  215. arrow:SetTexCoord(xstart,xend,ystart,yend)
  216. end
  217. -- Calculate the TTA every second (%01d:%02d)
  218. --[[
  219. if elapsed then
  220. tta_throttle = tta_throttle + elapsed
  221. if tta_throttle >= 1.0 then
  222. -- Calculate the speed in yards per sec at which we're moving
  223. local current_speed = (last_distance - dist) / tta_throttle
  224. if last_distance == 0 then
  225. current_speed = 0
  226. end
  227. if speed_count < 2 then
  228. speed = (speed + current_speed) / 2
  229. speed_count = speed_count + 1
  230. else
  231. speed_count = 0
  232. speed = current_speed
  233. end
  234. if speed > 0 then
  235. local eta = math.abs(dist / speed)
  236. tta:SetFormattedText("%01d:%02d", eta / 60, eta % 60)
  237. else
  238. tta:SetText("")
  239. end
  240. last_distance = dist
  241. tta_throttle = 0
  242. end
  243. end
  244. ]]
  245. end
  246. QH_Hook(wayframe, "OnUpdate", OnUpdate)
  247. local function spacer()
  248. local htex = QuestHelper:CreateIconTexture(item, 10)
  249. htex:SetVertexColor(1, 1, 1, 0)
  250. return htex
  251. end
  252. function QH_Arrow_PopulateMenu(menu)
  253. local hide = QuestHelper:CreateMenuItem(menu, QuestHelper_Pref.arrow and QHText("QH_BUTTON_HIDE") or QHText("QH_BUTTON_SHOW"))
  254. hide:SetFunction(function () QuestHelper:ToggleArrow() end)
  255. --hide:AddTexture(spacer(), true)
  256. --hide:AddTexture(spacer(), false)
  257. local lock = QuestHelper:CreateMenuItem(menu, "Lock")
  258. local ltex = QuestHelper:CreateIconTexture(item, 10)
  259. lock:SetFunction(function () QuestHelper_Pref.arrow_locked = not QuestHelper_Pref.arrow_locked end)
  260. lock:AddTexture(ltex, true)
  261. lock:AddTexture(spacer(), false)
  262. ltex:SetVertexColor(1, 1, 1, QuestHelper_Pref.arrow_locked and 1 or 0)
  263. local scale = QuestHelper:CreateMenuItem(menu, "Arrow Scale")
  264. local scale_menu = QuestHelper:CreateMenu()
  265. scale:SetSubmenu(scale_menu)
  266. scale:AddTexture(spacer(), true)
  267. for i = 5, 15 do
  268. local it = QuestHelper:CreateMenuItem(scale_menu, string.format("%d%%", i * 10))
  269. local ix = i
  270. it:SetFunction(function () QH_Arrow_SetScale(ix / 10) end)
  271. local icon = QuestHelper:CreateIconTexture(item, 10)
  272. if QuestHelper_Pref.arrow_arrowsize == ix / 10 then
  273. icon:SetVertexColor(1, 1, 1, 1)
  274. else
  275. icon:SetVertexColor(1, 1, 1, 0)
  276. end
  277. it:AddTexture(icon)
  278. end
  279. local tscale = QuestHelper:CreateMenuItem(menu, "Text Scale")
  280. local tscale_menu = QuestHelper:CreateMenu()
  281. tscale:SetSubmenu(tscale_menu)
  282. tscale:AddTexture(spacer(), true)
  283. for i = 5, 15 do
  284. local it = QuestHelper:CreateMenuItem(tscale_menu, string.format("%d%%", i * 10))
  285. local ix = i
  286. it:SetFunction(function () QH_Arrow_SetTextScale(ix / 10) end)
  287. local icon = QuestHelper:CreateIconTexture(item, 10)
  288. if QuestHelper_Pref.arrow_textsize == ix / 10 then
  289. icon:SetVertexColor(1, 1, 1, 1)
  290. else
  291. icon:SetVertexColor(1, 1, 1, 0)
  292. end
  293. it:AddTexture(icon)
  294. end
  295. local reset = QuestHelper:CreateMenuItem(menu, QHText("SETTINGS_MENU_ARROW_RESET"))
  296. reset:SetFunction(function () QH_Arrow_Reset() end)
  297. end
  298. local function WayFrame_OnClick(self, button)
  299. local menu = QuestHelper:CreateMenu()
  300. QuestHelper:CreateMenuTitle(menu, QHText("SETTINGS_ARROWLINK_ARROW"))
  301. QH_Arrow_PopulateMenu(menu)
  302. menu:ShowAtCursor()
  303. end
  304. wayframe:RegisterForClicks("RightButtonUp")
  305. QH_OnUpdate(OnUpdate)