Compare with Previous | Blame | View Log
--[[ Plugin that shows popup messages ]] ---------------------------------- -- Create plugin local RW = LibStub("AceAddon-3.0"):GetAddon("Raid Watch") local plugin = RW:Plugin("MessageFrame", "LibSink-2.0") if not plugin then return end ---------------------------------- -- Locals local L = LibStub("AceLocale-3.0"):GetLocale("RW2-Plugin-Messages") local LB = LibStub("AceLocale-3.0"):GetLocale("RW2-Plugin-Base") local LSM = LibStub("LibSharedMedia-3.0") local Colors local Utils = RW.Utils local nrSlots = 5 local db ---------------------------------- -- Init function plugin:OnRegister() local defaults = { profile = { Width = 180, PluginEnabled = true, GrowUp = true, Font = "accid", FontSize = 23, FontFlags = "OUTLINE", FadeOutTime = 10, SlotHeight = 30, sink20OutputSink = "RW", ScaleUpTime = 0.3, ScaleDownTime = 0.6, DefaultSound = "RW: Bell", PlaySound = true, ChatOutput = true, DefaultColor = {0.39, 0.67, 0.87, 1}, x = 0, y = 0, } } self.db = RW.db:RegisterNamespace(self:GetName(), defaults) db = self.db.profile -- Register for LibSink for message output selection self:SetSinkStorage(self.db.profile) self:RegisterSink("RW", "Raid Watch", "Messages trough RW", "AddMessage") local t = { type = "group", name = "test", args = { sink = plugin:GetSinkAce3OptionsDataTable() } } t.args.sink.guiInline = true LibStub("AceConfig-3.0"):RegisterOptionsTable("RW-Messages", t) Colors = RW:GetPlugin("Colors") self.db.RegisterCallback(self, "OnProfileChanged", "Reset") self.db.RegisterCallback(self, "OnProfileCopied", "Reset") self.db.RegisterCallback(self, "OnProfileReset", "Reset") end function plugin:PluginEnable() if not db.PluginEnabled then self:Disable() return end self:RegisterCallback("ConfigMode") self:RegisterCallback("MessageShow") end function plugin:PluginDisable() end ---------------------------------- -- Anchor local function dragStart(self) self:StartMoving() end local function dragStop(self) self:StopMovingOrSizing() local scale = self:GetEffectiveScale() / UIParent:GetEffectiveScale() local x, y = self:GetCenter() x, y = x * scale, y * scale x = x - GetScreenWidth()/2 y = y - GetScreenHeight()/2 db.x = x db.y = y RW.Callbacks:Fire("RefreshOptions") end local function onUpdate(self, elapsed) local showing = false for i, s in next, plugin.slots do if s:IsShown() then showing = true s.ScaleTime = s.ScaleTime + elapsed -- Scale the text up untill ScaleUpTime is reached if s.ScaleTime < db.ScaleUpTime then s:SetScale(s:GetScale() + elapsed * 3) -- Scale down untill ScaleDownTime is reached elseif s.ScaleTime <= db.ScaleDownTime then local newScale = s:GetScale() - elapsed * 3 s:SetScale(newScale > 0 and newScale or 0.01) -- Else reset the scale and text size else s:SetScale(1) end FadingFrame_OnUpdate(s) else end end if not showing then self:SetScript("OnUpdate", nil) end end function plugin:CreateAnchor() local frame = Utils:CreateAnchor("MessageAnchor", UIParent, "Messages") local s = frame:GetEffectiveScale() frame:SetScript("OnDragStart", dragStart) frame:SetScript("OnDragStop", dragStop) self.anchor = frame self:Reset() local updateFrame = CreateFrame("Frame", nil, UIParent) self.eventFrame = updateFrame end function plugin:Reset(var1, var2, var3) db = self.db.profile self:SetSinkStorage(self.db.profile) if self.anchor then local frame = self.anchor local scale = frame:GetEffectiveScale() / UIParent:GetEffectiveScale() frame:ClearAllPoints() frame:SetPoint("CENTER", UIParent, "CENTER", db.x / scale, db.y / scale) frame:SetWidth(db.Width) if self.slots then for i, slot in pairs(self.slots) do slot:SetHeight(db.SlotHeight) slot.icon:SetWidth(db.SlotHeight - 4) slot.icon:SetHeight(db.SlotHeight - 4) slot.text:SetFont(LSM:Fetch("font", db.Font), db.FontSize, db.FontFlags) end end end end ---------------------------------- -- Frame handling -- Creates and returns one message slot function plugin:GetMessageFrame() if not self.anchor then self:CreateAnchor() end -- Create message slots if not self.slots then self.slots = {} for i = 1, nrSlots do local frame = CreateFrame("Frame", "SlotFrame_"..i, self.eventFrame) frame:SetWidth(1) frame:SetHeight(db.SlotHeight) local str = frame:CreateFontString("RWMessageSlot_"..i, "ARTWORK") str:SetPoint("CENTER") str:SetFont(LSM:Fetch("font", db.Font), db.FontSize, db.FontFlags) local icon = frame:CreateTexture(nil, "OVERLAY") icon:SetTexCoord(0.07, 0.93, 0.07, 0.93) icon:SetPoint("RIGHT", str, "LEFT", -4, 0) icon:SetWidth(db.SlotHeight - 4) icon:SetHeight(db.SlotHeight - 4) local iconback = frame:CreateTexture(nil, "ARTOWRK") iconback:SetTexture(0, 0, 0, 1) iconback:SetPoint("TOPLEFT", icon, -3, 3) iconback:SetPoint("BOTTOMRIGHT", icon, 3, -3) FadingFrame_SetFadeInTime(frame, 0.4) FadingFrame_SetFadeOutTime(frame, 3) frame.text = str frame.icon = icon frame:Hide() self.slots[i] = frame end end -- Re-arrange slot, so that slot 1 is always the next one to be used (n:th slot becomes slot nr 1) local slots = self.slots local old = slots[#slots] for i = #slots, 1, -1 do if i > 1 then slots[i] = slots[i-1] else slots[i] = old end end -- Position the slots according to the slots order visually for i, t in pairs(self.slots) do t:ClearAllPoints() if i == 1 then t:SetPoint(db.GrowUp and "BOTTOM" or "TOP", self.anchor, db.GrowUp and "TOP" or "BOTTOM", 0, db.GrowUp and 3 or -3) else t:SetPoint(db.GrowUp and "BOTTOM" or "TOP", self.slots[i-1], db.GrowUp and "TOP" or "BOTTOM", 0, db.GrowUp and 3 or -3) end FadingFrame_SetHoldTime(t, db.FadeOutTime) end -- Return the "oldest" slot to be re-used return self.slots[1] end -- Internal function that is called from LibSink function plugin:AddMessage(addon, text, r, g, b, font, size, outline, sticky, loc, icon) local slot = self:GetMessageFrame() slot.text:SetText(text) slot.text:SetTextColor(r, g, b) slot.icon:SetTexture(icon) slot.ScaleTime = 0 FadingFrame_Show(slot) if not self.eventFrame:GetScript("OnUpdate") then self.eventFrame:SetScript("OnUpdate", onUpdate) end end ---------------------------------- -- Message Handling --- Show a new message as popup -- @param text The text to be shown -- @param r Red component to the color -- @param g Green component to the color -- @param b Blue component to the color -- @param a Alpha component to the color -- @param icon Optional icon to show function plugin:MessageShow(event, text, r, g, b, a, icon, sound, module) if not r or not g or not b then r, g, b, a = unpack(db.DefaultColor) end if db.PlaySound then PlaySoundFile(LSM:Fetch("sound", sound or db.DefaultSound)) end if db.ChatOutput and module then module:Msg((icon and "|T"..icon..":20|t " or "")..("|cff%x%x%x"..(text or "").."|r"):format(r*255, g*255, b*255)) end self:Pour(text or "Test message", r, g, b, nil, nil, nil, nil, nil, icon) end -- Enter configuration mode function plugin:ConfigMode(event, start) local function randomMessage() local spellName, rank, icon = Utils:GetRandomSpell() plugin:MessageShow("MessageShow", spellName ..((rank ~= "" or not rank) and (" ("..rank..")" ) or "" ), math.random(), math.random(), math.random(), math.random(), icon, "None") end if not self.anchor then self:CreateAnchor() end if start then self.anchor:Show() self:ScheduleRepeatingTimer(randomMessage, 2) else self.anchor:Hide() self:CancelAllTimers() end end --------------------------------------------- do function plugin:GetOptions() return LB.PLUGINS, LB.ALERT_PLUGINS, L.NAME, self.GetGUI, [[Interface\Icons\INV_MISC_NOTE_02]] end local function changeCallback() db.SlotHeight = db.FontSize plugin:Reset() end local LastTab local TabSelected function plugin:GetGUI() local self = self or plugin local UIF = LibStub("LibGUIFactory-1.0"):GetFactory("RW") local AceGUI = LibStub("AceGUI-3.0") local group, label, slider, check, igroup, button, color, select group = AceGUI:Create("ScrollFrame") group:SetLayout("Flow") label = UIF:MainTitleLabel(L.NAME) group:AddChild(label) igroup = UIF:InlineGroup("") group:AddChild(igroup) label = UIF:NormalText(L.DESC) label:SetImage([[Interface\Icons\INV_MISC_NOTE_02]]) igroup:AddChild(label) check = UIF:CheckBox(LB.ENABLED, db, "PluginEnabled", function() if not db.PluginEnabled then self:Disable() else self:Enable() end end) group:AddChild(check) local tgroup = UIF:TabGroup() group:AddChild(tgroup) tgroup:SetTabs({ {text = "Misc", value = "Misc"}, {text = LB.POSITION, value = "Position"}, {text = "Output", value = "Output"}, {text = LB.FONT, value = "Font"}, }) tgroup:SetCallback("OnGroupSelected", TabSelected) tgroup:SelectTab(LastTab or "Misc") button = UIF:Button(LB.TEST, function() local spellName, rank, icon = Utils:GetRandomSpell() RW.Callbacks:Fire("MessageShow", spellName ..((rank ~= "" or not rank) and (" ("..rank..")" ) or "" ), nil, nil, nil, nil, icon, nil, plugin) end) group:AddChild(button) button = UIF:Button(LB.RESET, function() plugin.db:ResetProfile() end) button:SetUserData("confirm", true) button:SetUserData("TriggerGlobalUpdate", true) group:AddChild(button) group:FixScroll() return group end TabSelected = function(self, evemt, tab) local UIF = LibStub("LibGUIFactory-1.0"):GetFactory("RW") local AceGUI = LibStub("AceGUI-3.0") self:ReleaseChildren() LastTab = tab if tab == "Misc" then local check = UIF:CheckBox(LB.PLAY_SOUND, db, "PlaySound") check:SetFullWidth(false) self:AddChild(check) local select = AceGUI:Create("LSM30_Sound") select:SetLabel(LB.DEFAULT_SOUND) select:SetList() select:SetValue(db["DefaultSound"]) select:SetUserData("db", db) select:SetUserData("key", "DefaultSound") select:SetCallback("OnValueChanged", function(widget, event, value) db["DefaultSound"] = value end) self:AddChild(select) check = UIF:CheckBox(LB.GROW_UP, db, "GrowUp") check:SetDescription(LB.GROW_UP_DESC) check:SetFullWidth(false) self:AddChild(check) check = UIF:CheckBox(L.CHAT_OUTPUT, db, "ChatOutput") check:SetDescription("Should the messages also be output to your chatwindow?") check:SetFullWidth(false) self:AddChild(check) local color = UIF:ColorSelect(LB.DEFAULT_COLOR, db, "DefaultColor") self:AddChild(color) local slider = UIF:Slider(L.FADE_OUT_TIME, db, "FadeOutTime", 1, 15, 0.5, changeCallback) self:AddChild(slider) elseif tab == "Position" then self:AddChild(UIF:Slider("X", db, "x", -floor(GetScreenWidth() * UIParent:GetEffectiveScale()), floor(GetScreenWidth() * UIParent:GetEffectiveScale()), 1, changeCallback, 0.5)) self:AddChild(UIF:Slider("Y", db, "y", -floor(GetScreenHeight() * UIParent:GetEffectiveScale()), floor(GetScreenHeight() * UIParent:GetEffectiveScale()), 1, changeCallback, 0.5)) elseif tab == "Output" then local sinkgroup = AceGUI:Create("SimpleGroup") sinkgroup:SetLayout("Fill") sinkgroup:SetFullWidth(true) self:AddChild(sinkgroup) LibStub("AceConfigDialog-3.0"):Open("RW-Messages", sinkgroup) elseif tab == "Font" then self:AddChild(UIF:LSMDropdown("font", LB.FONT, db, "Font", changeCallback, 0.5)) self:AddChild(UIF:Dropdown(LB.FONT_OUTLINE, db, "FontFlags", changeCallback, Utils.Constants.FontFlagList, 0.5)) self:AddChild(UIF:Slider(LB.FONT_SIZE, db, "FontSize", 1, 50, 1, changeCallback, 0.5)) end self:DoLayout() self.parent:DoLayout() end end