Mercurial > wow > sayit
diff SayIt.lua @ 0:24f337b9dfa0
Initial commit, testing .pkgmeta
| author | contrebasse |
|---|---|
| date | Sun, 08 May 2011 17:11:26 +0200 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SayIt.lua Sun May 08 17:11:26 2011 +0200 @@ -0,0 +1,604 @@ +--[[ TODO : +- Changer la couleur pour toutes les fenêtres de quête (possible ?) +- Chercher le texte pour les couleurs à partir de la somme des longueurs de texte précédents (incrémental), compliqué ! +- Modifier les variables statiques directement dans la fonction Paragraphes() (Bof...) +- Traduction +- Clic droit pour phrase perso +- Shif clic droit pour emote +- griser le choix des couleurs si pas de coloration +- reset des options (virer les couleurs foireuses...) +--]] + +--******************************************************** +-- +-- Déclarations de variables +-- +--******************************************************** +-- +-- Variables statiques +-- +local target_name = "" -- "" vide ou nom du npc +local text_table = {} -- table du texte à dire +local text_full = '' +local i_phrase = 1 -- indice de la prochaine phrase à dire +--local char_dits = 0 -- nombre de caractères prononcés, pour améliorer la recherche lors de la coloration +local max_phrase = 0 -- indice du nombre de phrases à dire +local gossip_button, quest_button, current_button +local TextFrame + +-- +-- Fonctions locales pour accélérer l'exécution +-- +local _G = _G +local GetUnitName = GetUnitName +local GetQuestText = GetQuestText +local GetProgressText = GetProgressText +local GetGossipText = GetGossipText +local GetRewardText = GetRewardText +local DEFAULT_CHAT_FRAME = DEFAULT_CHAT_FRAME +local UIErrorsFrame,UIErrorsFrame_OnEvent = UIErrorsFrame,UIErrorsFrame_OnEvent +local SendChatMessage = SendChatMessage +local GameTooltip = GameTooltip +local CreateFrame = CreateFrame +local IsShiftKeyDown,IsControlKeyDown = IsShiftKeyDown,IsControlKeyDown +local GossipFrame,QuestFrame = GossipFrame,QuestFrame +local GossipGreetingText = GossipGreetingText +local QuestProgressText = QuestProgressText +local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor; + +local tonumber = tonumber; +local string = string; +local string_format = string.format; + +local LibStub = LibStub; + +--******************************************************** +-- +-- Fonctions de debug et warning +-- +--******************************************************** +-- +-- fonction qui affiche des messages de debug +-- +local function DEBUG(msg) + --if true then return end + if not msg then msg="nil" end + DEFAULT_CHAT_FRAME:AddMessage("(DEBUG) " .. msg); +end + +local function Warn(msg) + if not msg then return end + --DEFAULT_CHAT_FRAME:AddMessage("(SayIt) "..msg); + local event = "UI_INFO_MESSAGE" + UIErrorsFrame_OnEvent(UIErrorsFrame, event, msg) +end + + +--******************************************************** +-- +-- Analyse de texte +-- +--******************************************************** +-- +-- Function qui sépare les paragraphes/phrases d'un texte en éléments de tableau +-- +local function Paragraphes(txt) + -- Si pas de texte, pas la peine de continuer + if not txt or txt=="" then + return {}, 0 + end + + local text = {} + local p = 1 + for paragraph in txt:gmatch("[^\r\n]+") do + -- On enlève au texte le double '|', le nom du Npc le " dit : " et un caractère en plus (fin de string ?) + + -- Est-ce une émote ? + local e = (paragraph:sub(1,1)=="<" and paragraph:sub(-1)==">") + local t,Nchar_supp + if e then + Nchar_supp = 2 + t = paragraph:sub(2,-2) -- on vire les < > + else + Nchar_supp = 9+target_name:len() + t = paragraph + end + + -- Coupe par phrase + -- [.!?]+ : au moins un signe de ponctuation, permet de gérer ... !? ?! par exemple + -- [^%s][^%s]%s* : le dernier mot de la phrase dois avoir au moins 2 caractères, pour éviter de couper "M. Dupont" (pas parfait mais mieux que rien) + -- on transforme chaque phrase en paragraphe, et on repasse le test précédent + for tt in t:gsub('([^%s][^%s]%s*[%.%!%?]+)(%s+)(%u)','%1\n%3'):gmatch('[^\r\n]+') do --for tt in t:gmatch('(.-[.!?]+)%s*') do + text[p] = { -- Le texte est coupé au cas où... + ["texte"] = tt:sub(1,254-Nchar_supp), -- ça devrait être 255, mais ça ne passe pas... + ["emote"] = e } + p = p+1 + end + end + + return text, p-1 +end + +-- +-- Coloration du texte de la fenêtre +-- +local cDit = "|cff".."606060" -- gris clair +local cJusteDit = "|cff".."7f0000" -- gris foncé +local cADire = "|cff".."00007f" -- jaunasse +local cNonDit = "|cff".."202020" -- noir + +local function SpecialChar(txt) + return txt and txt:gsub('([%(%)%.%+%-%*%?%[%^%$%]])','%%%1') or '' +end +local function ColorieTexte(txt) + --print('______') + local tJusteDit,tADire + if i_phrase > 1 then + tJusteDit = text_table[i_phrase-1].texte + end + if i_phrase <= max_phrase then + tADire = text_table[i_phrase].texte + end + + --print(txt) + --print('^(.*)('..SpecialChar(tJusteDit)..')(.-)('..SpecialChar(tADire)..')(.*)$') + local _,_,tDit,tJusteDit2,space,tADire2,tNonDit = txt:find('^(.-)('..SpecialChar(tJusteDit)..')(.-)('..SpecialChar(tADire)..')(.*)$') --,char_dits) + + --print('tDit:'..(tDit or '')) + --print('tJusteDit2:'..(tJusteDit2 or '')) + --print('tADire2:'..(tADire2 or '')) + --print('tNonDit:'..(tNonDit or '')) + + return (tDit and SayItOptions.cDit..tDit..'|r' or '' ).. + (tJusteDit and SayItOptions.cJusteDit..tJusteDit..'|r' or '' ).. + (space or '')..(tADire and SayItOptions.cADire..tADire..'|r' or '' ).. + (tNonDit and SayItOptions.cNonDit..tNonDit..'|r' or '' ) +end + +-- +-- Faire parler un Npc +-- +local function NpcDit(txt) + if not txt then return end + if not txt.emote then + SendChatMessage("\124\124 "..GetUnitName("Npc").." dit : ".. + txt.texte,"EMOTE") + else + SendChatMessage("\124\124 "..txt.texte,"EMOTE") + return + end +end + + +--******************************************************** +-- +-- Boutons et tooltips +-- +--******************************************************** +-- +-- Remplissage du tooltip +-- +local function TooltipUpdate(b) + if max_phrase>0 then + -- Coloration du texte dans la fenêtre + if TextFrame and SayItOptions.colorisation == 2 then + TextFrame:SetText(ColorieTexte(text_full)) + end + + -- tooltip + if not SayItOptions.tooltip then return end + + if SayItOptions.ancre_tooltip then + GameTooltip:SetOwner(b,"ANCHOR_BOTTOMRIGHT")-- Position du tooltip + else + GameTooltip_SetDefaultAnchor(GameTooltip, b) + end + + -- texte du tolltip + GameTooltip:SetText(target_name,1,1,1) -- Nom du Pnj + if SayItOptions.texte_tooltip then + local txt = "" + if i_phrase <= max_phrase then + if not text_table[i_phrase].emote then + GameTooltip:AppendText(" va dire :") + else + GameTooltip:AppendText(" :") + end + txt = text_table[i_phrase].texte + GameTooltip:AddLine('"'..txt..'"',1,0.82,0,true) + else + GameTooltip:AppendText(" a terminé.") + end + end + + -- Raccourcis + if SayItOptions.raccourcis_tooltip then + GameTooltip:AddLine(" ") + if i_phrase <= max_phrase then + GameTooltip:AddDoubleLine("Dire la phrase","Clic gauche",1,1,1,1,1,1) + end + if i_phrase>1 then + GameTooltip:AddDoubleLine("Phrase précédente","Ctrl+Clic/Roulette haut",1,1,1,1,1,1) + end + if i_phrase <= max_phrase then + GameTooltip:AddDoubleLine("Sauter la phrase","Shift+Clic/Roulette bas",1,1,1,1,1,1) + end + end + GameTooltip:Show() + else + GameTooltip:SetText("") + GameTooltip:Hide() + end +end + +-- +-- Créations des boutons, avec les fonctions des clics/mouseover +-- +local function CreerBouton(parent) + local button = CreateFrame("Button", parent:GetName().."SayButton", parent, "UIPanelButtonTemplate") + button:SetText("Dire") + button:SetHeight(22) + button:SetWidth(button:GetTextWidth() + 40) + button:SetPoint("BOTTOM",parent,"BOTTOM",-9,72) + + -- Set the frame level of the gossip_button to be 1 deeper than its parent + local buttonparent = button:GetParent() + local framelevel = buttonparent:GetFrameLevel() + local framestrata = buttonparent:GetFrameStrata() + button:SetFrameLevel(framelevel + 1) + button:SetFrameStrata(framestrata) + button:Enable() + + -- Action du bouton + button:RegisterForClicks("LeftButtonUp") + button:EnableMouseWheel(true) + button:SetScript("OnClick",function(self, button, down) + -- état des modificateurs + local shiftDown = IsShiftKeyDown(); + local ctrlDown = IsControlKeyDown(); + + -- On évite le cas foireux + if shiftDown and ctrlDown then return end + + -- lecture phrase actuelle + if not shiftDown and not ctrlDown and i_phrase<=max_phrase then + NpcDit(text_table[i_phrase]) + end + + -- Passage phrase suivante + if ctrlDown then + if i_phrase==1 then + Warn("Le début du texte est atteint.") + else + i_phrase = i_phrase-1 + --char_dits = char_dits - text_table[i_phrase].texte:len() + if TextFrame and SayItOptions.colorisation == 3 then + TextFrame:SetText(ColorieTexte(text_full)) + end + end + else + if i_phrase>max_phrase then + Warn("La fin du texte est atteinte.") + else + --char_dits = char_dits + text_table[i_phrase].texte:len() + i_phrase = i_phrase+1 + if TextFrame and SayItOptions.colorisation == 3 then + TextFrame:SetText(ColorieTexte(text_full)) + end + end + end + + -- Mise à jour du texte du tooltip + TooltipUpdate(self) + end) + button:SetScript("OnMouseWheel", function(self, delta) + -- Passage phrase suivante + if delta==1 then + if i_phrase==1 then + Warn("Le début du texte est atteint.") + else + i_phrase = i_phrase-1 + --char_dits = char_dits - text_table[i_phrase].texte:len() + if TextFrame and SayItOptions.colorisation == 3 then + TextFrame:SetText(ColorieTexte(text_full)) + end + end + else + if i_phrase>max_phrase then + Warn("La fin du texte est atteinte.") + else + --char_dits = char_dits + text_table[i_phrase].texte:len() + i_phrase = i_phrase+1 + if TextFrame and SayItOptions.colorisation == 3 then + TextFrame:SetText(ColorieTexte(text_full)) + end + end + end + + -- Mise à jour du texte du tooltip + TooltipUpdate(self) + end) + + + -- Tooltip + button:SetScript("OnEnter", TooltipUpdate) + button:SetScript("OnLeave", function() + GameTooltip:Hide() + if TextFrame and SayItOptions.colorisation == 2 then + TextFrame:SetText(text_full) + end + end) + + return button +end + + +--******************************************************** +-- +-- Gestion des events +-- +--******************************************************** +-- +-- fonction lancée au chargement de l'add-on +-- +function _G.SayIt_OnLoad(self,...) + -- Création des deux boutons + gossip_button = CreerBouton(GossipFrame) + quest_button = CreerBouton(QuestFrame) + + -- Pour ne pas avoir de warning avec findglobals + -- GLOBALS: this + -- Events à suivre + SayItFrame:RegisterEvent("GOSSIP_SHOW"); -- Affiche fenêtre Gossip + SayItFrame:RegisterEvent("GOSSIP_CLOSED"); -- Ferme fenêtre gossip (peut-être appelé juste avant l'ouverture d'une quête) + SayItFrame:RegisterEvent("QUEST_DETAIL"); -- Nouvelle quête + SayItFrame:RegisterEvent("QUEST_PROGRESS"); -- Quête en cours, non terminée + SayItFrame:RegisterEvent("QUEST_COMPLETE"); -- Quête en cours et terminée + SayItFrame:RegisterEvent("QUEST_FINISHED"); -- Fermeture fenêtre quête + --"QUEST_GREETING" ? +end + +-- +-- fonction appelée quand il y a un event +-- +function _G.SayIt_OnEvent(self, event, ...) + --DEBUG("Event:"..event) + --Warn(event) + + if ( event=="GOSSIP_CLOSED" or event=="QUEST_FINISHED") then + -- Reset + target_name = "" + text_full = nil + current_button = nil + TextFrame = nil + + elseif event=="GOSSIP_SHOW" then + target_name = GetUnitName("Npc") + text_full = GetGossipText() + current_button = gossip_button + TextFrame = GossipGreetingText + + elseif event=="QUEST_DETAIL" then + target_name = GetUnitName("Npc") + text_full = GetQuestText(); + current_button = quest_button + TextFrame = nil + + elseif event=="QUEST_PROGRESS" then + target_name = GetUnitName("Npc") + text_full = GetProgressText(); + current_button = quest_button + TextFrame = QuestProgressText + + elseif event=="QUEST_COMPLETE" then + target_name = GetUnitName("Npc") + text_full = GetRewardText(); + current_button = quest_button + TextFrame = nil + + --elseif event=="QUEST_GREETING" then + -- GetGreetingText() + --GreetingText + else return + end + + -- On ne sait jamais (ça arrive quand la fenêtre ne s'ouvre pas parce que celle des options est ouverte, par exemple) + if not target_name or not text_full or not current_button then + return + end + + -- Reset de l'indice + i_phrase = 1 + --char_dits = 0 + + -- Découpage du texte en paragraphes/phrase + text_table, max_phrase = Paragraphes(text_full) + + -- Affichage en couleur + if TextFrame and SayItOptions.colorisation == 3 then + TextFrame:SetText(ColorieTexte(text_full)) + end +end + + +--******************************************************** +-- +-- Ace 3.0 +-- +--******************************************************** +-- http://www.wowace.com/addons/ace3/pages/getting-started/ + +-- Enregistrement comme add-on +local SayIt = LibStub("AceAddon-3.0"):NewAddon("SayIt") +-- +-- Ace Config +-- +local function Hex2Val(h) + if not h then return 0,0,0 end + return tonumber(h:sub(5,6),16)/255, tonumber(h:sub(7,8),16)/255, tonumber(h:sub(9,10),16)/255 +end +local function Val2Hex(r,g,b) + return string_format("|cff%02x%02x%02x",(r or 0)*255,(g or 0)*255,(b or 0)*255) +end +local options = { + type = "group", + args = { + tooltip_header = { + name = "Tooltip", + type = "header", + order = 80 + }, + activer_tooltip = { + name = "Afficher le tooltip", + desc = "Affiche un tooltip pour le bouton \"Dire\"", + type = "toggle", + get = function() return SayItOptions.tooltip end, + set = function(info,state) SayItOptions.tooltip = state end, + width = "full", + order = 81 + }, + montrer_texte = { + name = "Afficher le texte dans le tooltip", + desc = "Affiche le texte qui va être dit pas le pnj dans le tooltip du bouton \"Dire\"", + type = "toggle", + get = function() return SayItOptions.texte_tooltip end, + set = function(info,state) SayItOptions.texte_tooltip = state end, + width = "full", + order = 82 + }, + montrer_raccourcis = { + name = "Afficher les raccourcis dans le tooltip", + desc = "Affiche les raccourcis dans le tooltip du bouton \"Dire\"", + type = "toggle", + get = function() return SayItOptions.raccourcis_tooltip end, + set = function(info,state) SayItOptions.raccourcis_tooltip = state end, + width = "full", + order = 83 + }, + ancre_tooltip = { + name = "Ancrer le tooltip au bouton", + desc = "Ancre le tooltip au bouton \"Dire\". Sinon, il sera dans sa position par défaut.", + type = "toggle", + get = function() return SayItOptions.ancre_tooltip end, + set = function(info,state) SayItOptions.ancre_tooltip = state end, + width = "full", + order = 84 + }, + couleur_header = { + name = "Couleurs des textes", + type = "header", + order = 99 + }, + o100 = { + name = "|cffffd100Remarque :|r La colorisation ne marche pas pour les fenêtres d'acceptation et de rendu de quête.\n", + type = "description", + order = 100 + }, + colorier = { + name = "Colorisation", + desc = "Colore le texte dans la fenêtre du pnj.", + --descStyle = 'inline', + type = "select", + values = { + "Aucune", + "Sous la souris", + "Toujours" + }, + style = 'radio', + get = function() return SayItOptions.colorisation end, + set = function(info,val) SayItOptions.colorisation = val end, + order = 101 + }, + o102 = { + name = "\n|cffffd100Couleurs utilisées lors de la colorisation des textes|r", + type = "description", + order = 102 + }, + couleur_cDit = { + name = "Texte déjà dit", + desc = "Couleur dans laquelle apparaitra le texte que le pnj a déjà dit.", + type = "color", + get = function() return Hex2Val(SayItOptions.cDit) end, + set = function(info,r,g,b) SayItOptions.cDit = Val2Hex(r,g,b) end, + width = "full", + order = 103 + }, + couleur_cJusteDit = { + name = "Texte tout juste dit", + desc = "Couleur dans laquelle apparaitra le texte que le pnj vient de dire.", + type = "color", + get = function() return Hex2Val(SayItOptions.cJusteDit) end, + set = function(info,r,g,b) SayItOptions.cJusteDit = Val2Hex(r,g,b) end, + width = "full", + order = 104 + }, + couleur_cADire = { + name = "Texte qui va être dit", + desc = "Couleur dans laquelle apparaitra le texte que le pnj dira la prochaine fois.", + type = "color", + get = function() return Hex2Val(SayItOptions.cADire) end, + set = function(info,r,g,b) SayItOptions.cADire = Val2Hex(r,g,b) end, + width = "full", + order = 105 + }, + couleur_cNonDit = { + name = "Texte pas encore dit", + desc = "Couleur dans laquelle apparaitra le texte que le pnj n'a pas encore dit.", + type = "color", + get = function() return Hex2Val(SayItOptions.cNonDit) end, + set = function(info,r,g,b) SayItOptions.cNonDit = Val2Hex(r,g,b) end, + width = "full", + order = 106 + } + } +} + +function SayIt:OnInitialize() + -- Code that you want to run when the addon is first loaded goes here. + + -- Application de la config par Ace + LibStub("AceConfig-3.0"):RegisterOptionsTable("SayIt".."BlizzOptions", options, {"sayit"}) + LibStub("AceConfigDialog-3.0"):AddToBlizOptions("SayIt".."BlizzOptions","Say It") + LibStub("AceConfig-3.0"):RegisterOptionsTable("SayIt", function() return self:GetOptions() end) -- tiré de adibags + + -- Récupération de la config... + if not SayItOptions then + SayItOptions = {} + end + if SayItOptions.tooltip==nil then + SayItOptions.tooltip = true + end + if SayItOptions.texte_tooltip==nil then + SayItOptions.texte_tooltip = true + end + if SayItOptions.raccourcis_tooltip==nil then + SayItOptions.raccourcis_tooltip = true + end + if SayItOptions.ancre_tooltip==nil then + SayItOptions.ancre_tooltip = true + end + if not SayItOptions.colorisation then + SayItOptions.colorisation = 2 + end + if not SayItOptions.cDit then + SayItOptions.cDit = "|cff".."606060" + end + if not SayItOptions.cJusteDit then + SayItOptions.cJusteDit = "|cff".."7f0000" + end + if not SayItOptions.cADire then + SayItOptions.cADire = "|cff".."00007f" + end + if not SayItOptions.cNonDit then + SayItOptions.cNonDit = "|cff".."202020" + end +end + +--function SayIt:OnEnable() + -- Called when the addon is enabled +--end + +--function SayIt:OnDisable() + -- Called when the addon is disabled +--end +
