Quantcast

* Re-working the internals of TomTom yet again. Tooltips for minimap nodes should work

James Whitehead Ii [03-09-08 - 11:04]
* Re-working the internals of TomTom yet again.  Tooltips for minimap nodes should work
Filename
TomTom.lua
TomTom_CrazyArrow.lua
TomTom_Waypoints.lua
diff --git a/TomTom.lua b/TomTom.lua
index 2eecd0b..9dd94dd 100755
--- a/TomTom.lua
+++ b/TomTom.lua
@@ -185,8 +185,7 @@ function WorldMapButton_OnClick(...)
 			return
 		end

-		local point = TomTom:SetWaypoint(c,z,x*100,y*100)
-		TomTom:SetCrazyArrow(point, 15)
+		local uid = TomTom:AddWaypoint(c,z,x*100,y*100)
     else
         return Orig_WorldMapButton_OnClick(...)
     end
@@ -209,6 +208,17 @@ local function WaypointCallback(event, arg1, arg2, arg3)
 	end
 end

+callbackTbl = {
+	tooltip_show = function(event, tooltip, uid, dist)
+		tooltip:SetText("TomTom waypoint")
+		tooltip:AddLine(string.format("%s yards away", math.floor(dist)), 1, 1, 1)
+		tooltip:Show()
+	end,
+	tooltip_update = function(event, tooltip, uid, dist)
+		tooltip.lines[2]:SetFormattedText("%s yards away", math.floor(dist), 1, 1, 1)
+	end,
+}
+
 -- TODO: Make this not suck
 function TomTom:AddWaypoint(x,y,desc)
 	local oc,oz = Astrolabe:GetCurrentPlayerPosition()
@@ -223,12 +233,12 @@ function TomTom:AddWaypoint(x,y,desc)
 		return
 	end

-	local point = self:SetWaypoint(c, z, x, y, nil, nil, 10, WaypointCallback)
+	local point = self:SetWaypoint(c, z, x, y, callbackTbl)
 	self:SetCrazyArrow(point, self.db.profile.arrow.arrival)
 end

 function TomTom:AddZWaypoint(c,z,x,y,desc)
-	local point = self:SetWaypoint(c,z,x,y,nil,nil,10,WaypointCallback)
+	local point = self:SetWaypoint(c,z,x,y, callbackTbl)
 	self:SetCrazyArrow(point, self.db.profile.arrow.arrival)
 end

diff --git a/TomTom_CrazyArrow.lua b/TomTom_CrazyArrow.lua
index b67ce84..b79f666 100644
--- a/TomTom_CrazyArrow.lua
+++ b/TomTom_CrazyArrow.lua
@@ -116,7 +116,7 @@ local function OnUpdate(self, elapsed)
 		return
 	end

-	local dist,x,y = active_point:GetDistanceToWaypoint()
+	local dist,x,y = TomTom:GetDistanceToWaypoint(active_point)
 	if not dist then
 		self:Hide()
 		return
@@ -158,7 +158,7 @@ local function OnUpdate(self, elapsed)
 			showDownArrow = false
 		end

-		local angle = active_point:GetDirectionToWaypoint()
+		local angle = TomTom:GetDirectionToWaypoint(active_point)
 		local player = GetPlayerBearing()

 		angle = angle - player
diff --git a/TomTom_Waypoints.lua b/TomTom_Waypoints.lua
index db37649..ee4586b 100644
--- a/TomTom_Waypoints.lua
+++ b/TomTom_Waypoints.lua
@@ -21,57 +21,54 @@ do
 end

 -- Create a local table used as a frame pool
-local pool = {
-	minimap = {},
-	worldmap = {},
-}
+local pool = {}

--- Local declarations
-local Minimap_OnEnter,Minimap_OnLeave,Minimap_OnUpdate,Minimap_OnClick,Minimap_OnEvent
-local Arrow_OnUpdate
-local World_OnEnter,World_OnLeave,World_OnClick,World_OnEvent
-
-local WaypointClass = {}
+-- Create a mapping from uniqueID to waypoint
+local getuid,resolveuid
+do
+	local uidmap = {}
+	local uid = 0
+	function getuid(obj)
+		-- Ensure the object doesn't already have a uid mapping
+		for k,v in pairs(uidmap) do
+			if obj == v then
+				error("Attempt to re-use an object without clearing identifier")
+			end
+		end

-function WaypointClass:Show(minimap, worldmap)
-	local x = self.x / 100
-	local y = self.y / 100
+		-- Establish the new mapping
+		uid = uid + 1

-	if minimap then
-		Astrolabe:PlaceIconOnMinimap(self.minimap, self.c, self.z, x, y)
-	end
+		uidmap[uid] = obj

-	if worldmap then
-		local x, y = Astrolabe:PlaceIconOnWorldMap(WorldMapDetailFrame, self.worldmap, self.c, self.z, x, y)
-		self.worldmap:Show()
+		return uid
 	end
-end

-function WaypointClass:Hide(minimap, worldmap)
-	if minimap then
-		Astrolabe:RemoveIconFromMinimap(self.minimap)
-	end
+	function resolveuid(uid, remove)
+		-- Return the object that corresponds to the UID
+		local obj = uidmap[uid]
+		assert(obj, "Attempt to use out-of-date identifier")
+		if remove then
+			uidmap[uid] = nil
+		end

-	if worldmap then
-		Astrolabe:Hide()
+		return obj
 	end
 end

-function WaypointClass:GetDistanceToWaypoint()
-	return Astrolabe:GetDistanceToIcon(self.minimap)
-end
-
-function WaypointClass:GetDirectionToWaypoint()
-	return Astrolabe:GetDirectionToIcon(self.minimap)
-end
+-- Local declarations
+local Minimap_OnEnter,Minimap_OnLeave,Minimap_OnUpdate,Minimap_OnClick,Minimap_OnEvent
+local Arrow_OnUpdate
+local World_OnEnter,World_OnLeave,World_OnClick,World_OnEvent

-function TomTom:SetWaypoint(c, z, x, y, distances)
+function TomTom:SetWaypoint(c, z, x, y, callbacks)
 	-- Try to acquire a waypoint from the frame pool
-	local minimap = table.remove(pool.minimap)
-	local worldmap = table.remove(pool.worldmap)
+	local point = table.remove(pool)
+
+	if not point then
+		point = {}

-	if not minimap then
-		minimap = CreateFrame("Button", nil, Minimap)
+		local minimap = CreateFrame("Button", nil, Minimap)
 		minimap:SetHeight(20)
 		minimap:SetWidth(20)
 		minimap:RegisterForClicks("RightButtonUp")
@@ -96,10 +93,8 @@ function TomTom:SetWaypoint(c, z, x, y, distances)
 		minimap:SetScript("OnClick", Minimap_OnClick)
 		minimap:RegisterEvent("PLAYER_ENTERING_WORLD")
 		minimap:SetScript("OnEvent", Minimap_OnEvent)
-	end

-	if not worldmap then
-		worldmap = CreateFrame("Button", nil, WorldMapDetailFrame)
+		local worldmap = CreateFrame("Button", nil, WorldMapDetailFrame)
 		worldmap:SetHeight(12)
 		worldmap:SetWidth(12)
 		worldmap:RegisterForClicks("RightButtonUp")
@@ -112,57 +107,79 @@ function TomTom:SetWaypoint(c, z, x, y, distances)
 		worldmap:SetScript("OnLeave", World_OnLeave)
 		worldmap:SetScript("OnClick", World_OnClick)
 		worldmap:SetScript("OnEvent", World_OnEvent)
+
+		point.worldmap = worldmap
+		point.minimap = minimap
 	end

-	-- Create a new waypoint object which wraps
-	local point = setmetatable({}, {__index=WaypointClass})
 	point.c = c
 	point.z = z
 	point.x = x
 	point.y = y
-	point.distances = distances
-	point.minimap = minimap
-	point.worldmap = worldmap
+	point.callbacks = callbacks

 	-- Link the actual frames back to the waypoint object
-	minimap.point = point
-	worldmap.point = point
+	point.minimap.point = point
+	point.worldmap.point = point

-	-- Place the waypoints
-	point:Show(true, true)
+	-- Place the waypoint
+	local x,y = x/100,y/100
+	Astrolabe:PlaceIconOnMinimap(point.minimap, c, z, x, y)
+	Astrolabe:PlaceIconOnWorldMap(WorldMapDetailFrame, point.worldmap, c, z, x, y)

-	return point
+	point.uid = getuid(point)
+	return point.uid
 end

-function TomTom:ClearWaypoint(point)
-	if point then
-		point:Hide(true, true)
-		table.insert(pool.minimap, point.minimap)
-		table.insert(pool.worldmap, point.worldmap)
-		point.minimap = nil
-		point.worldmap = nil
-	end
+function TomTom:RemoveWaypoint(uid)
+	local point = resolveuid(uid, true)
+	Astrolabe:RemoveIconFromMinimap(point.minimap)
+	point.minimap:Hide()
+	point.worldmap:Hide()
+	table.insert(pool, point)
+end
+
+function TomTom:GetDistanceToWaypoint(uid)
+	local point = resolveuid(uid)
+	return Astrolabe:GetDistanceToIcon(point.minimap)
+end
+
+function TomTom:GetDirectionToWaypoint(uid)
+	local point = resolveuid(uid)
+	return Astrolabe:GetDirectionToIcon(point.minimap)
 end

 do
-	local tooltip_icon,tooltip_callback
+	local tooltip_uid,tooltip_callbacks
+
+	local function tooltip_onupdate(self, elapsed)
+		if tooltip_callbacks and tooltip_callbacks.tooltip_update then
+			local dist,x,y = TomTom:GetDistanceToWaypoint(tooltip_uid)
+			tooltip_callbacks.tooltip_update("tooltip_update", tooltip, tooltip_uid, dist)
+		end
+	end

 	function Minimap_OnEnter(self, motion)
-		local data = self
+		local data = self.point.callbacks

-		tooltip_icon = self
-		tooltip_callback = data.callback
+		if data and data.tooltip_show then
+			local uid = self.point.uid
+			local dist,x,y = TomTom:GetDistanceToWaypoint(uid)
+
+			tooltip_uid = uid
+			tooltip_callbacks = data

-		if tooltip_callback then
-			local dist,x,y = Astrolabe:GetDistanceToIcon(self)
 			tooltip:SetOwner(self, "ANCHOR_CURSOR")
-
-			-- Callback: OnTooltipShown
-			-- arg1: The tooltip object
-			-- arg2: The distance to the icon in yards
-			-- arg3: Boolean value indicating the tooltip was just shown
-			tooltip_callback("OnTooltipShown", tooltip, dist, true)
+
+			data.tooltip_show("tooltip_show", tooltip, uid, dist)
 			tooltip:Show()
+
+			-- Set the update script if there is one
+			if data.tooltip_update then
+				tooltip:SetScript("OnUpdate", tooltip_onupdate)
+			else
+				tooltip:SetScript("OnUpdate", nil)
+			end
 		end
 	end