You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
480 lines
16 KiB
480 lines
16 KiB
---------------------------------------------------------
|
|
-- Module declaration
|
|
local HandyNotes = LibStub("AceAddon-3.0"):GetAddon("HandyNotes")
|
|
local HN = HandyNotes:NewModule("HandyNotes", "AceEvent-3.0", "AceConsole-3.0")
|
|
local L = LibStub("AceLocale-3.0"):GetLocale("HandyNotes", false)
|
|
|
|
local HBD = LibStub("HereBeDragons-2.0")
|
|
local PIN_DRAG_SCALE = 1.2
|
|
|
|
---------------------------------------------------------
|
|
-- Our db upvalue and db defaults
|
|
local db
|
|
local dbdata
|
|
local defaults = {
|
|
global = {
|
|
["*"] = {}, -- ["mapFile"] = {[coord] = {note data}, [coord] = {note data}}
|
|
},
|
|
profile = {
|
|
icon_scale = 1.0,
|
|
icon_alpha = 1.0,
|
|
},
|
|
}
|
|
|
|
---------------------------------------------------------
|
|
-- Localize some globals
|
|
local next = next
|
|
local wipe = wipe
|
|
local GameTooltip = GameTooltip
|
|
|
|
|
|
---------------------------------------------------------
|
|
-- Constants
|
|
-- An addon can replace this table or add to it directly, but keep in mind
|
|
-- notes are currently stored with the index number of the chosen icon.
|
|
HN.icons = {
|
|
[1] = UnitPopupButtons.RAID_TARGET_1, -- Star
|
|
[2] = UnitPopupButtons.RAID_TARGET_2, -- Circle
|
|
[3] = UnitPopupButtons.RAID_TARGET_3, -- Diamond
|
|
[4] = UnitPopupButtons.RAID_TARGET_4, -- Triangle
|
|
[5] = UnitPopupButtons.RAID_TARGET_5, -- Moon
|
|
[6] = UnitPopupButtons.RAID_TARGET_6, -- Square
|
|
[7] = UnitPopupButtons.RAID_TARGET_7, -- Cross
|
|
[8] = UnitPopupButtons.RAID_TARGET_8, -- Skull
|
|
[9] = {text = MINIMAP_TRACKING_AUCTIONEER, icon = "Interface\\Minimap\\Tracking\\Auctioneer"},
|
|
[10] = {text = MINIMAP_TRACKING_BANKER, icon = "Interface\\Minimap\\Tracking\\Banker"},
|
|
[11] = {text = MINIMAP_TRACKING_BATTLEMASTER, icon = "Interface\\Minimap\\Tracking\\BattleMaster"},
|
|
[12] = {text = MINIMAP_TRACKING_FLIGHTMASTER, icon = "Interface\\Minimap\\Tracking\\FlightMaster"},
|
|
[13] = {text = MINIMAP_TRACKING_INNKEEPER, icon = "Interface\\Minimap\\Tracking\\Innkeeper"},
|
|
[14] = {text = MINIMAP_TRACKING_MAILBOX, icon = "Interface\\Minimap\\Tracking\\Mailbox"},
|
|
[15] = {text = MINIMAP_TRACKING_REPAIR, icon = "Interface\\Minimap\\Tracking\\Repair"},
|
|
[16] = {text = MINIMAP_TRACKING_STABLEMASTER, icon = "Interface\\Minimap\\Tracking\\StableMaster"},
|
|
[17] = {text = MINIMAP_TRACKING_TRAINER_CLASS, icon = "Interface\\Minimap\\Tracking\\Class"},
|
|
[18] = {text = MINIMAP_TRACKING_TRAINER_PROFESSION, icon = "Interface\\Minimap\\Tracking\\Profession"},
|
|
[19] = {text = MINIMAP_TRACKING_TRIVIAL_QUESTS, icon = "Interface\\Minimap\\Tracking\\TrivialQuests"},
|
|
[20] = {text = MINIMAP_TRACKING_VENDOR_AMMO, icon = "Interface\\Minimap\\Tracking\\Ammunition"},
|
|
[21] = {text = MINIMAP_TRACKING_VENDOR_FOOD, icon = "Interface\\Minimap\\Tracking\\Food"},
|
|
[22] = {text = MINIMAP_TRACKING_VENDOR_POISON, icon = "Interface\\Minimap\\Tracking\\Poisons"},
|
|
[23] = {text = MINIMAP_TRACKING_VENDOR_REAGENT, icon = "Interface\\Minimap\\Tracking\\Reagents"},
|
|
[24] = {text = FACTION_ALLIANCE, icon = "Interface\\TargetingFrame\\UI-PVP-Alliance",
|
|
tCoordLeft = 0.05, tCoordRight = 0.65, tCoordTop = 0, tCoordBottom = 0.6},
|
|
[25] = {text = FACTION_HORDE, icon = "Interface\\TargetingFrame\\UI-PVP-Horde",
|
|
tCoordLeft = 0.05, tCoordRight = 0.65, tCoordTop = 0, tCoordBottom = 0.6},
|
|
[26] = {text = FACTION_STANDING_LABEL4, icon = "Interface\\TargetingFrame\\UI-PVP-FFA",
|
|
tCoordLeft = 0.05, tCoordRight = 0.65, tCoordTop = 0, tCoordBottom = 0.6},
|
|
[27] = {text = ARENA, icon = "Interface\\PVPFrame\\PVP-ArenaPoints-Icon"},
|
|
[28] = {text = L["Portal"], icon = "Interface\\Icons\\Spell_Arcane_PortalDalaran"},
|
|
}
|
|
|
|
|
|
---------------------------------------------------------
|
|
-- Plugin Handlers to HandyNotes
|
|
|
|
local HNHandler = {}
|
|
|
|
function HNHandler:OnEnter(mapID, coord)
|
|
if ( self:GetCenter() > UIParent:GetCenter() ) then -- compare X coordinate
|
|
GameTooltip:SetOwner(self, "ANCHOR_LEFT")
|
|
else
|
|
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
|
|
end
|
|
local title = dbdata[mapID][coord].title
|
|
local desc = dbdata[mapID][coord].desc
|
|
if title == "" and desc == "" then title = L["(No Title)"] end
|
|
if title == "" and desc ~= "" then title = desc desc = nil end
|
|
GameTooltip:SetText(title)
|
|
GameTooltip:AddLine(desc, nil, nil, nil, true)
|
|
GameTooltip:Show()
|
|
end
|
|
|
|
function HNHandler:OnLeave(mapID, coord)
|
|
GameTooltip:Hide()
|
|
end
|
|
|
|
local function deletePin(button, mapID, coord)
|
|
local HNEditFrame = HN.HNEditFrame
|
|
if HNEditFrame.coord == coord and HNEditFrame.mapID == mapID then
|
|
HNEditFrame:Hide()
|
|
end
|
|
dbdata[mapID][coord] = nil
|
|
HN:SendMessage("HandyNotes_NotifyUpdate", "HandyNotes")
|
|
end
|
|
|
|
local function editPin(button, mapID, coord)
|
|
local HNEditFrame = HN.HNEditFrame
|
|
HNEditFrame.x, HNEditFrame.y = HandyNotes:getXY(coord)
|
|
HNEditFrame.coord = coord
|
|
HNEditFrame.mapID = mapID
|
|
HNEditFrame:Hide() -- Hide first to trigger the OnShow handler
|
|
HNEditFrame:Show()
|
|
end
|
|
|
|
local function addTomTomWaypoint(button, mapID, coord)
|
|
if TomTom then
|
|
local x, y = HandyNotes:getXY(coord)
|
|
TomTom:AddWaypoint(mapID, x, y, {
|
|
title = dbdata[mapID][coord].title,
|
|
persistent = nil,
|
|
minimap = true,
|
|
world = true
|
|
})
|
|
end
|
|
end
|
|
|
|
do
|
|
local isMoving = false
|
|
local movingPinScale = nil
|
|
local info = {}
|
|
local clickedMapID = nil
|
|
local clickedCoord = nil
|
|
local function generateMenu(button, level)
|
|
if (not level) then return end
|
|
for k in pairs(info) do info[k] = nil end
|
|
if (level == 1) then
|
|
-- Create the title of the menu
|
|
info.isTitle = 1
|
|
info.text = L["HandyNotes"]
|
|
info.notCheckable = 1
|
|
local t = HN.icons[dbdata[clickedMapID][clickedCoord].icon]
|
|
info.icon = t.icon
|
|
info.tCoordLeft = t.tCoordLeft
|
|
info.tCoordRight = t.tCoordRight
|
|
info.tCoordTop = t.tCoordTop
|
|
info.tCoordBottom = t.tCoordBottom
|
|
UIDropDownMenu_AddButton(info, level)
|
|
|
|
-- Edit menu item
|
|
info.disabled = nil
|
|
info.isTitle = nil
|
|
info.notCheckable = nil
|
|
info.icon = nil
|
|
info.tCoordLeft = nil
|
|
info.tCoordRight = nil
|
|
info.tCoordTop = nil
|
|
info.tCoordBottom = nil
|
|
info.text = L["Edit Handy Note"]
|
|
info.func = editPin
|
|
info.arg1 = clickedMapID
|
|
info.arg2 = clickedCoord
|
|
UIDropDownMenu_AddButton(info, level)
|
|
|
|
-- Delete menu item
|
|
info.text = L["Delete Handy Note"]
|
|
info.func = deletePin
|
|
info.arg1 = clickedMapID
|
|
info.arg2 = clickedCoord
|
|
UIDropDownMenu_AddButton(info, level)
|
|
|
|
if TomTom then
|
|
info.text = L["Add this location to TomTom waypoints"]
|
|
info.func = addTomTomWaypoint
|
|
info.arg1 = clickedMapID
|
|
info.arg2 = clickedCoord
|
|
UIDropDownMenu_AddButton(info, level)
|
|
end
|
|
|
|
-- Close menu item
|
|
info.text = CLOSE
|
|
info.func = function() CloseDropDownMenus() end
|
|
info.arg1 = nil
|
|
info.arg2 = nil
|
|
info.notCheckable = 1
|
|
UIDropDownMenu_AddButton(info, level)
|
|
|
|
-- Add the dragging hint
|
|
info.isTitle = 1
|
|
info.func = nil
|
|
info.text = L["|cFF00FF00Hint: |cffeda55fCtrl+Shift+LeftDrag|cFF00FF00 to move a note"]
|
|
UIDropDownMenu_AddButton(info, level)
|
|
end
|
|
end
|
|
local HandyNotes_HandyNotesDropdownMenu = CreateFrame("Frame", "HandyNotes_HandyNotesDropdownMenu")
|
|
HandyNotes_HandyNotesDropdownMenu.displayMode = "MENU"
|
|
HandyNotes_HandyNotesDropdownMenu.initialize = generateMenu
|
|
|
|
function HNHandler:OnClick(button, down, mapID, coord)
|
|
if button == "RightButton" and not down then
|
|
clickedMapID = mapID
|
|
clickedCoord = coord
|
|
ToggleDropDownMenu(1, nil, HandyNotes_HandyNotesDropdownMenu, self, 0, 0)
|
|
elseif button == "LeftButton" and down and IsControlKeyDown() and IsShiftKeyDown() then
|
|
-- Only move if we're viewing the same map as the icon's map
|
|
if mapID == WorldMapFrame:GetMapID() then
|
|
isMoving = true
|
|
movingPinScale = self:GetScale()
|
|
local x, y = self:GetCenter()
|
|
local s = self:GetEffectiveScale() / UIParent:GetEffectiveScale()
|
|
self:ClearAllPoints()
|
|
self:SetParent(UIParent)
|
|
self:SetScale(PIN_DRAG_SCALE)
|
|
self:SetPoint("CENTER", UIParent, "BOTTOMLEFT", x * s / PIN_DRAG_SCALE, y * s / PIN_DRAG_SCALE)
|
|
self:SetFrameStrata("TOOLTIP")
|
|
self:StartMoving()
|
|
end
|
|
elseif isMoving and not down then
|
|
isMoving = false
|
|
self:StopMovingOrSizing()
|
|
local x, y = self:GetCenter()
|
|
if movingPinScale then
|
|
x = x * PIN_DRAG_SCALE / movingPinScale
|
|
y = y * PIN_DRAG_SCALE / movingPinScale
|
|
self:SetScale(movingPinScale)
|
|
movingPinScale = nil
|
|
end
|
|
local s = self:GetEffectiveScale() / WorldMapFrame.ScrollContainer.Child:GetEffectiveScale()
|
|
x = x * s - WorldMapFrame.ScrollContainer.Child:GetLeft()
|
|
y = y * s - WorldMapFrame.ScrollContainer.Child:GetTop()
|
|
self:ClearAllPoints()
|
|
self:SetParent(WorldMapFrame.ScrollContainer.Child)
|
|
self:SetPoint("CENTER", WorldMapFrame.ScrollContainer.Child, "TOPLEFT", x / self:GetScale(), y / self:GetScale())
|
|
self:SetFrameStrata("TOOLTIP")
|
|
self:SetUserPlaced(false)
|
|
|
|
-- Get the new coordinate
|
|
x = x / WorldMapFrame.ScrollContainer.Child:GetWidth()
|
|
y = -y / WorldMapFrame.ScrollContainer.Child:GetHeight()
|
|
-- Move the button back into the map if it was dragged outside
|
|
if x < 0.001 then x = 0.001 end
|
|
if x > 0.999 then x = 0.999 end
|
|
if y < 0.001 then y = 0.001 end
|
|
if y > 0.999 then y = 0.999 end
|
|
local newCoord = HandyNotes:getCoord(x, y)
|
|
-- Search in 4 directions till we find an unused coord
|
|
local count = 0
|
|
local zoneData = dbdata[mapID]
|
|
while true do
|
|
if not zoneData[newCoord + count] then
|
|
zoneData[newCoord + count] = zoneData[coord]
|
|
break
|
|
elseif not zoneData[newCoord - count] then
|
|
zoneData[newCoord - count] = zoneData[coord]
|
|
break
|
|
elseif not zoneData[newCoord + count * 10000] then
|
|
zoneData[newCoord + count*10000] = zoneData[coord]
|
|
break
|
|
elseif not zoneData[newCoord - count * 10000] then
|
|
zoneData[newCoord - count*10000] = zoneData[coord]
|
|
break
|
|
end
|
|
count = count + 1
|
|
end
|
|
dbdata[mapID][coord] = nil
|
|
HN:SendMessage("HandyNotes_NotifyUpdate", "HandyNotes")
|
|
end
|
|
end
|
|
end
|
|
|
|
do
|
|
local tablepool = setmetatable({}, {__mode = 'k'})
|
|
|
|
-- This is a custom iterator we use to iterate over every node in a given zone
|
|
local function iter(t, prestate)
|
|
if not t then return end
|
|
local data = t.data
|
|
local state, value = next(data, prestate)
|
|
if value then
|
|
return state, nil, HN.icons[value.icon], db.icon_scale, db.icon_alpha
|
|
end
|
|
wipe(t)
|
|
tablepool[t] = true
|
|
end
|
|
|
|
-- This is a funky custom iterator we use to iterate over every zone's nodes
|
|
-- in a given continent + the continent itself
|
|
local function iterCont(t, prestate)
|
|
if not t then return end
|
|
local zone = t.C[t.Z]
|
|
local data = dbdata[zone]
|
|
local state, value
|
|
while zone do
|
|
if data then -- Only if there is data for this zone
|
|
state, value = next(data, prestate)
|
|
while state do -- Have we reached the end of this zone?
|
|
if value.cont or zone == t.contId then -- Show on continent?
|
|
return state, zone, HN.icons[value.icon], db.icon_scale, db.icon_alpha
|
|
end
|
|
state, value = next(data, state) -- Get next data
|
|
end
|
|
end
|
|
-- Get next zone
|
|
t.Z = next(t.C, t.Z)
|
|
zone = t.C[t.Z]
|
|
data = dbdata[zone]
|
|
prestate = nil
|
|
end
|
|
wipe(t)
|
|
tablepool[t] = true
|
|
end
|
|
|
|
function HNHandler:GetNodes2(uiMapId, minimap)
|
|
local C = HandyNotes:GetContinentZoneList(uiMapId) -- Is this a continent?
|
|
if C then
|
|
local tbl = next(tablepool) or {}
|
|
tablepool[tbl] = nil
|
|
tbl.C = C
|
|
tbl.Z = next(C)
|
|
tbl.contId = uiMapId
|
|
return iterCont, tbl, nil
|
|
else -- It is a zone
|
|
local tbl = next(tablepool) or {}
|
|
tablepool[tbl] = nil
|
|
tbl.data = dbdata[uiMapId]
|
|
return iter, tbl, nil
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
---------------------------------------------------------
|
|
-- HandyNotes core
|
|
|
|
function HN.OnCanvasClicked(mapCanvas, button, cursorX, cursorY)
|
|
local self = HN
|
|
if button == "RightButton" and IsAltKeyDown() and not IsControlKeyDown() and not IsShiftKeyDown() then
|
|
|
|
local coord = HandyNotes:getCoord(cursorX, cursorY)
|
|
local x, y = HandyNotes:getXY(coord)
|
|
|
|
-- Pass the data to the edit note frame
|
|
local HNEditFrame = self.HNEditFrame
|
|
HNEditFrame.x = x
|
|
HNEditFrame.y = y
|
|
HNEditFrame.coord = coord
|
|
HNEditFrame.mapID = mapCanvas:GetMapID()
|
|
HNEditFrame:Hide() -- Hide first to trigger the OnShow handler
|
|
HNEditFrame:Show()
|
|
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
-- Function to create a note where the player is
|
|
function HN:CreateNoteHere(arg1)
|
|
local mapID, x, y
|
|
|
|
if arg1 ~= "" then
|
|
-- Coordinates entered
|
|
x, y = string.match(strtrim(arg1), "([%d.]+)[, ]+([%d.]+)")
|
|
x, y = tonumber(x), tonumber(y)
|
|
if x and y and x > 1 and x < 100 and y > 1 and y < 100 then
|
|
-- Normalize coordinates to between 0 and 1
|
|
x, y = x/100, y/100
|
|
end
|
|
if not x or not y or x <= 0 or x >= 1 or y <= 0 or y >= 1 then
|
|
self:Print(L["Syntax:"].." /hnnew [x, y]")
|
|
return
|
|
end
|
|
mapID = HBD:GetPlayerZone()
|
|
else
|
|
-- No coordinates entered, get the coordinates of player
|
|
x, y, mapID = HBD:GetPlayerZonePosition()
|
|
end
|
|
|
|
if mapID and x and y then
|
|
local coord = HandyNotes:getCoord(x, y)
|
|
x, y = HandyNotes:getXY(coord)
|
|
|
|
-- Pass the data to the edit note frame
|
|
local HNEditFrame = self.HNEditFrame
|
|
HNEditFrame.x = x
|
|
HNEditFrame.y = y
|
|
HNEditFrame.coord = coord
|
|
HNEditFrame.mapID = mapID
|
|
HNEditFrame:Hide() -- Hide first to trigger the OnShow handler
|
|
HNEditFrame:Show()
|
|
else
|
|
self:Print(L["ERROR_CREATE_NOTE1"])
|
|
end
|
|
end
|
|
|
|
---------------------------------------------------------
|
|
-- Options table
|
|
local options = {
|
|
type = "group",
|
|
name = L["HandyNotes"],
|
|
desc = L["HandyNotes"],
|
|
get = function(info) return db[info.arg] end,
|
|
set = function(info, v)
|
|
db[info.arg] = v
|
|
HN:SendMessage("HandyNotes_NotifyUpdate", "HandyNotes")
|
|
end,
|
|
args = {
|
|
desc = {
|
|
name = L["These settings control the look and feel of the HandyNotes icons."],
|
|
type = "description",
|
|
order = 0,
|
|
},
|
|
icon_scale = {
|
|
type = "range",
|
|
name = L["Icon Scale"],
|
|
desc = L["The scale of the icons"],
|
|
min = 0.25, max = 2, step = 0.01,
|
|
arg = "icon_scale",
|
|
order = 10,
|
|
},
|
|
icon_alpha = {
|
|
type = "range",
|
|
name = L["Icon Alpha"],
|
|
desc = L["The alpha transparency of the icons"],
|
|
min = 0, max = 1, step = 0.01,
|
|
arg = "icon_alpha",
|
|
order = 20,
|
|
},
|
|
},
|
|
}
|
|
|
|
|
|
---------------------------------------------------------
|
|
-- Addon initialization, enabling and disabling
|
|
|
|
function HN:OnInitialize()
|
|
-- Set up our database
|
|
self.db = LibStub("AceDB-3.0"):New("HandyNotes_HandyNotesDB", defaults)
|
|
db = self.db.profile
|
|
dbdata = self.db.global
|
|
|
|
-- migrate data, if neccessary
|
|
local HBDMigrate = LibStub("HereBeDragons-Migrate")
|
|
|
|
local migration = {}
|
|
for zone in pairs(dbdata) do
|
|
if type(zone) == "string" then
|
|
migration[zone] = true
|
|
end
|
|
end
|
|
|
|
for zone in pairs(migration) do
|
|
local data = dbdata[zone]
|
|
dbdata[zone] = nil
|
|
|
|
local stripped_zone = zone:gsub("_terrain%d+$", "")
|
|
for coord, info in pairs(data) do
|
|
local newzone = HBDMigrate:GetUIMapIDFromMapFile(stripped_zone, info.level)
|
|
if newzone then
|
|
info.level = nil
|
|
if not dbdata[newzone] then
|
|
dbdata[newzone] = {}
|
|
end
|
|
dbdata[newzone][coord] = info
|
|
end
|
|
end
|
|
|
|
end
|
|
HNData = dbdata
|
|
|
|
-- Initialize our database with HandyNotes
|
|
HandyNotes:RegisterPluginDB("HandyNotes", HNHandler, options)
|
|
|
|
--WorldMapMagnifyingGlassButton:SetText(WorldMapMagnifyingGlassButton:GetText() .. L["\nAlt+Right Click To Add a HandyNote"])
|
|
WorldMapFrame:AddCanvasClickHandler(self.OnCanvasClicked)
|
|
|
|
-- Slash command
|
|
self:RegisterChatCommand("hnnew", "CreateNoteHere")
|
|
end
|
|
|
|
function HN:OnEnable()
|
|
end
|
|
|
|
function HN:OnDisable()
|
|
end
|
|
|