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.

4726 lines
193 KiB

local addonName, platerInternal = ...
local Plater = Plater
local GameCooltip = GameCooltip2
local DF = DetailsFramework
local _
local unpack = _G.unpack
local tremove = _G.tremove
local CreateFrame = _G.CreateFrame
local tinsert = _G.tinsert
--sort scripts
function Plater.SortScripts (t1, t2)
--> index 4 stores if the script is enabled
if (t1[4] > t2[4]) then
return true
elseif (t1[4] < t2[4]) then
return false
--> index 5 stores if the script is a wago update import
elseif (t1[5] > t2[5]) then
return true
elseif (t1[5] < t2[5]) then
return false
else
--> index 3 stores the script name
return t1[3] < t2[3]
end
end
-- simple rounding to full numbers
local function round(x)
if not x then return nil end
return (x + 0.5 - (x + 0.5) % 1)
end
--tab indexes
local PLATER_OPTIONS_SCRIPTING_TAB = 6
local PLATER_OPTIONS_HOOKING_TAB = 7
local PLATER_OPTIONS_PROFILES_TAB = 22
local PLATER_OPTIONS_WAGO_TAB = 25
--options
local start_y = platerInternal.optionsYStart
local main_frames_size = {600, 400}
local edit_script_size = {620, 431}
local scrollbox_size = {200, 405}
local scrollbox_lines = 13
local hook_scrollbox_lines = 12
local scrollbox_line_height = 30
local triggerbox_size = {180, 228}
local triggerbox_lines = 9
local triggerbox_line_height = 24
local hookbox_size = {triggerbox_size[1], triggerbox_size[2] + 85}
local hookbox_label_y = -145
local scrollbox_line_backdrop_color = {0, 0, 0, 0.5}
local scrollbox_line_backdrop_not_inuse = {0, 0, 0, 0.4}
local scrollbox_line_backdrop_color_selected = {.6, .6, .1, 0.7}
local buttons_size = {120, 20}
local luaeditor_backdrop_color = {.2, .2, .2, .5}
local luaeditor_border_color = {0, 0, 0, 1}
--get templates
local options_text_template = DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE")
local options_dropdown_template = DF:GetTemplate ("dropdown", "OPTIONS_DROPDOWN_TEMPLATE")
local options_switch_template = DF:GetTemplate ("switch", "OPTIONS_CHECKBOX_TEMPLATE")
local options_slider_template = DF:GetTemplate ("slider", "OPTIONS_SLIDER_TEMPLATE")
local options_button_template = DF:GetTemplate ("button", "OPTIONS_BUTTON_TEMPLATE")
options_dropdown_template = DF.table.copy({}, options_dropdown_template)
options_dropdown_template.backdropcolor = {.2, .2, .2, .8}
options_slider_template = DF.table.copy({}, options_slider_template)
options_slider_template.backdropcolor = {.2, .2, .2, .8}
options_button_template = DF.table.copy({}, options_button_template)
options_button_template.backdropcolor = {.2, .2, .2, .8}
Plater.APIList = {
{Name = "SetNameplateColor", Signature = "Plater.SetNameplateColor (unitFrame, color)", Desc = "Set the color of the nameplate.\n\nColor formats are:\n|cFFFFFF00Just Values|r: r, g, b\n|cFFFFFF00Index Table|r: {r, g, b}\n|cFFFFFF00Hash Table|r: {r = 1, g = 1, b = 1}\n|cFFFFFF00Hex|r: '#FFFF0000' or '#FF0000'\n|cFFFFFF00Name|r: 'yellow' 'white'\n\nCalling without passing width and height reset the color to default."},
{Name = "SetNameplateSize", Signature = "Plater.SetNameplateSize (unitFrame, width, height)", Desc = "Adjust the nameplate size.\n\nCalling without passing width and height reset the size to default."},
{Name = "SetBorderColor", Signature = "Plater.SetBorderColor (unitFrame, r, g, b, a)", Desc = "Set the border color.\n\nCalling without passing any color reset the color to default."},
{Name = "SetCastBarColor", Signature = "Plater.SetCastBarColor (unitFrame, r, g, b)", Desc = "Set the cast bar color.\n\nColor formats are:\n|cFFFFFF00Just Values|r: r, g, b\n|cFFFFFF00Index Table|r: {r, g, b}\n|cFFFFFF00Hash Table|r: {r = 1, g = 1, b = 1}\n|cFFFFFF00Hex|r: '#FFFF0000' or '#FF0000'\n|cFFFFFF00Name|r: 'yellow' 'white'\n\nCalling without passing width and height reset the color to default."},
{Name = "SetCastBarSize", Signature = "Plater.SetCastBarSize (unitFrame, width, height)", Desc = "Adjust the cast bar size.\n\nCalling without passing width and height reset the size to default."},
{Name = "SetCastBarBorderColor", Signature = "Plater.SetCastBarBorderColor (castBar, color)", Desc = "Set the color of the castbar.\n\nColor formats are:\n|cFFFFFF00Just Values|r: r, g, b, a\n|cFFFFFF00Index Table|r: {r, g, b}\n|cFFFFFF00Hash Table|r: {r = 1, g = 1, b = 1}\n|cFFFFFF00Hex|r: '#FFFF0000' or '#FF0000'\n|cFFFFFF00Name|r: 'yellow' 'white'\n\nCalling without passing any color reset the color to default."},
{Name = "FlashNameplateBorder", Signature = "Plater.FlashNameplateBorder (unitFrame [, duration])", Desc = "Do a quick flash in the nameplate border, duration is optional."},
{Name = "FlashNameplateBody", Signature = "Plater.FlashNameplateBody (unitFrame [, text [, duration]])", Desc = "Flash the healthbar portion of the nameplate, text and duration are optionals."},
{Name = "NameplateHasAura", Signature = "Plater.NameplateHasAura (unitFrame, aura)", Desc = "Return true if the aura is shown on nameplate.\n\nAura can be the buff name, debuff name or spellID."},
{Name = "UnitHasAura", Signature = "Plater.UnitHasAura (unitFrame, aura)", Desc = "Return true if the aura exist on the nameplate, visible or not.\n\nAura can be the buff name, debuff name or spellID."},
{Name = "UnitHasEnrage", Signature = "Plater.UnitHasEnrage (unitFrame)", Desc = "Return true if any of the auras is an enrage effect."},
{Name = "UnitHasDispellable", Signature = "Plater.UnitHasDispellable (unitFrame)", Desc = "Return true if there is any aura on the unit your character can remove at this moment (enrage, magic, etc)."},
{Name = "NameplateInRange", Signature = "Plater.NameplateInRange (unitFrame)", Desc = "Return true if the nameplate is in range of the selected spell for range check.\n\nIt also updates the range flag for unitFrame.namePlateInRange."},
{Name = "GetNpcIDFromGUID", Signature = "Plater.GetNpcIDFromGUID (GUID)", Desc = "Extract the npcID from a GUID, guarantee to always return a number."},
{Name = "GetRaidMark", Signature = "Plater.GetRaidMark (unitFrame)", Desc = "Return which raid mark the nameplate has. Always return false if the nameplate is the personal health bar."},
{Name = "GetConfig", Signature = "Plater.GetConfig (unitFrame)", Desc = "Return a table with the settings chosen for the nameplate in the options panel. Use it to restore values is needed."},
{Name = "GetPlayerRole", Signature = "Plater:GetPlayerRole()", Desc = "Return TANK DAMAGER HEALER or NONE."},
{Name = "GetUnitGuildName", Signature = "Plater.GetUnitGuildName (unitFrame)", Desc = "Return the name unit's guild name if any, always return nil for npcs."},
{Name = "GetNpcColor", Signature = "Plater.GetNpcColor (unitFrame)", Desc = "Return a table with the color selected in the Npc Colors tab.\n\nThe color set there must have the 'Only Scripts' checked."},
{Name = "SetExecuteRange", Signature = "function Plater.SetExecuteRange (isExecuteEnabled, healthAmountLower, healthAmountUpper)", Desc = "Set if Plater should check for execute range and in what percent of health the execute range starts\n\nhealthAmountLower is in a range of zero to value, whereas healthAmountUpper is in range of value to 1.\nExample:\n'healthAmountLower = 0.25' sets lower execute range to start at 25% health; 'healthAmountUpper = 0.8' will enable execute between full health and 80%.\n'nil' or '0'/'1' values for lower/upper will disable this range."},
{Name = "IsUnitInFriendsList", Signature = "Plater.IsUnitInFriendsList (unitFrame)", Desc = "Return 'true' if the unit is in the player's friends list."},
{Name = "IsUnitTank", Signature = "Plater.IsUnitTank (unitFrame)", Desc = "Return 'true' if the unit is in tank role."},
{Name = "IsUnitTapped", Signature = "Plater.IsUnitTapped (unitFrame)", Desc = "Return 'true' if the unit is tapped and the player does not receives credits to kill it. Usually units tapped are shown with a gray color."},
{Name = "IsInCombat", Signature = "Plater.IsInCombat()", Desc = "Return 'true' if the player is in combat."},
{Name = "IsInOpenWorld", Signature = "Plater.IsInOpenWorld()", Desc = "Return 'true' if the player is in open world (not inside raids, dungeons, etc)."},
{Name = "IsPlayerTank", Signature = "Plater.IsPlayerTank()", Desc = "Return 'true' if the player is in the tank role."},
{Name = "GetTanks", Signature = "Plater.GetTanks()", Desc = "Return a table with all tanks in the group, use Plater.GetTanks()[unitName] to know if the unit is a tank."},
{Name = "ShowIndicator", Signature = "Plater.ShowIndicator (unitFrame, texture, width, height, color, L, R, T, B)", Desc = "Adds an indicator within the default indicators row.\n\nL, R, T, B: texcoordinates (optional)."},
{Name = "DisableHighlight", Signature = "Plater.DisableHighlight (unitFrame)", Desc = "The nameplate won't highlight when the mouse passes over it."},
{Name = "EnableHighlight", Signature = "Plater.EnableHighlight (unitFrame)", Desc = "Enable the mouse over highlight."},
{Name = "CheckAuras", Signature = "Plater.CheckAuras (self, buffList, debuffList, noSpecialAuras)", Desc = "Perform a custom aura check overriding the default from Plater.\n\nbuffList and debuffList receive tables with the aura name as key and true as value, example: \n{\n ['Arcane Intellect'] = true,\n}\n"},
{Name = "RefreshNameplateColor", Signature = "Plater.RefreshNameplateColor (unitFrame)", Desc = "Check which color the nameplate should have and set it."},
{Name = "RefreshNameplateStrata", Signature = "Plater.RefreshNameplateStrata (unitFrame)", Desc = "Reset the frame strata and frame levels to default."},
{Name = "UpdateNameplateThread", Signature = "Plater.UpdateNameplateThread (unitFrame)", Desc = "Perform an Aggro update on the nameplate changing color to the current thread situation."},
{Name = "SafeSetCVar", Signature = "Plater.SafeSetCVar (variableName, value)", Desc = "Change the value of a CVar, if called during combat, it'll be applied when the player leaves combat.\n\nOriginal value is stored until Plater.RestoreCVar (variableName) is called."},
{Name = "RestoreCVar", Signature = "Plater.RestoreCVar (variableName)", Desc = "Restore the value a CVar had before Plater.SafeSetCVar() was called."},
{Name = "SetAnchor", Signature = "Plater.SetAnchor (frame, config, attachTo, centered)", Desc = "Anchor the 'frame' to the 'attachTo' frame according to the given 'config' ('config = {x = 0, y = 0, side = 1}', where 'side' is one of the following:\nTOP_LEFT = 1, LEFT = 2, BOTTOM_LEFT = 3, BOTTOM = 4, BOTTOM_RIGHT = 5, RIGHT = 6, TOP_RIGHT = 7, TOP = 8, CENTER = 9, INNER_LEFT = 10, INNER_RIGHT = 11, INNER_TOP = 12, INNER_BOTTOM = 13)"},
}
Plater.FrameworkList = {
{Name = "CreateFlash", Signature = "Plater.CreateFlash (parent, duration, amountOfFlashes, color)", Desc = "Creates a custom flash which can be triggered by the ReturnValue:Play()\n\nUse:\n|cFFFFFF00ReturnedValue:Play()|r on OnShow.\n|cFFFFFF00ReturnedValue:Stop()|r on OnHide.", AddVar = true, AddCall = "--@ENV@:Play() --@ENV@:Stop()"},
--{Name = "CreateFrameShake", Signature = "Plater:CreateFrameShake (parent, duration, amplitude, frequency, bAbsoluteSineX, bAbsoluteSineY, scaleX, scaleY, fadeInTime, fadeOutTime)", Desc = "Creates a shake for the frame.\n\nStore the returned table inside the envTable and call parent:PlayFrameShake (returned table) to play the shake.", AddVar = true, AddCall = "--parent:PlayFrameShake(@ENV@)"}, -- --parent:StopFrameShake(@ENV@)
{Name = "CreateLabel", Signature = "Plater:CreateLabel (parent, text, size, color, font, member, name, layer)", Desc = "Creates a simple text to show in the nameplate, all parameters after 'parent' are optional.\n\nUse:\n|cFFFFFF00ReturnedValue:Show()|r on OnShow.\n|cFFFFFF00ReturnedValue:Hide()|r on OnHide.\n\nMembers:\n.text = 'new text'\n.textcolor = 'red'\n.textsize = 12\n.textfont = 'fontName'", AddVar = true, AddCall = "@ENV@:SetPoint ('center', 0, 0)"},
{Name = "CreateImage", Signature = "Plater:CreateImage (parent, texture, w, h, layer, coords, member, name)", Desc = "Creates a image to show in the nameplate, all parameters after 'parent' are optional.\n\nUse:\n|cFFFFFF00ReturnedValue:Show()|r on OnShow.\n|cFFFFFF00ReturnedValue:Hide()|r on OnHide.\n\nMembers:\n.texture = 'texture path'\n.alpha = 0.5\n.width = 300\n.height = 200", AddVar = true, AddCall = "@ENV@:SetPoint ('center', 0, 0)"},
{Name = "CreateBar", Signature = "Plater:CreateBar (parent, texture, w, h, value, member, name)", Desc = "Creates progress bar, all parameters after 'parent' are optional.\n\nUse:\n|cFFFFFF00ReturnedValue:Show()|r on OnShow.\n|cFFFFFF00ReturnedValue:Hide()|r on OnHide.\n\nMembers:\n.value = 50\n.texture = 'texture path'\n.icon = 'texture path'\n.lefttext = 'new text'\n.righttext = 'new text'\n.color = color\n.width = 300\n.height = 200", AddVar = true, AddCall = "@ENV@:SetPoint ('center', 0, 0)"},
{Name = "SetFontSize", Signature = "Plater:SetFontSize (fontString, fontSize, ...)", Desc = "Set the size of a text, accept more than one size, automatically picks the bigger one."},
{Name = "SetFontFace", Signature = "Plater:SetFontFace (fontString, fontFace)", Desc = "Set the font of a text."},
{Name = "SetFontColor", Signature = "Plater:SetFontColor (fontString, r, g, b, a)", Desc = "Set the color of a text.\n\nColor formats are:\n|cFFFFFF00Just Values|r: r, g, b, a\n|cFFFFFF00Index Table|r: {r, g, b}\n|cFFFFFF00Hash Table|r: {r = 1, g = 1, b = 1}\n|cFFFFFF00Hex|r: '#FFFF0000' or '#FF0000'\n|cFFFFFF00Name|r: 'yellow' 'white'"},
{Name = "CreateAnimationHub", Signature = "Plater:CreateAnimationHub (parent, onPlayFunc, onStopFunc)", Desc = "Creates an object to hold animations, see 'CreateAnimation' to add animations to the hub. When ReturnedValue:Play() is called all animations in the hub start playing respecting the Order set in the CreateAnimation().\n\nUse onShowFunc and onHideFunc to show or hide custom frames, textures or text.\n\nMethods:\n|cFFFFFF00ReturnedValue:Play()|r plays all animations in the hub.\n|cFFFFFF00ReturnedValue:Stop()|r: stop all animations in the hub.", AddVar = true, AddCall = "--@ENV@:Play() --@ENV@:Stop()"},
{Name = "CreateAnimation", Signature = "Plater:CreateAnimation (animationHub, animationType, order, duration, |cFFCCCCCCarg1|r, |cFFCCCCCCarg2|r, |cFFCCCCCCarg3|r, |cFFCCCCCCarg4|r)", Desc = "Creates an animation within an animation hub.\n\nOrder: integer between 1 and 10, lower play first. Animations with the same Order play at the same time.\n\nDuration: how much time this animation takes to complete.\n\nAnimation Types:\n|cFFFFFF00\"Alpha\"|r:\n|cFFCCCCCCarg1|r: Alpha Start Value, |cFFCCCCCCarg2|r: Alpha End Value.\n\n|cFFFFFF00\"Scale\"|r:\n|cFFCCCCCCarg1|r: X Start, |cFFCCCCCCarg2|r: Y Start, |cFFCCCCCCarg3|r: X End, |cFFCCCCCCarg4|r: Y End.\n\n|cFFFFFF00\"Rotation\"|r:\n |cFFCCCCCCarg1|r: Rotation Degrees.\n\n|cFFFFFF00\"Translation\"|r:\n |cFFCCCCCCarg1|r: X Offset, |cFFCCCCCCarg2|r: Y Offset."},
{Name = "CreateIconGlow", Signature = "Plater.CreateIconGlow (self)", Desc = "Creates a glow effect around an icon.\n\nUse:\n|cFFFFFF00ReturnedValue:Show()|r on OnShow.\n|cFFFFFF00ReturnedValue:Hide()|r on OnHide.\n|cFFFFFF00ReturnedValue:SetColor(dotColor, glowColor)|r to adjust the color.", AddVar = true, AddCall = "--@ENV@:Show() --@ENV@:Hide()"},
{Name = "CreateNameplateGlow", Signature = "Plater.CreateNameplateGlow (unitFrame.healthBar)", Desc = "Creates a glow effect around the nameplate.\n\nUse:\n|cFFFFFF00ReturnedValue:Show()|r on OnShow.\n|cFFFFFF00ReturnedValue:Hide()|r on OnHide.\n|cFFFFFF00ReturnedValue:SetColor(dotColor, glowColor)|r to adjust the color.\n\nUse offsets to adjust the dot animation to fit the nameplate.", AddVar = true, AddCall = "--@ENV@:Show() --@ENV@:Hide() --@ENV@:SetOffset (-27, 25, 5, -7)"},
{Name = "LimitTextSize", Signature = "Plater.LimitTextSize (fontString, maxWidth)", Desc = "Cut the text making it shorter.\n\nExample: using 50 as maxWidth with 'Jaina Proudmoore' would result 'Jaina Prou'"},
{Name = "FormatNumber", Signature = "Plater.FormatNumber (number)", Desc = "Format a number to be short as possible.\n\nExample:\n300000 to 300K\n2500000 to 2.5M"},
{Name = "CommaValue", Signature = "Plater:CommaValue (number)", Desc = "Format a number separating by thousands and millions.\n\nExample: 300000 to 300.000\n2500000 to 2.500.000"},
{Name = "IntegerToTimer", Signature = "Plater:IntegerToTimer (number)", Desc = "Format a number to time\n\nExample: 94 to 1:34"},
{Name = "RemoveRealmName", Signature = "Plater:RemoveRealmName (playerName)", Desc = "Removes the realm name from a player name."},
{Name = "Trim", Signature = "Plater:Trim (string)", Desc = "Removes spaces in the begining and end of a string."},
}
Plater.UnitFrameMembers = {
"unitFrame.castBar",
"unitFrame.castBar.Text",
"unitFrame.castBar.FrameOverlay",
"unitFrame.castBar.percentText",
--"unitFrame.castBar.extraBackground",
"unitFrame.healthBar",
"unitFrame.healthBar.unitName",
--"unitFrame.healthBar.actorLevel",
"unitFrame.healthBar.lifePercent",
"unitFrame.healthBar.border",
--"unitFrame.healthBar.healthCutOff",
"unitFrame.BuffFrame",
"unitFrame.BuffFrame2",
--"unitFrame.ExtraIconFrame",
"unitFrame.Top3DFrame",
--"unitFrame.FocusIndicator",
"unitFrame.TargetNeonUp",
"unitFrame.TargetNeonDown",
}
Plater.NameplateComponents = {
["unitFrame - Members"] = {
"namePlateUnitToken",
"namePlateUnitGUID",
"namePlateNpcId",
"namePlateIsQuestObjective",
"namePlateUnitReaction",
"namePlateClassification",
"namePlateInRange",
"namePlateUnitName",
"namePlateUnitNameLower",
"namePlateIsTarget",
"namePlateThreatPercent",
"namePlateThreatStatus",
"namePlateThreatIsTanking",
"PlayerCannotAttack",
"InExecuteRange",
"InCombat",
"targetUnitID",
"UsingCustomColor",
},
["unitFrame - Frames"] = {
"healthBar",
"castBar",
"aggroGlowUpper",
"aggroGlowLower",
"BuffFrame",
"BuffFrame2",
"PlaterRaidTargetFrame",
"TargetNeonUp",
"TargetNeonDown",
"ExtraRaidMark",
"ExtraIconFrame",
"Top3DFrame",
"ActorNameSpecial",
"ActorTitleSpecial",
},
["healthBar - Members"] = {
"CurrentHealth",
"CurrentHealthMax",
},
["healthBar - Frames"] = {
"unitName",
"actorLevel",
"lifePercent",
"ExecuteRangeHealthCutOff",
"ExecuteRangeBar",
"ExecuteGlowUp",
"ExecuteGlowDown",
"ExtraRaidMark",
"FocusIndicator",
},
["castBar - Members"] = {
"unit",
"ThrottleUpdate",
"SpellName",
"SpellID",
"SpellTexture",
"SpellStartTime",
"SpellEndTime",
"CanInterrupt",
"IsInterrupted",
},
["castBar - Frames"] = {
"percentText",
"Text",
"FrameOverlay",
"TargetName",
"BorderShield",
},
}
Plater.TriggerDefaultMembers = {
[1] = {
"envTable._SpellID",
"envTable._UnitID",
"envTable._SpellName",
"envTable._Texture",
"envTable._Caster",
"envTable._StackCount",
"envTable._Duration",
"envTable._StartTime",
"envTable._EndTime",
"envTable._RemainingTime",
},
[2] = {
"envTable._SpellID",
"envTable._UnitID",
"envTable._SpellName",
"envTable._Texture",
"envTable._Caster",
"envTable._Duration",
"envTable._StartTime",
"envTable._EndTime",
"envTable._RemainingTime",
"envTable._CastPercent",
"envTable._CanInterrupt",
},
[3] = {
"envTable._UnitID",
"envTable._NpcID",
"envTable._UnitName",
"envTable._UnitGUID",
"envTable._HealthPercent",
},
}
local openURL = function(url)
if (not PlaterURLFrameHelper) then
local f = DF:CreateSimplePanel (UIParent, 460, 90, "URL", "PlaterURLFrameHelper")
f:SetFrameStrata ("TOOLTIP")
f:SetPoint ("center", UIParent, "center")
DF:CreateBorder (f)
local LinkBox = DF:CreateTextEntry (f, function()end, 380, 20, "ExportLinkBox", _, _, options_dropdown_template)
LinkBox:SetPoint ("center", f, "center", 0, -10)
PlaterURLFrameHelper.linkBox = LinkBox
f:SetScript ("OnShow", function()
C_Timer.After (.1, function()
LinkBox:SetFocus (true)
LinkBox:HighlightText()
end)
end)
f:Hide()
end
PlaterURLFrameHelper.linkBox:SetText(url)
PlaterURLFrameHelper:Show()
end
Plater.OpenCopyUrlDialog = openURL
--return a unique string ID to identify each script
--return a string containing time() and GetTime() merged into a string which is converted to hexadecimal
--examples: 0x60abce782cb0df 0x60abce7847845 0x60abce782cb3cd 0x60abce782cb485 0x60abce792cb51b 0x60abce792cb58f 0x60abce792cb625
local createUniqueIdentifier = function(seed)
--transform time() into a hex
local hexTime = format("%8x", tonumber(seed) or time())
--take the GetTime() and remove the dot
local getTime = tostring(GetTime()) --convert to string
getTime = getTime:gsub("%.", "") --remove the dot
local getTimeInt = tonumber(getTime) --conver to to number
getTimeInt = math.fmod(getTimeInt, 2^31) --ensure integer range
--tranform GetTime into a hex
local hexGetTime = format("%8x", getTimeInt)
--remove spaces added due to the string not having 8 digits
hexGetTime = hexGetTime:gsub("%s", "")
local finalHex = "0x" .. hexTime .. hexGetTime
return finalHex
end
function Plater.CreateUniqueIdentifier(seed)
return createUniqueIdentifier(seed)
end
--get numbers from a string of number separated by a comma
--example: "10, 45, 30, 5, 16" returns 10, 45, 30, 5, 16
function Plater.GetNumbersFromString(str)
local result = {}
for value in str:gmatch("([^,%s]+)") do
local number = tonumber(value)
if (number) then
result[#result+1] = number
end
end
return unpack(result)
end
--initialize the options panel for a script object
function Plater.CreateOptionTableForScriptObject(scriptObject)
scriptObject.Options = scriptObject.Options or {}
scriptObject.OptionsValues = scriptObject.OptionsValues or {}
--[[ tinsert(scriptObject.Options, {
Type = 5, --label
Name = "Options Intro",
Key = "",
Desc = "",
Icon = "Interface\\AddOns\\Plater\\images\\option_label",
Value = "Options For @scriptname"
});
tinsert(scriptObject.Options, {
Type = 6, --blank space
Name = "Blank Space",
Key = "",
Desc = "",
Icon = "Interface\\AddOns\\Plater\\images\\option_blank",
Value = ""
});
]]--
end
--shared functions between all script tabs
local do_script_or_hook_import = function (text, scriptType, keepExisting)
if (scriptType == "hook") then
--the user inserted a string for a hook
--call the external function to import this script with ignoreRevision, overrideExisting and showDebug
local importSuccess, newObject = Plater.ImportScriptString (text, true, true, true, keepExisting)
if (importSuccess) then
PlaterOptionsPanelContainer:SelectIndex (Plater, PLATER_OPTIONS_HOOKING_TAB)
local mainFrame = PlaterOptionsPanelContainer
local hookFrame = mainFrame.AllFrames [PLATER_OPTIONS_HOOKING_TAB]
hookFrame.EditScript (newObject)
hookFrame.ScriptSelectionScrollBox:Refresh()
end
elseif (scriptType == "script") then
local importSuccess, newObject = Plater.ImportScriptString (text, true, true, true, keepExisting)
if (importSuccess) then
PlaterOptionsPanelContainer:SelectIndex (Plater, PLATER_OPTIONS_SCRIPTING_TAB)
local mainFrame = PlaterOptionsPanelContainer
local scriptingFrame = mainFrame.AllFrames [PLATER_OPTIONS_SCRIPTING_TAB]
scriptingFrame.EditScript (newObject)
scriptingFrame.ScriptSelectionScrollBox:Refresh()
end
else
Plater:Msg ("Cannot import: data imported is invalid")
end
Plater.UpdateOptionsTabUpdateState()
end
local import_mod_or_script = function (text)
--cleanup the text removing extra spaces and break lines
text = DF:Trim (text)
if (string.len (text) > 0) then
local indexScriptTable = Plater.DecompressData (text, "print")
--print(DF.table.dump(indexScriptTable))
if (indexScriptTable and type (indexScriptTable) == "table") then
local scriptType = Plater.GetDecodedScriptType (indexScriptTable)
indexScriptTable.type = scriptType
indexScriptTable = Plater.MigrateScriptModImport (indexScriptTable)
--check if this is a mod or a script, if none show a msg for the import data
if (indexScriptTable.type ~= "script" and indexScriptTable.type ~= "hook") then
Plater.SendScriptTypeErrorMsg(indexScriptTable)
return
end
local promptToOverwrite = false
local scriptDB = Plater.GetScriptDB (scriptType) or {}
local newScript = Plater.BuildScriptObjectFromIndexTable (indexScriptTable, scriptType) or {}
for i = 1, #scriptDB do
local scriptObject = scriptDB [i]
if (scriptObject.Name == newScript.Name) then
promptToOverwrite = true
end
end
if promptToOverwrite then
DF:ShowPromptPanel ("This Mod/Script already exists. Do you want to overwrite it?\nClicking 'No' will create a copy instead.\nTo cancel close this window wiht the 'x'.", function() do_script_or_hook_import (text, scriptType, false) end, function() do_script_or_hook_import (text, scriptType, true) end, true, 550)
else
do_script_or_hook_import (text, scriptType, true)
end
else
Plater:Msg ("Cannot import: data imported is invalid")
end
end
end
-- store companion update data internally
local CompanionDataSlugs = {}
Plater.CompanionDataSlugs = CompanionDataSlugs
local CompanionDataStash = {}
local legacyDataInitialized = false
local CompanionSlugData = {}
local CompanionStashData = {}
local copy_companion_data = function(data)
if not data or not type(data) == "table" or data.encoded then return end -- just accept slugs tables
DF.table.copy(CompanionDataSlugs, data.slugs or {})
DF.table.copy(CompanionDataStash, data.stash or {})
end
Plater.AddCompanionData = copy_companion_data
local handle_legacy_wa_companion_data = function()
if legacyDataInitialized then return end
--handle update slugs
local data = WeakAurasCompanion and WeakAurasCompanion.Plater
if data then
copy_companion_data(data)
legacyDataInitialized = true
end
end
local has_wago_update = function (scriptObject)
if scriptObject and scriptObject.url then
local url = scriptObject.url
local id = url:match("wago.io/([^/]+)/([0-9]+)") or url:match("wago.io/([^/]+)$")
if id and CompanionDataSlugs[id] then
local update = CompanionDataSlugs[id]
local companionVersion = tonumber(update.wagoVersion)
--skip?
if scriptObject.skipWagoUpdate and scriptObject.skipWagoUpdate == (companionVersion or 0) then
return false
end
--ignore?
if scriptObject.ignoreWagoUpdate then
return false
end
--update?
return companionVersion > (scriptObject.version or 0)
end
end
return false
end
Plater.HasWagoUpdate = has_wago_update
-- return: notImported, isScipt, isMod, isProfile
local is_wago_stash_slug_already_imported = function(slug)
--scripts
for _, scriptObject in pairs(Plater.db.profile.script_data) do
local url = scriptObject.url
local id = url and (url:match("wago.io/([^/]+)/([0-9]+)") or url:match("wago.io/([^/]+)$"))
if id and slug == id then
return not has_wago_update(scriptObject), true, false, false
end
end
--mods:
for _, scriptObject in pairs(Plater.db.profile.hook_data) do
local url = scriptObject.url
local id = url and (url:match("wago.io/([^/]+)/([0-9]+)") or url:match("wago.io/([^/]+)$"))
if id and slug == id then
return not has_wago_update(scriptObject), false, true, false
end
end
--profile:
for _, profile in pairs(Plater.db.profiles) do
local url = profile.url
local id = url and (url:match("wago.io/([^/]+)/([0-9]+)") or url:match("wago.io/([^/]+)$"))
if id and slug == id then
return not has_wago_update(profile), false, false, true
end
end
return false
end
-- return: isUpdate, isScipt, isMod, isProfile
local is_wago_update = function(slug)
--scripts:
for _, scriptObject in pairs(Plater.db.profile.script_data) do
local url = scriptObject.url
local id = url and (url:match("wago.io/([^/]+)/([0-9]+)") or url:match("wago.io/([^/]+)$"))
if id and slug == id then
return has_wago_update(scriptObject), true, false, false
end
end
--mods:
for _, scriptObject in pairs(Plater.db.profile.hook_data) do
local url = scriptObject.url
local id = url and (url:match("wago.io/([^/]+)/([0-9]+)") or url:match("wago.io/([^/]+)$"))
if id and slug == id then
return has_wago_update(scriptObject), false, true, false
end
end
--profile:
local url = Plater.db.profile.url
local id = url and (url:match("wago.io/([^/]+)/([0-9]+)") or url:match("wago.io/([^/]+)$"))
if id and slug == id then
return has_wago_update(Plater.db.profile), false, false, true
end
return false
end
local get_update_from_companion = function (object)
--if not has_wago_update(object) then return end
if object and object.url then
local url = object.url
local id = url:match("wago.io/([^/]+)/([0-9]+)") or url:match("wago.io/([^/]+)$")
if id and CompanionDataSlugs[id] then
local update = CompanionDataSlugs[id]
return update
end
end
return nil
end
Plater.GetWagoUpdateDataFromCompanion = get_update_from_companion
local update_from_wago = function (scriptObject)
if not scriptObject.hasWagoUpdateFromImport and not has_wago_update(scriptObject) then return end
if scriptObject and scriptObject.url then
local url = scriptObject.url
local id = url:match("wago.io/([^/]+)/([0-9]+)") or url:match("wago.io/([^/]+)$")
if id and CompanionDataSlugs[id] then
local update = CompanionDataSlugs[id]
import_mod_or_script(update.encoded)
end
end
end
local import_npc_colors = function (colorData)
if (colorData and colorData.NpcColor) then
--store which npcs has a color enabled
local dbColors = Plater.db.profile.npc_colors
--table storing all npcs already detected inside dungeons and raids
local allNpcsDetectedTable = Plater.db.profile.npc_cache
--the uncompressed table is a numeric table of tables
for i, colorTable in pairs (colorData) do
--check integrity
if (type (colorTable) == "table") then
local npcID, scriptOnly, colorID, npcName, zoneName = unpack (colorTable)
if (npcID and colorID and npcName and zoneName) then
if (type (colorID) == "string" and type (npcName) == "string" and type (zoneName) == "string") then
if (type (npcID) == "number" and type (scriptOnly) == "boolean") then
dbColors [npcID] = dbColors [npcID] or {}
dbColors [npcID] [1] = true --the color for the npc is enabled
dbColors [npcID] [2] = scriptOnly --the color is only used in scripts
dbColors [npcID] [3] = colorID --string with the color name
--add this npcs in the npcs detected table as well
allNpcsDetectedTable [npcID] = allNpcsDetectedTable [npcID] or {}
allNpcsDetectedTable [npcID] [1] = npcName
allNpcsDetectedTable [npcID] [2] = zoneName
end
end
end
end
end
Plater:Msg ("NPC colors imported.")
end
end
local import_from_wago = function (script_id, isStash)
local update = script_id and isStash and CompanionStashData [script_id] or CompanionSlugData [script_id]
if update then
local encoded = update.encoded
--cleanup the text removing extra spaces and break lines
encoded = DF:Trim (encoded)
if (string.len (encoded) > 0) then
local decompressedTable = Plater.DecompressData (encoded, "print")
if (decompressedTable and type (decompressedTable) == "table") then
decompressedTable = Plater.MigrateScriptModImport (decompressedTable)
--check if the user in importing a profile
if (decompressedTable.plate_config) then
--DF:ShowErrorMessage ("Profiles are currently not supported.") --TODO! :D
local profile = decompressedTable
local profileName = update.Name
if (not profile.spell_animation_list) then
profile.spell_animation_list = DF.table.copy ({}, PLATER_DEFAULT_SETTINGS.profile.spell_animation_list)
end
local profiles = Plater.db:GetProfiles()
local profileExists = false
for i, existingProfName in ipairs(profiles) do
if existingProfName == profileName then
profileExists = true
break
end
end
local mainFrame = PlaterOptionsPanelContainer
local profilesFrame = mainFrame.AllFrames [PLATER_OPTIONS_PROFILES_TAB]
if profileExists then
DF:ShowPromptPanel (format (L["OPTIONS_PROFILE_IMPORT_OVERWRITE"], profileName), function() profilesFrame.DoProfileImport(profileName, profile, true, isWagoUpdate) end, function() end, true, 500)
else
profilesFrame.DoProfileImport(profileName, profile, false, false)
end
return
elseif (decompressedTable.NpcColor) then
import_npc_colors(decompressedTable)
return
end
local scriptType = Plater.GetDecodedScriptType (decompressedTable)
local promptToOverwrite = false
local scriptDB = Plater.GetScriptDB (scriptType) or {}
local newScript = Plater.BuildScriptObjectFromIndexTable (decompressedTable, scriptType) or {}
for i = 1, #scriptDB do
local scriptObject = scriptDB [i]
if (scriptObject.Name == newScript.Name) then
promptToOverwrite = true
end
end
if promptToOverwrite then
DF:ShowPromptPanel ("This Mod/Script already exists. Do you want to overwrite it?\nClicking 'No' will create a copy instead.\nTo cancel close this window wiht the 'x'.", function() do_script_or_hook_import (encoded, scriptType, false) end, function() do_script_or_hook_import (encoded, scriptType, true) end, true, 550)
else
do_script_or_hook_import (encoded, scriptType, true)
end
else
Plater:Msg ("Cannot import: data imported is invalid")
end
end
end
end
local update_wago_slug_data = function()
handle_legacy_wa_companion_data()
local slugs = CompanionDataSlugs
local slugData = CompanionSlugData
wipe(slugData)
for slug, entry in pairs(slugs) do
local isUpdate, isScipt, isMod, isProfile = is_wago_update(slug)
local newScriptObject = { -- Dummy data --~prototype ~new ~create ñew
Enabled = true,
Name = "New Mod",
Icon = "",
Desc = "",
Author = "",
Time = time(),
Revision = 1,
PlaterCore = Plater.CoreVersion,
Hooks = {},
HooksTemp = {},
LastHookEdited = "",
LoadConditions = DF:UpdateLoadConditionsTable ({}),
Options = {},
}
Plater.CreateOptionTableForScriptObject(newScriptObject)
newScriptObject.semver = entry.wagoSemver
newScriptObject.Author = entry.author
newScriptObject.version = tonumber(entry.wagoVersion) or 0
newScriptObject.Name = DF:CleanTruncateUTF8String(strsub(entry.name, 1, 28)) --entry.name
newScriptObject.FullName = entry.name
newScriptObject.encoded = entry.encoded
newScriptObject.url = "https://wago.io/" .. slug .. "/" .. entry.wagoVersion
newScriptObject.slug = slug
newScriptObject.isWagoImport = true
newScriptObject.isWagoStash = false
newScriptObject.hasWagoUpdateFromImport = isUpdate
newScriptObject.isScipt = isScipt
newScriptObject.isMod = isMod
newScriptObject.isProfile = isProfile
tinsert(slugData, newScriptObject)
end
return slugData
end
local update_wago_stash_data = function()
handle_legacy_wa_companion_data()
local stash = CompanionDataStash
local stashData = CompanionStashData
wipe(stashData)
for slug, entry in pairs(stash) do
local isAlreadyImported = is_wago_stash_slug_already_imported(slug)
if not isAlreadyImported then
local newScriptObject = { -- Dummy data --~prototype ~new ~create ñew
Enabled = true,
Name = "New Mod",
Icon = "",
Desc = "",
Author = "",
Time = time(),
Revision = 1,
PlaterCore = Plater.CoreVersion,
Hooks = {},
HooksTemp = {},
LastHookEdited = "",
LoadConditions = DF:UpdateLoadConditionsTable ({}),
Options = {},
}
Plater.CreateOptionTableForScriptObject(newScriptObject)
newScriptObject.semver = entry.wagoSemver
newScriptObject.Author = entry.author
newScriptObject.version = tonumber(entry.wagoVersion) or 0
newScriptObject.Name = DF:CleanTruncateUTF8String(strsub(entry.name, 1, 28)) --entry.name
newScriptObject.FullName = entry.name
newScriptObject.encoded = entry.encoded
newScriptObject.url = "https://wago.io/" .. slug .. "/" .. entry.wagoVersion
newScriptObject.slug = slug
newScriptObject.isWagoImport = true
newScriptObject.isWagoStash = true
newScriptObject.hasWagoUpdateFromImport = true
newScriptObject.isScipt = isScipt
newScriptObject.isMod = isMod
newScriptObject.isProfile = isProfile
tinsert(stashData, newScriptObject)
end
end
return stashData
end
function Plater.CheckWagoUpdates(silent)
handle_legacy_wa_companion_data()
local countScripts = 0
for _, scriptObject in pairs(Plater.db.profile.script_data) do
countScripts = countScripts + (has_wago_update(scriptObject) and 1 or 0)
end
local countMods = 0
for _, scriptObject in pairs(Plater.db.profile.hook_data) do
countMods = countMods + (has_wago_update(scriptObject) and 1 or 0)
end
if not silent and (countMods > 0 or countScripts > 0) then
Plater:Msg ("There are " .. countMods .. " new mod and " .. countScripts .. " new script updates available from wago.io.")
end
local hasProfileUpdate = false
if has_wago_update(Plater.db.profile) then
hasProfileUpdate = true
if not silent then
Plater:Msg ("Your current profile has an update available from wago.io.")
end
end
return countMods, countScripts, hasProfileUpdate
end
local onclick_menu_scroll_line = function (self, scriptId, option, mainFrame)
if (option == "editscript") then
mainFrame.EditScript (scriptId)
elseif (option == "remove") then
mainFrame.RemoveScript (scriptId)
elseif (option == "duplicate") then
mainFrame.DuplicateScript (scriptId)
elseif (option == "export") then
mainFrame.ExportScript (scriptId)
elseif (option == "url") then
local url = mainFrame
openURL(url)
elseif (option == "sendtogroup") then
if (not IsInGroup()) then
Plater:Msg ("You need to be in a group to use this export option.")
return
end
Plater.ExportScriptToGroup (scriptId, mainFrame.ScriptType)
elseif (option == "exporttriggers") then
mainFrame.ExportScriptTriggers(scriptId)
elseif (option == "exportastable") then
mainFrame.ExportScriptAsLuaTable(scriptId)
elseif (option == "wago_update") then
local scriptObject = mainFrame.GetScriptObject (scriptId)
update_from_wago(scriptObject)
elseif (option == "skip_wago_update") then
local scriptObject = mainFrame.GetScriptObject (scriptId)
local update = get_update_from_companion(scriptObject)
local companionVersion = update and tonumber(update.wagoVersion) or nil
scriptObject.skipWagoUpdate = companionVersion
mainFrame.ScriptSelectionScrollBox:Refresh()
Plater.UpdateOptionsTabUpdateState()
elseif (option == "ignore_wago_update") then
local scriptObject = mainFrame.GetScriptObject (scriptId)
scriptObject.ignoreWagoUpdate = true
mainFrame.ScriptSelectionScrollBox:Refresh()
Plater.UpdateOptionsTabUpdateState()
elseif (option == "dont_skip_wago_update") then
local scriptObject = mainFrame.GetScriptObject (scriptId)
scriptObject.skipWagoUpdate = nil
mainFrame.ScriptSelectionScrollBox:Refresh()
Plater.UpdateOptionsTabUpdateState()
elseif (option == "dont_ignore_wago_update") then
local scriptObject = mainFrame.GetScriptObject (scriptId)
scriptObject.ignoreWagoUpdate = nil
mainFrame.ScriptSelectionScrollBox:Refresh()
Plater.UpdateOptionsTabUpdateState()
elseif (option == "wago_slugs") then
import_from_wago(scriptId)
update_wago_slug_data()
mainFrame.wagoSlugFrame.ScriptSelectionScrollBox:Refresh()
elseif (option == "wago_stash") then
import_from_wago(scriptId, true)
update_wago_stash_data()
mainFrame.wagoStashFrame.ScriptSelectionScrollBox:Refresh()
end
GameCooltip:Hide()
end
--when the user hover over a scrollbox line
local onenter_scroll_line = function (self)
self:SetBackdropColor (.3, .3, .3, .6)
end
--when the user leaves a scrollbox line from a hover over
local onleave_scroll_line = function (self)
local mainFrame = self.MainFrame
local currentScript = mainFrame.GetCurrentScriptObject()
--check if the hover overed button is the current script being edited
if (currentScript == self.Data) then
self:SetBackdropColor (unpack (scrollbox_line_backdrop_color_selected))
else
self:SetBackdropColor (unpack (scrollbox_line_backdrop_color))
end
end
local onclick_wago_icon = function (self, button)
if (button == "LeftButton") then
local mainFrame = self.line.MainFrame
local scriptObject = mainFrame.GetScriptObject (self.line.ScriptId)
if not scriptObject.isWagoImport then
update_from_wago(scriptObject)
else
import_from_wago(self.line.ScriptId, scriptObject.isWagoStash)
end
end
end
--when the user clicks on a scrollbox line to select a script
local onclick_scroll_line = function (self, button)
local mainFrame = self.MainFrame
if (button == "LeftButton") then
local currentScriptObject = mainFrame.GetCurrentScriptObject()
--check if isn't the same script
local scriptToBeEdited = mainFrame.GetScriptObject (self.ScriptId)
if (scriptToBeEdited == currentScriptObject) then
--no need to load the new script if is the same
return
end
--save the current script if any
if (currentScriptObject and mainFrame.ScriptType ~= "wago_slugs" and mainFrame.ScriptType ~= "wago_stash") then
mainFrame.SaveScript()
end
--select the script to start edit
mainFrame.EditScript (self.ScriptId)
--refresh the script list to update the backdrop color of the selected script
mainFrame.ScriptSelectionScrollBox:Refresh()
--open the user options
if mainFrame.ScriptType ~= "wago_slugs" and mainFrame.ScriptType ~= "wago_stash" then
Plater.RefreshUserScriptOptions(mainFrame)
end
--Plater.RefreshAdminScriptOptions(mainFrame) --debug open the admin panel
elseif (button == "RightButton") then
--open menu
GameCooltip:Preset (2)
GameCooltip:SetType ("menu")
GameCooltip:SetOption ("TextSize", 10)
GameCooltip:SetOption ("FixedWidth", 200)
GameCooltip:SetOption ("ButtonsYModSub", -1)
GameCooltip:SetOption ("YSpacingModSub", -4)
GameCooltip:SetOwner (self, "topleft", "topright", 2, 0)
GameCooltip:SetFixedParameter (self.ScriptId)
local scriptObject = mainFrame.GetScriptObject (self.ScriptId)
if mainFrame.ScriptType == "wago_slugs" or mainFrame.ScriptType == "wago_stash" then
-- wago import tab
--GameCooltip:AddLine ("Remove")
--GameCooltip:AddMenu (1, onclick_menu_scroll_line, "remove", mainFrame)
--GameCooltip:AddIcon ([[Interface\AddOns\Plater\images\icons]], 1, 1, 16, 16, 3/512, 21/512, 235/512, 257/512)
GameCooltip:AddLine ("Import")
GameCooltip:AddMenu (1, onclick_menu_scroll_line, mainFrame.ScriptType, mainFrame)
GameCooltip:AddIcon ([[Interface\AddOns\Plater\images\wagologo.tga]], 1, 1, 16, 10)
GameCooltip:AddLine ("Copy Wago.io URL")
GameCooltip:AddMenu (1, onclick_menu_scroll_line, "url", scriptObject.url)
GameCooltip:AddIcon ([[Interface\AddOns\Plater\images\wagologo.tga]], 1, 1, 16, 10)
else
-- script/mod tab
GameCooltip:AddLine ("Edit Script")
GameCooltip:AddMenu (1, onclick_menu_scroll_line, "editscript", mainFrame)
GameCooltip:AddIcon ([[Interface\BUTTONS\UI-GuildButton-PublicNote-Up]], 1, 1, 16, 16)
GameCooltip:AddLine ("Duplicate")
GameCooltip:AddMenu (1, onclick_menu_scroll_line, "duplicate", mainFrame)
GameCooltip:AddIcon ([[Interface\AddOns\Plater\images\icons]], 1, 1, 16, 16, 3/512, 21/512, 215/512, 233/512)
GameCooltip:AddLine ("Export")
GameCooltip:AddIcon ([[Interface\BUTTONS\UI-GuildButton-MOTD-Up]], 1, 1, 16, 16, 1, 0, 0, 1)
GameCooltip:AddLine ("As a Text String", "", 2)
GameCooltip:AddIcon ([[Interface\BUTTONS\UI-GuildButton-MOTD-Up]], 2, 1, 16, 16, 1, 0, 0, 1)
GameCooltip:AddMenu (2, onclick_menu_scroll_line, "export", mainFrame)
GameCooltip:AddLine ("Send to Your Party/Raid", "", 2)
GameCooltip:AddIcon ([[Interface\BUTTONS\UI-GuildButton-MOTD-Up]], 2, 1, 16, 16, 1, 0, 0, 1)
GameCooltip:AddMenu (2, onclick_menu_scroll_line, "sendtogroup", mainFrame)
if (mainFrame:GetName():find("Scripting")) then
GameCooltip:AddLine("$div", "$div", 2)
GameCooltip:AddLine("Export Triggers as Array", "", 2)
GameCooltip:AddIcon([[Interface\BUTTONS\UI-GuildButton-MOTD-Up]], 2, 1, 16, 16, 1, 0, 0, 1)
GameCooltip:AddMenu(2, onclick_menu_scroll_line, "exporttriggers", mainFrame)
end
if (mainFrame:GetName():find("Scripting")) then
GameCooltip:AddLine("$div", "$div", 2)
GameCooltip:AddLine("Export Table (debug)", "", 2)
GameCooltip:AddIcon([[Interface\BUTTONS\UI-GuildButton-MOTD-Up]], 2, 1, 16, 16, 1, 0, 0, 1)
GameCooltip:AddMenu(2, onclick_menu_scroll_line, "exportastable", mainFrame)
end
GameCooltip:AddLine ("Remove")
GameCooltip:AddMenu (1, onclick_menu_scroll_line, "remove", mainFrame)
GameCooltip:AddIcon ([[Interface\AddOns\Plater\images\icons]], 1, 1, 16, 16, 3/512, 21/512, 235/512, 257/512)
if (scriptObject.url) then
GameCooltip:AddLine ("$div")
GameCooltip:AddLine ("Copy Wago.io URL")
GameCooltip:AddMenu (1, onclick_menu_scroll_line, "url", scriptObject.url)
GameCooltip:AddIcon ([[Interface\AddOns\Plater\images\wagologo.tga]], 1, 1, 16, 10)
local has_update = has_wago_update(scriptObject)
local wago_update = get_update_from_companion(scriptObject)
local companionVersion = wago_update and tonumber(wago_update.wagoVersion) or nil
if (has_update) then
GameCooltip:AddLine ("Update from Wago.io")
GameCooltip:AddMenu (1, onclick_menu_scroll_line, "wago_update", mainFrame)
GameCooltip:AddIcon ([[Interface\AddOns\Plater\images\wagologo.tga]], 1, 1, 16, 10)
end
if (scriptObject.skipWagoUpdate and wago_update) or has_update then
if scriptObject.skipWagoUpdate or companionVersion and scriptObject.skipWagoUpdate == companionVersion then
GameCooltip:AddLine ("Don't skip this version")
GameCooltip:AddMenu (1, onclick_menu_scroll_line, "dont_skip_wago_update", mainFrame)
else
GameCooltip:AddLine ("Skip this version")
GameCooltip:AddMenu (1, onclick_menu_scroll_line, "skip_wago_update", mainFrame)
end
GameCooltip:AddIcon ([[Interface\AddOns\Plater\images\wagologo.tga]], 1, 1, 16, 10)
end
if scriptObject.ignoreWagoUpdate then
GameCooltip:AddLine ("Don't ignore Wago Updates")
GameCooltip:AddMenu (1, onclick_menu_scroll_line, "dont_ignore_wago_update", mainFrame)
else
GameCooltip:AddLine ("Ignore Wago Updates")
GameCooltip:AddMenu (1, onclick_menu_scroll_line, "ignore_wago_update", mainFrame)
end
GameCooltip:AddIcon ([[Interface\AddOns\Plater\images\wagologo.tga]], 1, 1, 16, 10)
else
GameCooltip:AddLine ("no wago.io url found", "", 1, "gray")
end
end
GameCooltip:SetOption("SubFollowButton", true)
GameCooltip:Show()
end
end
local update_line = function (self, script_id, data)
local icon_texture, script_name, script_type = data.Icon, data.Name, data.ScriptType
self.ScriptId = script_id
self.Data = data
self.Icon:SetTexture (icon_texture)
self.Icon:SetTexCoord (.1, .9, .1, .9)
self.ScriptName:SetText (script_name)
local scriptTypeName = self.MainFrame.GetScriptTriggerTypeName (script_type)
self.ScriptType:SetText (scriptTypeName)
self.EnabledCheckbox:SetValue (data.Enabled)
self.EnabledCheckbox:SetFixedParameter (script_id)
if data.isWagoImport then
self.EnabledCheckbox:Hide()
end
--if not data.isWagoImport and has_wago_update(data) then
if data.hasWagoUpdateFromImport or has_wago_update(data) then
self.UpdateIcon:Show()
else
self.UpdateIcon:Hide()
end
end
local onclick_remove_script = function (self)
local parent = self:GetParent() --get the line
local scriptId = parent.ScriptId
parent.MainFrame.RemoveScript (scriptId)
end
local cooltip_scriptsscrollbox = function (self, fixed_parameter)
GameCooltip:Preset (2)
GameCooltip:SetOption ("TextSize", 10)
GameCooltip:SetOption ("FixedWidth", 200)
local mainFrame = self.MainFrame
local scriptObject = mainFrame.GetScriptObject (self.ScriptId)
local lastEdited = scriptObject.Time and date ("%d/%m/%Y", scriptObject.Time)
GameCooltip:AddLine (scriptObject.Name, nil, 1, "yellow", "yellow", 11, "Friz Quadrata TT", "OUTLINE")
if (scriptObject.Icon ~= "") then
GameCooltip:AddIcon (scriptObject.Icon)
end
if lastEdited then
GameCooltip:AddLine ("Last Edited:", lastEdited)
end
local scriptTypeName = mainFrame.GetScriptTriggerTypeName (scriptObject.ScriptType)
GameCooltip:AddLine ("Trigger Type:", scriptTypeName)
GameCooltip:AddLine ("Author:", scriptObject.Author or "--x--x--")
if (scriptObject.url and scriptObject.url ~= "") then
GameCooltip:AddLine (scriptObject.url, "", 1, "gold")
if (scriptObject.semver and scriptObject.semver ~= "") then
GameCooltip:AddLine ("Wago-Version", scriptObject.semver, 1, "gold")
end
if (scriptObject.version and scriptObject.version > 0) then
GameCooltip:AddLine ("Wago-Revision", scriptObject.version, 1, "gold")
end
else
GameCooltip:AddLine ("no wago.io url found", "", 1, "gray")
end
if (scriptObject.Desc and scriptObject.Desc ~= "") then
GameCooltip:AddLine (scriptObject.Desc, "", 1, "gray")
end
end
local cooltip_inject_table_scriptsscrollbox = {
Type = "tooltip",
BuildFunc = cooltip_scriptsscrollbox,
ShowSpeed = 0.016,
MyAnchor = "topleft",
HisAnchor = "topright",
X = 10,
Y = 0,
}
local toggle_script_enabled = function (self, scriptId, value)
local mainFrame = self:GetParent().MainFrame
local scriptObject = Plater.GetScriptObject (scriptId, self.ScriptType)
if (scriptObject) then
scriptObject.Enabled = value
Plater.WipeAndRecompileAllScripts (mainFrame.ScriptType)
end
mainFrame.ScriptSelectionScrollBox:Refresh()
end
--create a line in the scroll box
local create_line_scrollbox = function (self, index)
--create a new line
local line = CreateFrame ("button", "$parentLine" .. index, self, BackdropTemplateMixin and "BackdropTemplate")
--get the scripting frame and store in the line
line.MainFrame = self:GetParent()
--set its parameters
line:SetPoint ("topleft", self, "topleft", 1, -((index-1) * (scrollbox_line_height+1)) - 1)
line:SetSize (scrollbox_size[1]-2, scrollbox_line_height)
line:RegisterForClicks ("LeftButtonDown", "RightButtonDown")
line:SetScript ("OnEnter", onenter_scroll_line)
line:SetScript ("OnLeave", onleave_scroll_line)
line:SetScript ("OnClick", onclick_scroll_line)
line.CoolTip = cooltip_inject_table_scriptsscrollbox
GameCooltip:CoolTipInject (line)
line:SetBackdrop ({bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true, edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1})
line:SetBackdropColor (unpack (scrollbox_line_backdrop_color))
line:SetBackdropBorderColor (0, 0, 0, 1)
local icon = line:CreateTexture ("$parentIcon", "overlay")
icon:SetSize (scrollbox_line_height-4, scrollbox_line_height-4)
local updateIcon = DF:CreateButton (line, onclick_wago_icon, 16, 10, nil, param1, param2, [[Interface\AddOns\Plater\images\wagologo.tga]], nil, "$parentUpdateIconFrame")
updateIcon.button.line = line
local script_name = DF:CreateLabel (line, "", DF:GetTemplate ("font", "PLATER_SCRIPTS_NAME"))
local script_type = DF:CreateLabel (line, "", DF:GetTemplate ("font", "PLATER_SCRIPTS_TYPE"))
local remove_button = CreateFrame ("button", "$parentRemoveButton", line, "UIPanelCloseButton")
remove_button:SetSize (16, 16)
remove_button:SetScript ("OnClick", onclick_remove_script)
remove_button:SetPoint ("topright", line, "topright")
remove_button:GetNormalTexture():SetDesaturated (true)
remove_button:SetAlpha (.4)
--hide the remove button
remove_button:Hide()
--create the enabled box
--the with_label value with passing an empty string "" making the switch create a label and anchor the checkbox to it
--after that it anchor the checkbox again here making the checkbox to be anchor to two different widgets making it not move while its parent moves
local enabled_checkbox = DF:CreateSwitch (line, toggle_script_enabled, true, _, _, _, _, "enabledCheckbox", "$parentScriptToggle" .. index, _, _, _, nil, DF:GetTemplate ("switch", "OPTIONS_CHECKBOX_BRIGHT_TEMPLATE"))
enabled_checkbox.ScriptType = line.MainFrame.ScriptType
enabled_checkbox:SetAsCheckBox()
--setup anchors
icon:SetPoint ("left", line, "left", 2, 0)
script_name:SetPoint ("topleft", icon, "topright", 2, -2)
script_type:SetPoint ("topleft", script_name, "bottomleft", 0, 0)
enabled_checkbox:SetPoint ("right", line, "right", -2, 0)
updateIcon:SetPoint ("bottomright", line, "bottomright", -enabled_checkbox:GetWidth()-6, 2)
line.Icon = icon
line.UpdateIcon = updateIcon
line.ScriptName = script_name
line.ScriptType = script_type
line.EnabledCheckbox = enabled_checkbox
line.UpdateLine = update_line
return line
end
--refresh the list of scripts already created
local refresh_script_scrollbox = function (self, data, offset, total_lines)
--get the main frame
local mainFrame = self:GetParent()
--alphabetical order
local dataInOrder = {}
if (mainFrame.SearchString ~= "") then
for i = 1, #data do
if not data[i].hidden then
local bFoundMatch = false
local triggerSpellIdList = data[i].SpellIds
if (triggerSpellIdList and type(triggerSpellIdList) == "table") then
for o, spellId in ipairs(triggerSpellIdList) do
local spellName = GetSpellInfo(spellId)
if (spellName) then
spellName = spellName:lower()
if (spellName:find(mainFrame.SearchString)) then
dataInOrder[#dataInOrder+1] = {i, data [i], data[i].Name, data[i].Enabled and 1 or 0, data[i].hasWagoUpdateFromImport and 1 or 0}
bFoundMatch = true
end
end
end
end
if (not bFoundMatch) then
local name = data[i].FullName or data[i].Name or ""
if (name:lower():find (mainFrame.SearchString)) then
dataInOrder [#dataInOrder+1] = {i, data [i], data[i].Name, data[i].Enabled and 1 or 0, data[i].hasWagoUpdateFromImport and 1 or 0}
end
end
end
end
else
for i = 1, #data do
if not data[i].hidden then
dataInOrder [#dataInOrder+1] = {i, data [i], data[i].Name, data[i].Enabled and 1 or 0, data[i].hasWagoUpdateFromImport and 1 or 0}
end
end
end
table.sort (dataInOrder, Plater.SortScripts)
local currentScript = mainFrame.GetCurrentScriptObject()
--update the scroll
for i = 1, total_lines do
local index = i + offset
local t = dataInOrder [index]
if (t) then
--get the data
local scriptId = t [1]
local data = t [2]
--update the line
local line = self:GetLine (i)
line:UpdateLine (scriptId, data)
if (data == currentScript) then
line:SetBackdropColor (unpack (scrollbox_line_backdrop_color_selected))
else
line:SetBackdropColor (unpack (scrollbox_line_backdrop_color))
end
end
end
--update overlap button
if (mainFrame.UpdateOverlapButton) then
mainFrame.UpdateOverlapButton()
end
end
local create_script_control_header = function (mainFrame, scriptDB)
local onclick_create_new_script_button = function()
mainFrame.CreateNewScript()
end
--localization
local buttonText = "" --text on the create new button
local importTooltipText = "" --text when hover over the import button
if (scriptDB == "script") then
buttonText = "New Script"
importTooltipText = "Import Script"
elseif (scriptDB == "hook") then
buttonText = "New Mod"
importTooltipText = "Import Mod"
end
--create new script script button, it does use the width of the scrollbox to select a created script
local create_new_script_button = DF:CreateButton (mainFrame, onclick_create_new_script_button, scrollbox_size[1] - (28*3), buttons_size[2], buttonText, -1, nil, nil, "CreateButton", nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
create_new_script_button:SetPoint ("topleft", mainFrame, "topleft", 10, start_y)
create_new_script_button:SetIcon ([[Interface\BUTTONS\UI-PlusButton-Up]], 20, 20, "overlay", {0, 1, 0, 1})
--create the trash restore button
local restore_script_button = DF:CreateButton (mainFrame, function() GameCooltip:Hide() end, 26, buttons_size[2], "", nil, nil, nil, nil, nil, false, options_button_template)
restore_script_button:SetPoint ("left", create_new_script_button, "right", 2, 0)
restore_script_button:SetIcon ([[Interface\AddOns\Plater\images\icons]], 16, 16, "overlay", {0, 64/512, 0, 64/512}, {0.945, .635, 0}, nil, nil, nil, false)
mainFrame.RestoreScriptButton = restore_script_button
local restore_from_trashcan = function (self, fixed_parameter, script_id)
local restoredScriptObject = Plater.db.profile [scriptDB .. "_data_trash"] [script_id]
restoredScriptObject.__TrashAt = nil
tinsert (Plater.db.profile [scriptDB .. "_data"], restoredScriptObject)
tremove (Plater.db.profile [scriptDB .. "_data_trash"], script_id)
--start editing the restored script
mainFrame.EditScript (#Plater.db.profile [scriptDB .. "_data"])
--refresh the script selection scrollbox
mainFrame.ScriptSelectionScrollBox:Refresh()
GameCooltip:Hide()
end
local build_restore_menu = function()
local data = Plater.db.profile [scriptDB .. "_data_trash"]
local timeToday = time()
GameCooltip:Preset (2)
GameCooltip:SetOption ("TextSize", 10)
GameCooltip:SetOption ("FixedWidth", 200)
if (#data == 0) then
GameCooltip:SetType ("tooltip")
GameCooltip:AddLine ("Recycle Bin", "", 1, "yellow", "yellow", 12, nil, "OUTLINE")
GameCooltip:AddLine ("All deleted scripts are moved to here for 30 days where they can be restored during this period")
else
for i = 1, #data do
local scriptObject = data [i]
local age = timeToday - scriptObject.__TrashAt
GameCooltip:AddLine (scriptObject.Name, floor (age/60/60/24) .. " days")
GameCooltip:AddIcon (scriptObject.Icon ~= "" and scriptObject.Icon or [[Interface\ICONS\INV_Misc_QuestionMark]], 1, 1, 20, 20)
GameCooltip:AddMenu (1, restore_from_trashcan, i)
end
end
end
restore_script_button.CoolTip = {
Type = "menu",
BuildFunc = build_restore_menu,
ShowSpeed = 0.05,
}
local GameCooltip = GameCooltip2
GameCooltip:CoolTipInject (restore_script_button)
--import button
local import_script_button = DF:CreateButton (mainFrame, mainFrame.ShowImportTextField, 26, buttons_size[2], "", -1, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
import_script_button:SetPoint ("left", restore_script_button, "right", 2, 0)
import_script_button:SetIcon ([[Interface\AddOns\Plater\images\icons]], 16, 16, "overlay", {5/512, 19/512, 195/512, 210/512}, {1, .8, .2}, nil, nil, nil, false)
import_script_button:HookScript ("OnEnter", function()
GameCooltip:Preset (2)
GameCooltip:SetOption ("TextSize", 10)
GameCooltip:SetOption ("FixedWidth", 200)
GameCooltip:SetOwner (import_script_button.widget)
GameCooltip:AddLine (importTooltipText, "", 1, "yellow", "yellow", 12, nil, "OUTLINE")
GameCooltip:AddLine ("Visit http://wago.io for more scripts, mods and profiles.")
GameCooltip:Show()
end)
import_script_button:HookScript ("OnLeave", function()
GameCooltip:Hide()
end)
--help button
local help_script_button = DF:CreateButton (mainFrame, function() mainFrame.HelpFrame:Show() end, 26, buttons_size[2], "", -1, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
help_script_button:SetPoint ("left", import_script_button, "right", 2, 0)
help_script_button:SetIcon ([[Interface\GossipFrame\ActiveQuestIcon]], 18, 18, "overlay", {0, 1, 0, 1}, nil, 0, -1, nil, false)
end
local create_script_scroll = function (mainFrame)
--scroll panel to select which script to edit
local script_scrollbox_label = DF:CreateLabel (mainFrame, "Scripts", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
local enabled_scrollbox_label = DF:CreateLabel (mainFrame, "Enabled", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
mainFrame.ScriptScrollLabel = script_scrollbox_label
mainFrame.ScriptEnabledLabel = enabled_scrollbox_label
local data
if (mainFrame.ScriptType == "script") then
data = Plater.db.profile.script_data
elseif (mainFrame.ScriptType == "hook") then
data = Plater.db.profile.hook_data
elseif (mainFrame.ScriptType == "wago_slugs") then
data = CompanionSlugData
elseif (mainFrame.ScriptType == "wago_stash") then
data = CompanionStashData
end
local script_scroll_box = DF:CreateScrollBox (mainFrame, "$parentScrollBox", refresh_script_scrollbox, data, scrollbox_size[1], scrollbox_size[2], scrollbox_lines, scrollbox_line_height)
DF:ReskinSlider (script_scroll_box)
mainFrame.ScriptSelectionScrollBox = script_scroll_box
--create the scrollbox lines
for i = 1, scrollbox_lines do
script_scroll_box:CreateLine (create_line_scrollbox)
end
--script search box
function mainFrame.OnSearchBoxTextChanged()
local text = mainFrame.ScriptSearchTextEntry:GetText()
mainFrame.SearchString = text:lower()
script_scroll_box:Refresh()
end
local script_search_textentry = DF:CreateTextEntry (mainFrame, function()end, 200, 20, "ScriptSearchTextEntry", _, _, options_dropdown_template)
if mainFrame.CreateButton then
script_search_textentry:SetPoint ("topleft", mainFrame.CreateButton, "bottomleft", 0, -20)
else
script_search_textentry:SetPoint ("topleft", mainFrame, "topleft", 10, start_y)
end
script_search_textentry:SetHook ("OnChar", mainFrame.OnSearchBoxTextChanged)
script_search_textentry:SetHook ("OnTextChanged", mainFrame.OnSearchBoxTextChanged)
local script_search_label = DF:CreateLabel (mainFrame, "Search:", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
script_search_label:SetPoint ("bottomleft", script_search_textentry, "topleft", 0, 2)
end
local create_script_namedesc = function (mainFrame, parent)
--textentry to insert the name of the script
local script_name_label = DF:CreateLabel (parent, "Script Name:", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
local script_name_textentry = DF:CreateTextEntry (parent, function()end, 156, 20, "ScriptNameTextEntry", _, _, options_dropdown_template)
script_name_textentry:SetPoint ("topleft", script_name_label, "bottomleft", 0, -2)
mainFrame.ScriptNameTextEntry = script_name_textentry
--icon selection
local script_icon_callback = function (texture)
mainFrame.ScriptIconButtonTexture = texture
mainFrame.ScriptIconButton:SetIcon (texture)
end
local script_icon_label = DF:CreateLabel (parent, "Icon:", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
local script_icon_button = DF:CreateButton (parent, function() DF:IconPick (script_icon_callback, true) end, 20, 20, "", 0, nil, nil, nil, nil, nil, options_button_template)
script_icon_button:SetPoint ("topleft", script_icon_label, "bottomleft", 0, -2)
mainFrame.ScriptIconButton = script_icon_button
--description
local script_desc_label = DF:CreateLabel (parent, "Description:", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
local script_desc_textentry = DF:CreateTextEntry (parent, function()end, 191, 20, "ScriptDescriptionTextEntry", _, _, options_dropdown_template)
script_desc_textentry:SetPoint ("topleft", script_desc_label, "bottomleft", 0, -2)
mainFrame.ScriptDescTextEntry = script_desc_textentry
--priority
local script_prio_label = DF:CreateLabel (parent, "Priority:", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
local script_prio_entry = DF:CreateSlider (parent, 191, 20, 1, 99, 1, 99, false, "ScriptPrioritySlider", _, _, options_slider_template, _)
script_prio_entry:SetPoint ("topleft", script_prio_label, "bottomleft", 0, -2)
script_prio_entry.tooltip = "Lower number -> higher priority.\nRight Click to Type the Value"
mainFrame.ScriptPrioSlideEntry = script_prio_entry
--options button
local scriptOptionButton = DF:CreateButton (parent, function() Plater.RefreshUserScriptOptions(mainFrame) end, 170, 20, "Options", 0, nil, nil, nil, nil, nil, options_button_template)
local scriptOptionButtonAdmin = DF:CreateButton (parent, function() Plater.RefreshAdminScriptOptions(mainFrame) end, 20, 20, "", 0, nil, nil, nil, nil, nil, options_button_template)
scriptOptionButton.tooltip = "Show options for this script or mod"
scriptOptionButtonAdmin.tooltip = "Build or edit the options panel for this script or mod"
scriptOptionButtonAdmin:SetIcon ([[Interface\BUTTONS\UI-OptionsButton]], 18, 18, "overlay", false, false, 0, -3, 0, false)
scriptOptionButton:SetPoint("topleft", script_prio_entry, "bottomleft", 0, -5) --position
scriptOptionButtonAdmin:SetPoint("left", scriptOptionButton, "right", 1, 0)
mainFrame.ScriptOptionButton = scriptOptionButton
mainFrame.ScriptOptionButtonAdmin = scriptOptionButtonAdmin
parent.ScriptNameLabel = script_name_label
parent.ScriptIconLabel = script_icon_label
parent.ScriptDescLabel = script_desc_label
parent.ScriptPrioLabel = script_prio_label
end
local create_import_box = function (parent, mainFrame)
--import and export string text editor
local import_text_editor = DF:NewSpecialLuaEditorEntry (parent, edit_script_size[1], edit_script_size[2], "ImportEditor", "$parentImportEditor", true)
import_text_editor:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
import_text_editor:SetBackdropBorderColor (unpack (luaeditor_border_color))
import_text_editor:SetBackdropColor (unpack (luaeditor_backdrop_color))
import_text_editor:Hide()
--hide the code editor when the import text editor is shown
import_text_editor:SetScript ("OnShow", function()
mainFrame.CodeEditorLuaEntry:Hide()
end)
--show the code editor when the import text editor is hide
import_text_editor:SetScript ("OnHide", function()
mainFrame.CodeEditorLuaEntry:Show()
end)
mainFrame.ImportTextEditor = import_text_editor
--import info
local info_import_label = DF:CreateLabel (import_text_editor, "IMPORT INFO:", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
info_import_label:SetPoint ("bottomleft", import_text_editor, "topleft", 0, 2)
mainFrame.ImportTextEditor.TextInfo = info_import_label
--import button
local okay_import_button = DF:CreateButton (import_text_editor, mainFrame.ImportScript, buttons_size[1], buttons_size[2], "Okay", -1, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
okay_import_button:SetIcon ([[Interface\BUTTONS\UI-Panel-BiggerButton-Up]], 20, 20, "overlay", {0.1, .9, 0.1, .9})
--cancel button
local cancel_import_button = DF:CreateButton (import_text_editor, function() mainFrame.ImportTextEditor:Hide() end, buttons_size[1], buttons_size[2], "Cancel", -1, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
cancel_import_button:SetIcon ([[Interface\BUTTONS\UI-Panel-MinimizeButton-Up]], 20, 20, "overlay", {0.1, .9, 0.1, .9})
import_text_editor.OkayButton = okay_import_button
import_text_editor.CancelButton = cancel_import_button
end
local create_code_editor = function (parent, mainFrame)
local code_editor = DF:NewSpecialLuaEditorEntry (parent, edit_script_size[1], edit_script_size[2], "CodeEditor", "$parentCodeEditor", false, true)
--need to make the scroll of line numbers be mouse off (enablemouse(false))
code_editor.scroll:SetBackdrop (nil)
code_editor.editbox:SetBackdrop (nil)
code_editor:SetBackdrop (nil)
DF:ReskinSlider (code_editor.scroll)
--DF:ApplyStandardBackdrop (code_editor, false, 1)
if (not code_editor.__background) then
code_editor.__background = code_editor:CreateTexture (nil, "background")
end
code_editor:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1})
code_editor:SetBackdropBorderColor (0, 0, 0, 1)
code_editor.__background:SetColorTexture (0.2317647, 0.2317647, 0.2317647)
code_editor.__background:SetVertexColor (0.27, 0.27, 0.27)
code_editor.__background:SetAlpha (0.8)
code_editor.__background:SetVertTile (true)
code_editor.__background:SetHorizTile (true)
code_editor.__background:SetAllPoints()
mainFrame.CodeEditorLuaEntry = code_editor
--add api palette dropdown
local on_select_FW_option = function (self, fixed_parameter, option_selected)
local api = Plater.APIList [option_selected]
code_editor.editbox:Insert (api.Signature)
end
local build_API_dropdown_options = function()
local t = {}
for i = 1, #Plater.APIList do
local api = Plater.APIList [i]
t [#t + 1] = {label = api.Name, value = i, onclick = on_select_FW_option, desc = "Signature:\n|cFFFFFF00" .. api.Signature .. "|r\n\n" .. api.Desc, tooltipwidth = 300}
end
return t
end
local add_API_label = DF:CreateLabel (parent, "API:", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
local add_API_dropdown = DF:CreateDropDown (parent, build_API_dropdown_options, 1, 130, 20, "AddAPIDropdown", _, options_dropdown_template)
mainFrame.AddAPIDropdown = add_API_dropdown
add_API_dropdown:SetFrameStrata (code_editor:GetFrameStrata())
add_API_dropdown:SetFrameLevel (code_editor:GetFrameLevel()+100)
--top right of the code editor
add_API_dropdown:SetPoint ("bottomright", code_editor, "topright", 0, 2)
add_API_label:SetPoint ("right", add_API_dropdown, "left", -2, 0)
--add framework palette dropdowns
local frameworkSelected
local memberNameCallback = function (text)
if (text and text ~= "" and not text:find ("%s")) then
text = DF:Trim (text)
local textToAdd = frameworkSelected.Signature
--save the current cursor position
code_editor.editbox:SetFocus (true)
local cursorPosition = code_editor.editbox:GetCursorPosition()
--insert the text
local textToInsert = "unitFrame." .. text .. " = unitFrame." .. text .. " or " .. frameworkSelected.Signature
code_editor.editbox:Insert (textToInsert)
if (frameworkSelected.AddCall) then
code_editor.editbox:Insert ("\n")
local addCallString = frameworkSelected.AddCall
addCallString = addCallString:gsub ("@ENV@", "unitFrame." .. text)
code_editor.editbox:Insert (addCallString)
code_editor.editbox:Insert ("\n")
end
--restore the cursor position
local argumentStart = textToInsert:find ("%(")
code_editor.editbox:SetCursorPosition (cursorPosition + argumentStart)
else
Plater:Msg ("Invalid variable name.")
end
end
local on_select_FW_option = function (self, fixed_parameter, option_selected)
local framework = Plater.FrameworkList [option_selected]
if (framework.AddVar) then
frameworkSelected = framework
DF:ShowTextPromptPanel ("Name the variable using letters, numbers and no spaces (e.g. myFlash, overlayTexture, animation1)", memberNameCallback)
else
code_editor.editbox:Insert (framework.Signature)
end
end
local build_FW_dropdown_options = function()
local t = {}
for i = 1, #Plater.FrameworkList do
local api = Plater.FrameworkList [i]
t [#t + 1] = {label = api.Name, value = i, onclick = on_select_FW_option, desc = "Signature:\n|cFFFFFF00" .. api.Signature .. "|r\n\n" .. api.Desc, tooltipwidth = 300}
end
return t
end
local add_FW_label = DF:CreateLabel (parent, "Framework:", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
local add_FW_dropdown = DF:CreateDropDown (parent, build_FW_dropdown_options, 1, 130, 20, "AddFWDropdown", _, options_dropdown_template)
mainFrame.AddFWDropdown = add_FW_dropdown
add_FW_dropdown:SetFrameStrata (code_editor:GetFrameStrata())
add_FW_dropdown:SetFrameLevel (code_editor:GetFrameLevel()+100)
add_FW_dropdown:SetPoint ("right", add_API_label, "left", -10, 0)
add_FW_label:SetPoint ("right", add_FW_dropdown, "left", -2, 0)
--error text
local errortext_frame = CreateFrame ("frame", nil, code_editor, BackdropTemplateMixin and "BackdropTemplate")
errortext_frame:SetPoint ("bottomleft", code_editor, "bottomleft", 1, 1)
errortext_frame:SetPoint ("bottomright", code_editor, "bottomright", -1, 1)
errortext_frame:SetHeight (20)
errortext_frame:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
errortext_frame:SetBackdropBorderColor (unpack (luaeditor_border_color))
errortext_frame:SetBackdropColor (0, 0, 0, 1)
errortext_frame:SetFrameLevel(code_editor:GetFrameLevel()+10)
DF:ApplyStandardBackdrop(errortext_frame)
errortext_frame.bgTexture = errortext_frame:CreateTexture(nil, "artwork")
errortext_frame.bgTexture:SetVertexColor(.3, .3, .3, .95)
errortext_frame.bgTexture:SetAllPoints()
local errortext_label = DF:CreateLabel (errortext_frame, "", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
errortext_label.textcolor = "red"
errortext_label:SetPoint ("left", errortext_frame, "left", 3, 0)
code_editor.NextCodeCheck = 0.33
code_editor:HookScript ("OnUpdate", function (self, deltaTime)
code_editor.NextCodeCheck = code_editor.NextCodeCheck - deltaTime
if (code_editor.NextCodeCheck < 0) then
local script = code_editor:GetText()
script = "return " .. script
local func, errortext = loadstring (script, "Q")
if (not func) then
local firstLine = strsplit ("\n", script, 2)
errortext = errortext:gsub (firstLine, "")
errortext = errortext:gsub ("%[string \"", "")
errortext = errortext:gsub ("...\"]:", "")
errortext = errortext:gsub ("Q\"]:", "")
errortext = "Line " .. errortext
errortext_label.text = errortext
else
errortext_label.text = ""
end
code_editor.NextCodeCheck = 0.33
end
--
end)
--apply button
local apply_script_button = DF:CreateButton (code_editor, mainFrame.ApplyScript, buttons_size[1], buttons_size[2], "Apply", -1, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
apply_script_button:SetIcon ([[Interface\BUTTONS\UI-Panel-BiggerButton-Up]], 20, 20, "overlay", {0.1, .9, 0.1, .9})
apply_script_button:SetFrameLevel(code_editor:GetFrameLevel()+11)
--save button
local save_script_button = DF:CreateButton (code_editor, mainFrame.SaveScript, buttons_size[1], buttons_size[2], "Save", -1, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
save_script_button:SetIcon ([[Interface\BUTTONS\UI-Panel-ExpandButton-Up]], 20, 20, "overlay", {0.1, .9, 0.1, .9})
save_script_button.tooltip = "While editing, you may use:\n\n|cFFFFFF00SHIFT + Enter|r: save the script, apply the changes and don't lose the focus on the editor.\n\n|cFFFFFF00CTRL + Enter|r: save the script and apply the changes."
save_script_button:SetFrameLevel(code_editor:GetFrameLevel()+11)
--cancel button
local cancel_script_button = DF:CreateButton (code_editor, mainFrame.CancelEditing, buttons_size[1], buttons_size[2], "Cancel", -1, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
cancel_script_button:SetIcon ([[Interface\BUTTONS\UI-Panel-MinimizeButton-Up]], 20, 20, "overlay", {0.1, .9, 0.1, .9})
cancel_script_button:SetFrameLevel(code_editor:GetFrameLevel()+11)
--documentation icon
local docs_button = DF:CreateButton (code_editor, mainFrame.OpenDocs, buttons_size[1], buttons_size[2], "Docs", -1, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
docs_button:SetIcon ([[Interface\BUTTONS\UI-GuildButton-PublicNote-Up]], 16, 16, "overlay", {0, 1, 0, 1})
docs_button:SetFrameLevel(code_editor:GetFrameLevel()+11)
local save_feedback_texture = save_script_button:CreateTexture (nil, "overlay")
save_feedback_texture:SetColorTexture (1, 1, 1)
save_feedback_texture:SetAllPoints()
save_feedback_texture:SetDrawLayer ("overlay", 7)
save_feedback_texture:SetAlpha (0)
local save_button_flash_animation = DF:CreateAnimationHub (save_feedback_texture)
DF:CreateAnimation (save_button_flash_animation, "alpha", 1, 0.08, 0, 0.2)
DF:CreateAnimation (save_button_flash_animation, "alpha", 2, 0.08, 0.4, 0)
local save_button_feedback_animation = DF:CreateAnimationHub (save_script_button, function() save_button_flash_animation:Play() end)
local speed = 0.06
local rotation = 0
local translation = 7
--DF:CreateAnimation (save_button_feedback_animation, "scale", 1, speed, 1, 1, 1.01, 1.01)
DF:CreateAnimation (save_button_feedback_animation, "translation", 1, speed, 0, -translation)
DF:CreateAnimation (save_button_feedback_animation, "rotation", 1, speed, -rotation)
--DF:CreateAnimation (save_button_feedback_animation, "scale", 1, speed, 1.01, 1.01, 1, 1)
DF:CreateAnimation (save_button_feedback_animation, "translation", 2, speed, 0, translation)
DF:CreateAnimation (save_button_feedback_animation, "rotation", 2, speed, rotation)
DF:CreateAnimation (save_button_feedback_animation, "rotation", 3, speed, rotation)
DF:CreateAnimation (save_button_feedback_animation, "rotation", 4, speed, -rotation)
code_editor.editbox:HookScript ("OnEnterPressed", function()
--if shift is pressed when the user pressed enter, save/apply the script and don't lose the focus of the editor
if (IsShiftKeyDown()) then
mainFrame.SaveScript()
code_editor.editbox:SetFocus (true)
save_button_feedback_animation:Play()
--if ctrl is pressed when the user pressed enter, save the script like if the user has pressed the Save button
elseif (IsControlKeyDown()) then
mainFrame.SaveScript()
save_button_feedback_animation:Play()
else
code_editor.editbox:Insert ("\n")
end
end)
mainFrame.ApplyScriptButton = apply_script_button
mainFrame.SaveScriptButton = save_script_button
mainFrame.CancelScriptButton = cancel_script_button
mainFrame.DocsButton = docs_button
end
function Plater.CreateWagoPanel()
--controi o menu principal
local f = PlaterOptionsPanelFrame
local mainFrame = PlaterOptionsPanelContainer
local wagoFrame = mainFrame.AllFrames [PLATER_OPTIONS_WAGO_TAB]
local wagoSlugFrame = CreateFrame ("frame", "$parentWagoSlugFrame", wagoFrame)
wagoSlugFrame:SetPoint("topleft", wagoFrame, "topleft")
wagoSlugFrame:SetPoint("bottomright", wagoFrame, "bottomright")
wagoFrame.wagoSlugFrame = wagoSlugFrame
wagoSlugFrame:Show()
--wagoSlugFrame:SetScript("OnShow", function() end)
local wagoStashFrame = CreateFrame ("frame", "$parentWagoStashFrame", wagoFrame)
wagoStashFrame:SetPoint("topleft", wagoFrame, "topleft")
wagoStashFrame:SetPoint("bottomright", wagoFrame, "bottomright")
wagoFrame.wagoStashFrame = wagoStashFrame
wagoStashFrame:Show()
local currentEditingScript = nil
wagoSlugFrame.SearchString = ""
wagoSlugFrame.ScriptType = "wago_slugs"
wagoStashFrame.SearchString = ""
wagoStashFrame.ScriptType = "wago_stash"
update_wago_slug_data()
update_wago_stash_data()
--create the frame which will hold the create panel
local wago_info_frame = CreateFrame ("frame", "$parentWagoInfoFrame2", wagoFrame, BackdropTemplateMixin and "BackdropTemplate")
wago_info_frame:SetSize (unpack (main_frames_size))
wago_info_frame:SetScript ("OnShow", function() end)
wago_info_frame:SetScript ("OnHide", function() end)
wago_info_frame:Hide()
wago_info_frame:SetPoint ("topleft", wagoFrame, "topleft", scrollbox_size[1] + 30, start_y)
wagoSlugFrame.EditScriptFrame = wago_info_frame
wago_info_frame = CreateFrame ("frame", "$parentWagoInfoFrame3", wagoFrame, BackdropTemplateMixin and "BackdropTemplate")
wago_info_frame:SetSize (unpack (main_frames_size))
wago_info_frame:SetScript ("OnShow", function() end)
wago_info_frame:SetScript ("OnHide", function() end)
wago_info_frame:Hide()
wago_info_frame:SetPoint ("topleft", wagoFrame, "topleft", scrollbox_size[1] + 30, start_y)
wagoStashFrame.EditScriptFrame = wago_info_frame
create_script_scroll (wagoSlugFrame)
create_script_scroll (wagoStashFrame)
wagoSlugFrame.ScriptScrollLabel.text = "Updates/Imports"
wagoSlugFrame.ScriptSearchTextEntry.widget:SetPoint ("topleft", wagoFrame, "topleft", 10, start_y - 10)
wagoSlugFrame.ScriptSelectionScrollBox:SetPoint ("topleft", wagoSlugFrame.ScriptSearchTextEntry.widget, "bottomleft", 0, -20)
wagoSlugFrame.ScriptScrollLabel:SetPoint ("bottomleft", wagoSlugFrame.ScriptSelectionScrollBox, "topleft", 0, 2)
wagoSlugFrame.ScriptEnabledLabel:Hide()
wagoStashFrame.ScriptScrollLabel.text = "Stash"
wagoStashFrame.ScriptSearchTextEntry.widget:SetPoint ("topleft", wagoSlugFrame.ScriptSearchTextEntry.widget, "topright", 20, 0)
wagoStashFrame.ScriptSelectionScrollBox:SetPoint ("topleft", wagoStashFrame.ScriptSearchTextEntry.widget, "bottomleft", 0, -20)
wagoStashFrame.ScriptScrollLabel:SetPoint ("bottomleft", wagoStashFrame.ScriptSelectionScrollBox, "topleft", 0, 2)
wagoStashFrame.ScriptEnabledLabel:Hide()
local helpText = "The 'Updates/Imports' list contains all scripts, mods and profiles that are made available as update by the WeakAuras-Companion app or other wago.io updater tools." .. "\n\n"
helpText = helpText .. "The 'Stash' list contains content sent from wago.io to the client directly via 'Send to Desktop App'.".."\n\n"
helpText = helpText .. "The lists are sorted by 'updates' first." .. "\n\n"
helpText = helpText .. "Use the wago-icons for updates or the right-click menu to import." --localize me
local wagoTabInfoLabel = DF:CreateLabel (wagoStashFrame, helpText, DF:GetTemplate ("font", "PLATER_BUTTON"))
wagoTabInfoLabel.width = 200
--wagoTabInfoLabel.height = 80
wagoTabInfoLabel.valign = "bottom"
wagoTabInfoLabel.align = "left"
wagoTabInfoLabel:SetPoint ("bottomleft", wagoStashFrame.ScriptSelectionScrollBox, "bottomright", 40, 0)
local importInfoLabel = DF:CreateLabel (wagoFrame, "Selected Import Info:", DF:GetTemplate ("font", "PLATER_BUTTON"))
importInfoLabel.width = 200
importInfoLabel:SetPoint ("topleft", wagoStashFrame.ScriptSelectionScrollBox, "topright", 40, 40)
local importInfoText = ""
importInfoText = importInfoText .. "Name: \n\n"
importInfoText = importInfoText .. "Import-Revision: \n"
importInfoText = importInfoText .. "Import-Version: \n\n"
local importInfo = DF:CreateLabel(wagoFrame, importInfoText, 10, "orange")
importInfo.width = 200
importInfo.height = 120
importInfo.valign = "top"
importInfo.align = "left"
importInfo:SetPoint("topleft", importInfoLabel, "bottomleft", 0, -5)
wagoFrame.importInfoText = importInfo
function wagoFrame.GetCurrentScriptObject()
return currentEditingScript
end
function wagoSlugFrame.GetCurrentScriptObject()
return currentEditingScript
end
function wagoStashFrame.GetCurrentScriptObject()
return currentEditingScript
end
function wagoSlugFrame.GetScriptTriggerTypeName()
return ""
end
function wagoStashFrame.GetScriptTriggerTypeName()
return ""
end
function wagoSlugFrame.GetScriptObject (script_id)
local script = CompanionSlugData [script_id]
if (script) then
return script
else
Plater:Msg ("GetScriptObject could find the script id")
return
end
end
function wagoStashFrame.GetScriptObject (script_id)
local script = CompanionStashData [script_id]
if (script) then
return script
else
Plater:Msg ("GetScriptObject could find the script id")
return
end
end
function wagoFrame.UpdateEditingPanel()
--get the current editing object
local scriptObject = wagoFrame.GetCurrentScriptObject()
local importInfoText = ""
if scriptObject then
importInfoText = importInfoText .. "Name: \n" .. scriptObject.FullName .. "\n\n"
importInfoText = importInfoText .. "Import-Revision: " .. scriptObject.version .. "\n"
importInfoText = importInfoText .. "Import-Version: " .. scriptObject.semver .. "\n"
importInfoText = importInfoText .. (scriptObject.url or "")
else
importInfoText = importInfoText .. "Name: \n\n"
importInfoText = importInfoText .. "Import-Revision: \n"
importInfoText = importInfoText .. "Import-Version: \n\n"
end
wagoFrame.importInfoText:SetText(importInfoText)
end
function wagoSlugFrame.EditScript (script_id)
wagoStashFrame.CancelEditing()
local scriptObject
--> check if passed a script object
if (type (script_id) == "table") then
scriptObject = script_id
else
scriptObject = wagoSlugFrame.GetScriptObject (script_id)
end
if (not scriptObject) then
return
end
--set the new editing script
currentEditingScript = scriptObject
--load the values in the frame
wagoFrame.UpdateEditingPanel()
end
function wagoStashFrame.EditScript (script_id)
wagoSlugFrame.CancelEditing()
local scriptObject
--> check if passed a script object
if (type (script_id) == "table") then
scriptObject = script_id
else
scriptObject = wagoStashFrame.GetScriptObject (script_id)
end
if (not scriptObject) then
return
end
--set the new editing script
currentEditingScript = scriptObject
--load the values in the frame
wagoFrame.UpdateEditingPanel()
end
--restore the values on the text fields and scroll boxes to the values on the object
function wagoStashFrame.CancelEditing ()
--clear current editing script
currentEditingScript = nil
--reload the script selection scrollbox in case the script got renamed
wagoStashFrame.ScriptSelectionScrollBox:Refresh()
end
function wagoSlugFrame.CancelEditing ()
--clear current editing script
currentEditingScript = nil
--reload the script selection scrollbox in case the script got renamed
wagoSlugFrame.ScriptSelectionScrollBox:Refresh()
end
wagoFrame:SetScript ("OnShow", function()
--update the hook scripts scrollbox
update_wago_stash_data()
update_wago_slug_data()
wagoSlugFrame.ScriptSelectionScrollBox:Refresh()
wagoStashFrame.ScriptSelectionScrollBox:Refresh()
end)
end
function Plater.CreateHookingPanel()
--controi o menu principal
local f = PlaterOptionsPanelFrame
local mainFrame = PlaterOptionsPanelContainer
--[=[
Plater.db.profile.hook_data
Plater.db.profile.hook_data_trash
Plater.db.profile.hook_auto_imported
Plater.db.profile.hook_banned_user
hook_data = {},
hook_data_trash = {}, --deleted scripts are placed here, they can be restored in 30 days
hook_auto_imported = {}, --store the name and revision of scripts imported from the Plater script library
hook_banned_user = {}, --players banned from sending scripts to this player
--]=]
local hookFrame = mainFrame.AllFrames [PLATER_OPTIONS_HOOKING_TAB]
--holds the current text to search
hookFrame.SearchString = ""
hookFrame.ScriptType = "hook"
hookFrame.LastAddedHookTime = GetTime()
local currentEditingScript = nil
function hookFrame.GetCurrentScriptObject()
return currentEditingScript
end
function hookFrame.GetScriptObject (script_id)
local script = Plater.db.profile.hook_data [script_id]
if (script) then
return script
else
Plater:Msg ("GetScriptObject could find the script id")
return
end
end
--restore the values on the text fields and scroll boxes to the values on the object
function hookFrame.CancelEditing (is_deleting)
if (not is_deleting) then
--re fill all the text entried and dropdowns to the default from the script
--doing this to restore the script so it can do a hot reload
hookFrame.UpdateEditingPanel()
--hot reload restored scripts
hookFrame.ApplyScript()
end
--clear current editing script
currentEditingScript = nil
--lock the editing panel
hookFrame.EditScriptFrame:LockFrame()
--reload the script selection scrollbox in case the script got renamed
hookFrame.ScriptSelectionScrollBox:Refresh()
end
--must have this for the shared frames
function hookFrame.GetScriptTriggerTypeName()
return ""
end
--save all values
function hookFrame.SaveScript()
--get the current editing object
local scriptObject = hookFrame.GetCurrentScriptObject()
--script name
scriptObject.Name = hookFrame.ScriptNameTextEntry.text
--script icon
scriptObject.Icon = hookFrame.ScriptIconButtonTexture or hookFrame.ScriptIconButton:GetIconTexture()
--script description
scriptObject.Desc = hookFrame.ScriptDescTextEntry.text
--script priority
local scriptPrioChanged = not (round(scriptObject.Prio) == round(hookFrame.ScriptPrioSlideEntry.value))
scriptObject.Prio = round(hookFrame.ScriptPrioSlideEntry.value)
--time and revision
scriptObject.Time = time()
scriptObject.Revision = scriptObject.Revision + 1
--reload the script selection scrollbox in case the script got renamed
hookFrame.ScriptSelectionScrollBox:Refresh()
--remove focus of everything
hookFrame.CodeEditorLuaEntry:ClearFocus()
hookFrame.ScriptNameTextEntry:ClearFocus()
hookFrame.ScriptDescTextEntry:ClearFocus()
hookFrame.ScriptPrioSlideEntry:ClearFocus()
--transfer code from temp table to hook table
--check if has any script changes before wipe and recompile all scripts
local haveChanges = scriptPrioChanged
for hookName, _ in pairs (scriptObject.Hooks) do
if (scriptObject.Hooks [hookName] ~= scriptObject.HooksTemp [hookName]) then
haveChanges = true
end
scriptObject.Hooks [hookName] = scriptObject.HooksTemp [hookName]
end
--save the current code for the hook being edited now
if (scriptObject.LastHookEdited ~= "" and scriptObject.Hooks [scriptObject.LastHookEdited]) then
local currentCode = hookFrame.CodeEditorLuaEntry:GetText()
if (scriptObject.Hooks [scriptObject.LastHookEdited] ~= currentCode) then
haveChanges = true
end
scriptObject.Hooks [scriptObject.LastHookEdited] = currentCode
scriptObject.HooksTemp [scriptObject.LastHookEdited] = currentCode
end
--do a hot reload on the script
if (haveChanges) then
hookFrame.ApplyScript()
end
--refresh all nameplates shown in the screen
Plater.FullRefreshAllPlates()
end
--hot reload the script by compiling it and applying it to the nameplates
function hookFrame.ApplyScript()
Plater.WipeAndRecompileAllScripts("hook")
end
function hookFrame.RemoveScript(scriptId)
local scriptObjectToBeRemoved = hookFrame.GetScriptObject (scriptId)
local currentScript = hookFrame.GetCurrentScriptObject()
--check if the script to be removed is valid
if (not scriptObjectToBeRemoved) then
return
end
--if is the current script being edited, cancel the edit
if (currentScript == scriptObjectToBeRemoved) then
--cancel the editing process
hookFrame.CancelEditing (true)
end
--set the time when the script has been moved to trash
scriptObjectToBeRemoved.__TrashAt = time()
tinsert (Plater.db.profile.hook_data_trash, scriptObjectToBeRemoved)
tremove (Plater.db.profile.hook_data, scriptId)
--refresh the script selection scrollbox
hookFrame.ScriptSelectionScrollBox:Refresh()
GameCooltip:Hide()
Plater:Msg ("Script moved to trash.")
--reload all scripts
Plater.WipeAndRecompileAllScripts (hookFrame.ScriptType)
end
function hookFrame.DuplicateScript (scriptId)
local scriptToBeCopied = hookFrame.GetScriptObject (scriptId)
local newScript = DF.table.copy ({}, scriptToBeCopied)
--generate a new unique id
newScript.UID = createUniqueIdentifier()
--cleanup:
newScript.HooksTemp = {}
newScript.url = nil
newScript.semver = nil
newScript.version = nil
tinsert (Plater.db.profile.hook_data, newScript)
hookFrame.ScriptSelectionScrollBox:Refresh()
Plater:Msg ("Script duplicated!.")
end
--called from the context menu when right click an option in the script menu
function hookFrame.ExportScript (scriptId)
local scriptToBeExported = hookFrame.GetScriptObject (scriptId)
--convert the script table into a index table for smaller size
local tableToExport = Plater.PrepareTableToExport (scriptToBeExported)
--compress the index table
local encodedString = Plater.CompressData (tableToExport, "print")
hookFrame.ImportTextEditor.IsImporting = false
hookFrame.ImportTextEditor.IsExporting = true
hookFrame.ImportTextEditor:Show()
hookFrame.CodeEditorLuaEntry:Hide()
hookFrame.ScriptOptionsPanelAdmin:Hide()
hookFrame.ScriptOptionsPanelUser:Hide()
hookFrame.ImportTextEditor:SetText (encodedString)
hookFrame.ImportTextEditor.TextInfo.text = "Exporting '" .. scriptToBeExported.Name .. "'"
--if there's anything being edited, start editing the script which is being exported
if (not hookFrame.GetCurrentScriptObject()) then
hookFrame.EditScript (scriptId)
end
hookFrame.EditScriptFrame:Show()
C_Timer.After (0.3, function()
hookFrame.ImportTextEditor.editbox:SetFocus (true)
hookFrame.ImportTextEditor.editbox:HighlightText()
end)
end
function hookFrame.ShowImportTextField()
--if editing a script, save it and close it
local scriptObject = hookFrame.GetCurrentScriptObject()
if (scriptObject) then
hookFrame.SaveScript()
hookFrame.CancelEditing()
--refresh the script selection scrollbox
hookFrame.ScriptSelectionScrollBox:Refresh()
end
--lock the editing panel
hookFrame.EditScriptFrame:LockFrame()
hookFrame.EditScriptFrame:Show()
hookFrame.ImportTextEditor:Show()
hookFrame.ImportTextEditor:SetText ("")
hookFrame.ImportTextEditor.IsImporting = true
hookFrame.ImportTextEditor.IsExporting = false
hookFrame.ImportTextEditor:SetFocus (true)
hookFrame.ImportTextEditor.TextInfo.text = "Paste the string:"
end
--this is only called from the 'okay' button in the import text editor
function hookFrame.ImportScript()
--if clicked in the 'okay' button when the import text editor is showing a string to export, just hide the import editor
if (hookFrame.ImportTextEditor.IsExporting) then
hookFrame.ImportTextEditor.IsImporting = nil
hookFrame.ImportTextEditor.IsExporting = nil
hookFrame.ImportTextEditor:Hide()
return
end
local text = hookFrame.ImportTextEditor:GetText()
import_mod_or_script (text)
hookFrame.ImportTextEditor.IsImporting = nil
hookFrame.ImportTextEditor:Hide()
end
--set all values from the current editing script object to all text entried and scroll fields
function hookFrame.UpdateEditingPanel()
--get the current editing object
local scriptObject = hookFrame.GetCurrentScriptObject()
--set the data from the object in the widgets
hookFrame.ScriptNameTextEntry.text = scriptObject.Name
hookFrame.ScriptNameTextEntry:ClearFocus()
hookFrame.ScriptIconButton:SetIcon (scriptObject.Icon)
hookFrame.ScriptIconButtonTexture = scriptObject.Icon
hookFrame.ScriptDescTextEntry.text = scriptObject.Desc or ""
hookFrame.ScriptDescTextEntry:ClearFocus()
hookFrame.ScriptPrioSlideEntry.value = round(scriptObject.Prio or 99)
hookFrame.ScriptPrioSlideEntry:ClearFocus()
hookFrame.HookScrollBox:Refresh()
hookFrame.HookTypeDropdown:Refresh()
--validate the latest selected hook
scriptObject.LastHookEdited = scriptObject.LastHookEdited or next (scriptObject.Hooks)
--check if the hook script for the last selected hook exists
if (scriptObject.LastHookEdited ~= "" and scriptObject.Hooks [scriptObject.LastHookEdited]) then
hookFrame.CodeEditorLuaEntry:SetText (scriptObject.Hooks [scriptObject.LastHookEdited])
else
--try to get a new last hook
scriptObject.LastHookEdited = next (scriptObject.Hooks) or ""
if (scriptObject.LastHookEdited ~= "") then
hookFrame.CodeEditorLuaEntry:SetText (scriptObject.Hooks [scriptObject.LastHookEdited])
else
hookFrame.CodeEditorLuaEntry:SetText ("")
end
end
hookFrame.CodeEditorLuaEntry:ClearFocus()
--copy scripts to the temp tables
for hookName, codeText in pairs (scriptObject.Hooks) do
scriptObject.HooksTemp [hookName] = codeText
end
hookFrame.HookTypeDropdown:Select (scriptObject.LastHookEdited)
end
--start editing a script
function hookFrame.EditScript (script_id)
local scriptObject
--> check if passed a script object
if (type (script_id) == "table") then
scriptObject = script_id
else
scriptObject = hookFrame.GetScriptObject (script_id)
end
if (not scriptObject) then
return
end
hookFrame.EditScriptFrame:UnlockFrame()
hookFrame.EditScriptFrame:Show()
--set the new editing script
currentEditingScript = scriptObject
if (scriptObject.Hooks ["Constructor"]) then
scriptObject.LastHookEdited = "Constructor"
end
--load the values in the frame
hookFrame.UpdateEditingPanel()
end
hookFrame:SetScript ("OnShow", function()
--update the hook scripts scrollbox
hookFrame.ScriptSelectionScrollBox:Refresh()
--update options
if hookFrame.ScriptOptionsPanelUser:IsShown() then
Plater.RefreshUserScriptOptions(hookFrame)
end
if hookFrame.ScriptOptionsPanelAdmin:IsShown() then
Plater.RefreshAdminScriptOptions(hookFrame)
end
--check trash can timeout
local timeout = 60 * 60 * 24 * 30
for i = #Plater.db.profile.hook_data_trash, 1, -1 do
local scriptObject = Plater.db.profile.hook_data_trash [i]
if (not scriptObject.__TrashAt or scriptObject.__TrashAt + timeout < time()) then
tremove (Plater.db.profile.hook_data_trash, i)
end
end
end)
hookFrame:SetScript ("OnHide", function()
--save
local hookObject = hookFrame.GetCurrentScriptObject()
if (hookObject) then
hookFrame.SaveScript()
end
end)
hookFrame.DefaultScript = [=[
function (self, unitId, unitFrame, envTable, modTable)
--insert code here
end
]=]
hookFrame.DefaultScriptNoNameplate = [=[
function (modTable)
--insert code here
end
]=]
hookFrame.DefaultPayloadScript = [=[
function (self, unitId, unitFrame, envTable, modTable, ...)
--vararg is the payload of the event, e.g. 'powerType' for power updates
end
]=]
hookFrame.DefaultReceiveCommScript = [=[
function (modTable, source, ...)
--source is the player who sent the comm, vararg is the payload
end
]=]
hookFrame.DefaultSendCommScript = [=[
function (modTable)
--called on a timer internally. use 'Plater.SendComm(payload)' to send comm-data if needed.
end
]=]
--a new script has been created
function hookFrame.CreateNewScript()
--build the table of the new script
local newScriptObject = { --~prototype ~new ~create ñew
Enabled = true,
Name = "New Mod",
Icon = "",
Desc = "",
Author = UnitName ("Player") .. "-" .. GetRealmName(),
Time = time(),
Revision = 1,
PlaterCore = Plater.CoreVersion,
Hooks = {
--["Function Name"] = " CODE " ??
},
HooksTemp = {},
LastHookEdited = "",
LoadConditions = DF:UpdateLoadConditionsTable ({}),
--ModEnvStart = "", --run once when the mod starts
--ModEnvTable = {}, --store data that is shared among all nameplates running this script
Options = {}, --store options where the end user can change aspects of the hook without messing with the code
UID = createUniqueIdentifier(), --create an ID that identifies this script, the ID cannot be changed, if the script is duplicated, a new id is generated
}
Plater.CreateOptionTableForScriptObject(newScriptObject)
--add it to the database
tinsert (Plater.db.profile.hook_data, newScriptObject)
--start editing the new script
hookFrame.EditScript (#Plater.db.profile.hook_data)
--refresh the scrollbox showing all scripts created
hookFrame.ScriptSelectionScrollBox:Refresh()
--refresh the options panel
end
function hookFrame:OpenDocs()
if (PlaterDocsPanel) then
PlaterDocsPanel:Show()
return
end
local f = DF:CreateSimplePanel (UIParent, 460, 90, "Plater Script Documentation", "PlaterDocsPanel")
f:SetFrameStrata ("TOOLTIP")
f:SetPoint ("center", UIParent, "center")
DF:CreateBorder (f)
local LinkBox = DF:CreateTextEntry (f, function()end, 380, 20, "ExportLinkBox", _, _, options_dropdown_template)
LinkBox:SetPoint ("center", f, "center", 0, -10)
f:SetScript ("OnShow", function()
LinkBox:SetText ("https://www.curseforge.com/wow/addons/plater-nameplates/pages/scripts")
C_Timer.After (.1, function()
LinkBox:SetFocus (true)
LinkBox:HighlightText()
end)
end)
f:Hide()
f:Show()
end
function hookFrame.AddHookToScript (hookName)
local scriptObject = hookFrame.GetCurrentScriptObject()
if (not scriptObject) then
return
end
--add the hook to the script object
if (not scriptObject.Hooks [hookName]) then
local defaultScript
if (hookName == "Load Screen" or hookName == "Player Logon" or hookName == "Initialization" or hookName == "Deinitialization") then
defaultScript = hookFrame.DefaultScriptNoNameplate
elseif (hookName == "Player Power Update") then
defaultScript = hookFrame.DefaultPayloadScript
elseif (hookName == "Receive Comm Message") then
defaultScript = hookFrame.DefaultReceiveCommScript
elseif (hookName == "Send Comm Message") then
defaultScript = hookFrame.DefaultSendCommScript
else
defaultScript = hookFrame.DefaultScript
end
--try to restore code from the temp table
scriptObject.Hooks [hookName] = scriptObject.HooksTemp [hookName] or defaultScript
scriptObject.HooksTemp [hookName] = defaultScript
end
--when adding, it start to edit the code for the hook added, check if there's a code being edited and save it
local lastEditedHook = scriptObject.LastHookEdited
if (lastEditedHook ~= "") then
scriptObject.HooksTemp [lastEditedHook] = hookFrame.CodeEditorLuaEntry:GetText()
end
hookFrame.CodeEditorLuaEntry:SetText (scriptObject.Hooks [hookName])
scriptObject.LastHookEdited = hookName
--update the hook scroll list
hookFrame.HookScrollBox:Refresh()
--refresh the hook selection dropdown
hookFrame.HookTypeDropdown:Refresh()
hookFrame.HookTypeDropdown:Select (hookName)
end
function hookFrame.RemoveHookFromScript (hookName)
local scriptObject = hookFrame.GetCurrentScriptObject()
if (not scriptObject) then
return
end
--remove the hook from this script object
if (scriptObject.Hooks [hookName]) then
scriptObject.Hooks [hookName] = nil
--won't delete the old hook script, instead just let the code there if the hook is added back later
--scriptObject.HooksTemp [hookName] = nil
end
--refresh the hook selection dropdown
hookFrame.HookTypeDropdown:Refresh()
--if the removed hook was the hook being edited, try to select another hook and start editing its code
if (scriptObject.LastHookEdited == hookName) then
scriptObject.LastHookEdited = next (scriptObject.Hooks) or ""
if (scriptObject.LastHookEdited ~= "") then
hookFrame.CodeEditorLuaEntry:SetText (scriptObject.Hooks [scriptObject.LastHookEdited])
hookFrame.HookTypeDropdown:Select (scriptObject.LastHookEdited)
else
hookFrame.CodeEditorLuaEntry:SetText ("")
end
end
--update the hook scroll list
hookFrame.HookScrollBox:Refresh()
end
--create the frame which will hold the create panel
local edit_script_frame = CreateFrame ("frame", "$parentCreateScript", hookFrame, BackdropTemplateMixin and "BackdropTemplate")
edit_script_frame:SetSize (unpack (main_frames_size))
edit_script_frame:SetScript ("OnShow", function()
end)
edit_script_frame:SetScript ("OnHide", function()
end)
edit_script_frame:Hide()
hookFrame.EditScriptFrame = edit_script_frame
function edit_script_frame.UnlockFrame()
hookFrame.ScriptNameTextEntry:Enable()
hookFrame.ScriptIconButton:Enable()
hookFrame.ScriptDescTextEntry:Enable()
hookFrame.ScriptPrioSlideEntry:Enable()
hookFrame.AddAPIDropdown:Enable()
hookFrame.AddFWDropdown:Enable()
hookFrame.CodeEditorLuaEntry:Enable()
hookFrame.SaveScriptButton:Enable()
hookFrame.CancelScriptButton:Enable()
hookFrame.HookTypeDropdown:Enable()
hookFrame.LoadConditionsButton:Enable()
hookFrame.ComponentsButton:Enable()
hookFrame.ScriptOptionButton:Enable()
hookFrame.ScriptOptionButtonAdmin:Enable()
end
function edit_script_frame.LockFrame()
hookFrame.ScriptNameTextEntry:SetText ("")
hookFrame.ScriptNameTextEntry:Disable()
hookFrame.ScriptIconButton:SetIcon ("")
hookFrame.ScriptIconButtonTexture = nil
hookFrame.ScriptIconButton:Disable()
hookFrame.ScriptDescTextEntry:SetText ("")
hookFrame.ScriptDescTextEntry:Disable()
hookFrame.ScriptPrioSlideEntry:SetValue (99)
hookFrame.ScriptPrioSlideEntry:Disable()
hookFrame.AddAPIDropdown:Disable()
hookFrame.AddFWDropdown:Disable()
hookFrame.CodeEditorLuaEntry:SetText ("")
hookFrame.CodeEditorLuaEntry:Disable()
hookFrame.SaveScriptButton:Disable()
hookFrame.CancelScriptButton:Disable()
hookFrame.HookTypeDropdown:Disable()
hookFrame.LoadConditionsButton:Disable()
hookFrame.ComponentsButton:Disable()
hookFrame.HookScrollBox:Refresh()
hookFrame.ScriptOptionButton:Disable()
hookFrame.ScriptOptionButtonAdmin:Disable()
hookFrame.ScriptOptionsPanelAdmin:Hide()
hookFrame.ScriptOptionsPanelUser:Hide()
end
function hookFrame.HideEditPanel()
edit_script_frame:Hide()
end
--end of the logic part
--create help frame
do
local help_popup = DF:CreateSimplePanel (UIParent, 1000, 480, "Plater Hook Help", "PlaterHookHelp")
help_popup:SetFrameStrata ("DIALOG")
help_popup:SetPoint ("center")
DF:ApplyStandardBackdrop (help_popup, false, 1.2)
help_popup:Hide()
hookFrame.HelpFrame = help_popup
local scripting_help_label = DF:CreateLabel (help_popup, "", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
local frontpageText_Welcome = "Hooking allows you to run code in a nameplate after a certain event happened.\n"
local frontpageText_Lua = "A basic knowledge of Lua programming may be required.\n\n"
local frontpageText_Triggers = "|cFFFFFF00How a Plater Hook Works:|r\n\nYou add an event and when the event is triggered at any nameplate it runs the code for that specific nameplate.\n"
local frontpageText_Scripts = "There's many types of events and they share an environment table between them for each nameplate.\n"
local frontpageText_Function = "\n|cFFFFFF00Function Parameters:|r\n\n|cFFC0C0C0function (self, unit, unitFrame, envTable)\n --code\nend|r\n\n|cFFFF5500self|r: is different for each type of event, for instance, self is the castBar frame for 'Cast Start' event and the unitFrame for 'Nameplate Added'.\n|cFFFF5500unit|r: unitId of the unit shown in the nameplate, use to query data, for example: UnitName (unitId).\n|cFFFF5500unitFrame|r: is the nameplate unit frame (parent of all widgets).\n|cFFFF5500envTable|r: a table where you can store data, this table is shared between each event script but not different nameplates.\n"
local frontpageText_ReturnValues = "\nWhat is a |cFFFF5500ReturnValue|r?\nIs what a function returns after a calling it, example:\nenvTable.MyFlash = Plater.CreateFlash (unitFrame.healthBar, 0.05, 2, 'white')\nPlater.CreateFlash() returned an object with information about the flash created, then this information is stored inside '|cFFFF5500envTable.MyFlash|r'\nYou can use it later to play the flash with '|cFFFF5500envTable.MyFlash:Play()|r' or stop it with '|cFFFF5500envTable.MyFlash:Stop()|r'."
local frontpageText_Parent = "\n\nWhat is a |cFFFF5500Parent|r?\nThe parent field required for create some widgets is the frame which will hold it, in other words: where it will be attach to."
scripting_help_label.text = frontpageText_Welcome .. frontpageText_Lua .. frontpageText_Triggers .. frontpageText_Scripts .. frontpageText_Function .. frontpageText_ReturnValues .. frontpageText_Parent
scripting_help_label.fontsize = 14
scripting_help_label:SetPoint ("topleft", help_popup, "topleft", 5, -25)
end
--create the header and script scroll box
create_script_control_header (hookFrame, "hook")
create_script_scroll(hookFrame)
--create the script name and desc frames
create_script_namedesc (hookFrame, edit_script_frame)
local onEnterHookButton = function (self)
if (self.CanAddHook or self.CanRemoveHook) then
self:SetBackdropColor (.3, .3, .3, 0.7)
end
GameCooltip2:Preset (2)
GameCooltip2:AddLine (self.tooltip)
GameCooltip2:ShowCooltip (self, "tooltip")
end
local onLeaveHookButton = function (self)
if (self.IsEditing) then
self:SetBackdropColor (1, .6, 0, 0.5)
else
self:SetBackdropColor (unpack (scrollbox_line_backdrop_color))
end
GameCooltip2:Hide()
end
local updateHookLine = function (self, index, hookName)
self.HookName:SetText (hookName)
self.tooltip = Plater.HookScriptsDesc [hookName]
self.Hook = hookName
self:SetBackdropBorderColor (0, 0, 0, 0)
self.AddedLabel:SetText ("")
self.RemoveButton:Hide()
self.AddButton:Hide()
self.CanAddHook = false
self.CanRemoveHook = false
self.IsEditing = false
self:SetAlpha (1)
local scriptObject = hookFrame.GetCurrentScriptObject()
if (not scriptObject) then
self:SetAlpha (.5)
return
end
--does this scriptObject has this hook?
if (scriptObject.Hooks [hookName]) then
self.AddedLabel:SetText ("ADDED")
self.RemoveButton:Show()
self:SetBackdropBorderColor (1, .6, 0, 0.5)
self.CanRemoveHook = true
self:SetAlpha (1)
--if this hook being edited?
if (scriptObject.LastHookEdited == hookName) then
self:SetBackdropColor (1, .6, 0, 0.5)
self.IsEditing = true
else
self:SetBackdropColor (unpack (scrollbox_line_backdrop_color))
end
else
self.CanAddHook = true
self.AddButton.Hook = hookName
self.AddButton:Show()
self:SetBackdropColor (unpack (scrollbox_line_backdrop_not_inuse))
self:SetAlpha (.75)
end
--self.Icon:SetTexture ("")
end
local selectHookToEdit = function (self)
if (not self.CanAddHook) then
local scriptObject = hookFrame.GetCurrentScriptObject()
if (scriptObject) then
--save the current code
local lastEditedHook = scriptObject.LastHookEdited
if (lastEditedHook ~= "") then
scriptObject.HooksTemp [lastEditedHook] = hookFrame.CodeEditorLuaEntry:GetText()
end
scriptObject.LastHookEdited = self.Hook
--load the code
hookFrame.CodeEditorLuaEntry:Show()
hookFrame.CodeEditorLuaEntry:SetText (scriptObject.HooksTemp [self.Hook])
--refresh the hook selection scroll
hookFrame.HookScrollBox:Refresh()
--refresh the hook selection dropdown
hookFrame.HookTypeDropdown:Select (self.Hook)
--hide other frames using the code editor space
hookFrame.ScriptOptionsPanelAdmin:Hide()
hookFrame.ScriptOptionsPanelUser:Hide()
end
return
end
end
local addHookToScriptObject = function (self)
if (hookFrame.LastAddedHookTime+0.5 >= GetTime()) then
return
end
local hookName = self.Hook
hookFrame.AddHookToScript (hookName)
hookFrame.LastAddedHookTime = GetTime()
end
local removeHookFromScriptObject = function (self)
self = self:GetParent()
if (not self.CanRemoveHook) then
return
end
local hookName = self.Hook
hookFrame.RemoveHookFromScript (hookName)
end
local refreshHookScrollBox = function (self, data, offset, totalLines)
local hookList = {}
local scriptObject = hookFrame.GetCurrentScriptObject()
if (scriptObject) then
for index, hookName in ipairs (Plater.HookScripts) do
if (scriptObject.Hooks [hookName]) then
tinsert (hookList, hookName)
end
end
for index, hookName in ipairs (Plater.HookScripts) do
if (not scriptObject.Hooks [hookName]) then
tinsert (hookList, hookName)
end
end
else
hookList = Plater.HookScripts
end
for i = 1, totalLines do
local index = i + offset
local hook = hookList [index]
if (hook) then
local line = self:GetLine (i)
line:UpdateLine (index, hook)
end
end
end
local hookListCreateLine = function (self, index)
--create a new line
local line = CreateFrame ("button", "$parentLine" .. index, self, BackdropTemplateMixin and "BackdropTemplate")
--set its parameters
line:SetPoint ("topleft", self, "topleft", 0, -((index-1) * (triggerbox_line_height+1)))
line:SetSize (triggerbox_size[1], triggerbox_line_height)
line:SetScript ("OnEnter", onEnterHookButton)
line:SetScript ("OnLeave", onLeaveHookButton)
line:SetScript ("OnMouseUp", selectHookToEdit)
line:SetBackdrop ({bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true, edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1})
line:SetBackdropColor (unpack (scrollbox_line_backdrop_color))
line:SetBackdropBorderColor (0, 0, 0, 0)
local icon = line:CreateTexture ("$parentIcon", "overlay")
icon:SetSize (triggerbox_line_height - 2, triggerbox_line_height - 2)
icon:SetTexture ([[Interface\ICONS\INV_Hand_1H_PirateHook_B_01]])
icon:SetTexCoord (.1, .9, .1, .9)
local hookNameLabel = DF:CreateLabel (line, "", DF:GetTemplate ("font", "PLATER_SCRIPTS_NAME"))
local addedLabel = DF:CreateLabel (line, "", DF:GetTemplate ("font", "PLATER_SCRIPTS_TRIGGER_SPELLID"))
local removeButton = CreateFrame ("button", "$parentRemoveButton", line, "UIPanelCloseButton")
removeButton:SetSize (16, 16)
removeButton:SetScript ("OnClick", removeHookFromScriptObject)
removeButton:SetPoint ("topright", line, "topright")
removeButton:GetNormalTexture():SetDesaturated (true)
local addButton = CreateFrame ("button", "$parentRemoveButton", line, BackdropTemplateMixin and "BackdropTemplate")
addButton:SetSize (16, 16)
addButton:SetScript ("OnClick", addHookToScriptObject)
addButton:SetPoint ("right", line, "right")
addButton:SetNormalTexture ([[Interface\BUTTONS\UI-PlusButton-Up]])
addButton:SetPushedTexture ([[Interface\BUTTONS\UI-PlusButton-Down]])
addButton:SetDisabledTexture ([[Interface\BUTTONS\UI-PlusButton-Disabled]])
addButton:SetHighlightTexture ([[Interface\BUTTONS\UI-PlusButton-Hilight]])
icon:SetPoint ("left", line, "left", 2, 0)
hookNameLabel:SetPoint ("topleft", icon, "topright", 4, -2)
addedLabel:SetPoint ("topleft", hookNameLabel, "bottomleft", 0, 0)
line.Icon = icon
line.HookName = hookNameLabel
line.AddedLabel = addedLabel
line.RemoveButton = removeButton
line.AddButton = addButton
line.UpdateLine = updateHookLine
line:Hide()
return line
end
--scroll showing all hooks of the mod
local hookLabel = DF:CreateLabel (edit_script_frame, "Add Hooks:", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
local hookScrollbox = DF:CreateScrollBox (edit_script_frame, "$parentHookScrollBox", refreshHookScrollBox, Plater.HookScripts, hookbox_size[1], hookbox_size[2], hook_scrollbox_lines, triggerbox_line_height)
hookScrollbox:SetPoint ("topleft", hookLabel.widget, "bottomleft", 0, -4)
hookScrollbox:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
hookScrollbox:SetBackdropColor (0, 0, 0, 0.2)
hookScrollbox:SetBackdropBorderColor (0, 0, 0, 1)
hookFrame.HookScrollBox = hookScrollbox
DF:ReskinSlider (hookScrollbox)
--create the hook scrollbox lines
for i = 1, hook_scrollbox_lines do
hookScrollbox:CreateLine (hookListCreateLine)
end
local onLoadConditionsChange = function()
--reload all hook scripts
Plater.WipeAndRecompileAllScripts ("hook")
--local scriptObject = hookFrame.GetCurrentScriptObject()
--print ("condition changed")
--Details:Dump (scriptObject.LoadConditions)
end
--create load conditions button
local openConditionsPanel = function()
local scriptObject = hookFrame.GetCurrentScriptObject()
if (scriptObject) then
DF:OpenLoadConditionsPanel (scriptObject.LoadConditions, onLoadConditionsChange, {title = "Hook Load Conditions", name = scriptObject.Name})
end
end
local loadConditionsButton = DF:CreateButton (edit_script_frame, openConditionsPanel, triggerbox_size[1], 20, "Load Conditions", -1, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
--add_trigger_button:SetIcon ([[Interface\BUTTONS\UI-PlusButton-Up]], 20, 20, "overlay", {0, 1, 0, 1})
loadConditionsButton:SetPoint ("top", hookScrollbox, "bottom", 0, -4)
hookFrame.LoadConditionsButton = loadConditionsButton
--create the code editor
create_import_box (edit_script_frame, hookFrame)
create_code_editor (edit_script_frame, hookFrame)
--create the components button and cooltip
--api help small frame
local componentsButton = DF:CreateButton (hookFrame.CodeEditorLuaEntry, function() end, 100, 20, "Components", -1, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
componentsButton:SetIcon ([[Interface\FriendsFrame\UI-FriendsList-Large-Up]], 16, 16, "overlay", {.2, .74, .27, .75}, nil, 4)
hookFrame.ComponentsButton = componentsButton
local getMoreModsFunc = function()
if (PlaterMoreModsPanel) then
PlaterMoreModsPanel:Show()
return
end
local f = DF:CreateSimplePanel (UIParent, 460, 90, "Plater Get More Mods", "PlaterMoreModsPanel")
f:SetFrameStrata ("TOOLTIP")
f:SetPoint ("center", UIParent, "center")
DF:CreateBorder (f)
local LinkBox = DF:CreateTextEntry (f, function()end, 380, 20, "ExportLinkBox", _, _, options_dropdown_template)
LinkBox:SetPoint ("center", f, "center", 0, -10)
f:SetScript ("OnShow", function()
LinkBox:SetText ("https://wago.io/plater/plater-mods")
C_Timer.After (.1, function()
LinkBox:SetFocus (true)
LinkBox:HighlightText()
end)
end)
f:Hide()
f:Show()
end
local moreModsButton = DF:CreateButton (hookFrame.CodeEditorLuaEntry, getMoreModsFunc, 120, 20, "Get More Mods", -1, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
moreModsButton:SetIcon ([[Interface\FriendsFrame\UI-FriendsList-Large-Up]], 16, 16, "overlay", {.2, .74, .27, .75}, nil, 4)
hookFrame.MoreModsButton = moreModsButton
hookFrame.MoreModsButton:SetPoint ("left", componentsButton, "right", 2, 0)
local onSelectComponentMember = function (a, d, member)
hookFrame.CodeEditorLuaEntry.editbox:Insert (member)
GameCooltip:Hide()
end
local buildComponentTableMenu = function()
GameCooltip:Preset (2)
GameCooltip:SetOption ("TextSize", 11)
GameCooltip:SetOption ("FixedWidth", 300)
GameCooltip:AddLine ("Nameplate Components", "", 1, "yellow", "yellow", 12, nil, "OUTLINE")
local backgroundAlpha = 0.2
for bracketName, listTable in pairs (Plater.NameplateComponents) do
GameCooltip:AddLine (bracketName)
GameCooltip:AddStatusBar (100, 1, 0, 0, 0, backgroundAlpha)
GameCooltip:AddIcon ("", 2, 1, 16, 16)
--GameCooltip:AddMenu (1, onSelectComponentMember, Plater.UnitFrameMembers [i])
for i, commandName in ipairs (listTable) do
GameCooltip:AddLine (commandName, "", 2)
GameCooltip:AddStatusBar (100, 2, 0, 0, 0, backgroundAlpha)
GameCooltip:AddIcon ("", 2, 1, 18, 18)
GameCooltip:AddMenu (2, onSelectComponentMember, commandName)
end
end
GameCooltip:AddLine ("$div")
GameCooltip:AddLine ("Help")
GameCooltip:AddLine ("|cFFFFFF22unitFrame|r is where things are connected.\n\n|cFFFFFF22Members|r just store information, they are read-only.\n|cFFFFFF22Frames|r are widgets that can be textures, fontstrings, etc.\n\nTo access a widget from the unitFrame:\n|cFFFFFF22castBar|r: unitFrame.castBar\n|cFFFFFF22healthBar|r: unitFrame.healthBar\n\nExamples:\n|cFFFFFF22- |rTo know if a cast can be interrupted use 'unitFrame.castBar.CanInterrupt'\n|cFFFFFF22- |rTo get the fontString for the health amount use 'unitFrame.healthBar.lifePercent'.", "", 2)
end
componentsButton.CoolTip = {
Type = "menu",
BuildFunc = buildComponentTableMenu,
ShowSpeed = 0.05,
}
GameCooltip2:CoolTipInject (componentsButton)
--create the hook selector dropdown
local onSelectHook = function (self, fixedParameter, valueSelected)
--get the current editing script
local scriptObject = hookFrame.GetCurrentScriptObject()
--save the current code
local lastEditedHook = scriptObject.LastHookEdited
if (lastEditedHook ~= "") then
scriptObject.HooksTemp [lastEditedHook] = hookFrame.CodeEditorLuaEntry:GetText()
end
scriptObject.LastHookEdited = valueSelected
--load the code
hookFrame.CodeEditorLuaEntry:SetText (scriptObject.HooksTemp [valueSelected])
--refresh the list of hooks for this script
hookScrollbox:Refresh()
end
local buildHookDropdownList = function()
local t = {}
local scriptObject = hookFrame.GetCurrentScriptObject()
if (scriptObject) then
for hookName, _ in pairs (scriptObject.Hooks) do
tinsert (t, {label = hookName, value = hookName, desc = hookName, onclick = onSelectHook})
end
end
return t
end
--create the options script box for hooks
Plater.CreateScriptingOptionsPanel(edit_script_frame, hookFrame)
local hookTypeLabel = DF:CreateLabel (hookFrame.CodeEditorLuaEntry, "Edit Hook:", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
local hookTypeDropdown = DF:CreateDropDown (hookFrame.CodeEditorLuaEntry, buildHookDropdownList, 1, 160, 20, "HookTypeDropdown", _, options_dropdown_template)
hookTypeDropdown:SetPoint ("left", hookTypeLabel, "right", 2, 0)
hookTypeDropdown.CodeType = 1
hookFrame.HookTypeDropdown = hookTypeDropdown
--when the profile has changed
function hookFrame:RefreshOptions()
--update the script data for the scroll and refresh
hookFrame.ScriptSelectionScrollBox:SetData (Plater.db.profile.hook_data)
hookFrame.ScriptSelectionScrollBox:Refresh()
end
hookFrame.ScriptSelectionScrollBox:SetPoint ("topleft", hookFrame.ScriptSearchTextEntry.widget, "bottomleft", 0, -20)
hookFrame.ScriptScrollLabel:SetPoint ("bottomleft", hookFrame.ScriptSelectionScrollBox, "topleft", 0, 2)
hookFrame.ScriptEnabledLabel:SetPoint ("bottomright", hookFrame.ScriptSelectionScrollBox, "topright", 0, 2)
--create frame holding the script options
edit_script_frame:SetPoint ("topleft", hookFrame, "topleft", scrollbox_size[1] + 30, start_y)
--script options
edit_script_frame.ScriptNameLabel:SetPoint ("topleft", edit_script_frame, "topleft", 10, 2)
edit_script_frame.ScriptIconLabel:SetPoint ("topleft", edit_script_frame, "topleft", 170, 0)
edit_script_frame.ScriptDescLabel:SetPoint ("topleft", edit_script_frame, "topleft", 10, -40)
edit_script_frame.ScriptPrioLabel:SetPoint ("topleft", edit_script_frame, "topleft", 10, -80)
hookLabel:SetPoint ("topleft", edit_script_frame, "topleft", 10, hookbox_label_y)
--lua code editor
hookFrame.CodeEditorLuaEntry:SetPoint ("topleft", edit_script_frame, "topleft", 230, -20)
--import editor
hookFrame.ImportTextEditor:SetPoint ("topleft", edit_script_frame, "topleft", 230, -20)
hookFrame.SaveScriptButton:SetPoint ("topright", hookFrame.CodeEditorLuaEntry, "bottomright", 0, -25)
hookFrame.CancelScriptButton:SetPoint ("right", hookFrame.SaveScriptButton, "left", -20, 0)
hookFrame.DocsButton:SetPoint ("right", hookFrame.CancelScriptButton, "left", -20, 0)
hookTypeLabel:SetPoint ("topleft", hookFrame.CodeEditorLuaEntry, "bottomleft", 0, -30)
--import control buttons
hookFrame.ImportTextEditor.OkayButton:SetPoint ("topright", hookFrame.CodeEditorLuaEntry, "bottomright", 0, -10)
hookFrame.ImportTextEditor.CancelButton:SetPoint ("right", hookFrame.ImportTextEditor.OkayButton, "left", -20, 0)
componentsButton:SetPoint ("bottomleft", hookFrame.CodeEditorLuaEntry, "topleft", 0, 2)
hookFrame.EditScriptFrame:LockFrame()
hookFrame.EditScriptFrame:Show()
--code options panel
hookFrame.ScriptOptionsPanelAdmin:SetPoint("topleft", edit_script_frame, "topleft", 230, -20)
hookFrame.ScriptOptionsPanelUser:SetPoint("topleft", edit_script_frame, "topleft", 230, -20)
end
function Plater.CreateScriptingPanel()
--controi o menu principal
local f = PlaterOptionsPanelFrame
local mainFrame = PlaterOptionsPanelContainer
local profile = Plater.db.profile
local scriptingFrame = mainFrame.AllFrames [PLATER_OPTIONS_SCRIPTING_TAB]
scriptingFrame.ScriptType = "script"
local currentEditingScript = nil
--localized names of the different trigger types and description
scriptingFrame.TriggerTypes = {
"Buffs & Debuffs",
"Spell Casting",
"Unit Name",
}
scriptingFrame.TriggerTypesDesc = {
"When an unit receives an aura (buff or debuff), the aura name is checked against all the spell names added in the trigger box below.",
"When an unit starts to cast a spell, the name of the spell is checked against all the spell names added in the trigger box below.",
"When a nameplate is shown, the name of the unit is checked against all the spell names added in the trigger box below.",
}
scriptingFrame.CodeTypes = {
{Name = "Constructor", Desc = "Is executed only once, create your custom stuff here like frames, textures, animations and store them inside |cFFFFFF00envTable|r.\n\nAlso check if the frame already exists before creating it!", Value = 2},
{Name = "On Show", Desc = "Executed when the trigger match!\n\nUse to show your custom frames, textures, play animations, etc.", Value = 4},
{Name = "On Update", Desc = "Executed after Plater updates the nameplate (does not run every frame).\n\nUse this to update your custom stuff or override values that Plater might have set during the nameplate update, e.g. the nameplate color due to aggro checks.", Value = 1},
{Name = "On Hide", Desc = "Executed when the widget is Hide() or trigger doesn't match anymore.\n\nUse to hide your custom frames, textures, stop animations, etc.", Value = 3},
{Name = "Initialization", Desc = "Executed once for the script when it is compiled. Used to initialize the global script environment 'scriptTable'.", Value = 5},
}
--store all spells from the game in a hash table and also on the index table
--these are loaded on demand and cleared when the scripting frame is hided
scriptingFrame.SpellHashTable = {}
scriptingFrame.SpellIndexTable = {}
scriptingFrame.SearchString = ""
scriptingFrame:SetScript ("OnShow", function()
--update the created scripts scrollbox
scriptingFrame.ScriptSelectionScrollBox:Refresh()
--update options
if scriptingFrame.ScriptOptionsPanelUser:IsShown() then
Plater.RefreshUserScriptOptions(scriptingFrame)
end
if scriptingFrame.ScriptOptionsPanelAdmin:IsShown() then
Plater.RefreshAdminScriptOptions(scriptingFrame)
end
--check trash can timeout
local timeout = 60 * 60 * 24 * 30
--local timeout = 60 * 60 * 24 * 1 --for testing, setting this to 1 day
for i = #Plater.db.profile.script_data_trash, 1, -1 do
local scriptObject = Plater.db.profile.script_data_trash [i]
if (not scriptObject.__TrashAt or scriptObject.__TrashAt + timeout < time()) then
tremove (Plater.db.profile.script_data_trash, i)
end
end
end)
scriptingFrame:SetScript ("OnHide", function()
--save
local scriptObject = scriptingFrame.GetCurrentScriptObject()
if (scriptObject) then
scriptingFrame.SaveScript()
end
--clean the spell hash table
wipe (scriptingFrame.SpellHashTable)
wipe (scriptingFrame.SpellIndexTable)
collectgarbage()
end)
-- scriptingFrame.ScriptNameTextEntry --name of the script (text entry)
-- scriptingFrame.ScriptIconButton -- icon pick button
-- scriptingFrame.ScriptTypeDropdown --type of the script (dropdown)
-- scriptingFrame.TriggerTextEntry --text entry for the trigger add (text entry)
-- scriptingFrame.TriggerScrollBox --scrollbox for the triggers (scrollbox)
-- scriptingFrame.CodeEditorLuaEntry --text entry for the lua editor
-- scriptingFrame.ScriptSelectionScrollBox --scrollbox with all script created to select
-- scriptingFrame.CodeTypeDropdown --dropdown for the type of code being edited (runtime or constructor)
scriptingFrame.DefaultScript = [=[
function (self, unitId, unitFrame, envTable, scriptTable)
--insert code here
end
]=]
scriptingFrame.DefaultScriptNoNameplate = [=[
function (scriptTable)
--insert code here
end
]=]
--a new script has been created
function scriptingFrame.CreateNewScript()
--build the table of the new script
local newScriptObject = { --~prototype ~new ~create ñew
Enabled = true,
ScriptType = 0x1,
Name = "New Script",
SpellIds = {},
NpcNames = {},
Icon = "",
Desc = "",
Author = "",
Time = time(), --is set when the save button is pressed
Revision = 1, --increase everytime the save button is pressed
PlaterCore = Plater.CoreVersion, --store the version of plater required to run this script
Options = {}, --store options where the end user can change aspects of the script without messing with the code
UID = createUniqueIdentifier(), --create an ID that identifies this script, the ID cannot be changed, if the script is duplicated, a new id is generated
}
Plater.CreateOptionTableForScriptObject(newScriptObject)
--scripts
for i = 1, #Plater.CodeTypeNames do
local memberName = Plater.CodeTypeNames [i]
if i == 5 then
-- init function
newScriptObject [memberName] = scriptingFrame.DefaultScriptNoNameplate
newScriptObject ["Temp_" .. memberName] = scriptingFrame.DefaultScriptNoNameplate
else
-- default function
newScriptObject [memberName] = scriptingFrame.DefaultScript
newScriptObject ["Temp_" .. memberName] = scriptingFrame.DefaultScript
end
end
local playerName = UnitName ("player")
local realm = GetRealmName()
newScriptObject.Author = playerName .. "-" .. realm
--add it to the database
tinsert (Plater.db.profile.script_data, newScriptObject)
--start editing the new script
scriptingFrame.EditScript (#Plater.db.profile.script_data)
--refresh the scrollbox showing all scripts created
scriptingFrame.ScriptSelectionScrollBox:Refresh()
end
function scriptingFrame.GetScriptObject (script_id)
local script = Plater.db.profile.script_data [script_id]
if (script) then
return script
else
Plater:Msg ("GetScriptObject could find the script id")
return
end
end
function scriptingFrame.GetCurrentScriptObject()
--create the options table for old scripts
if (currentEditingScript) then
if (not currentEditingScript.Options) then
Plater.CreateOptionTableForScriptObject(currentEditingScript)
end
end
return currentEditingScript
end
function scriptingFrame.LoadGameSpells()
if (not next (scriptingFrame.SpellHashTable)) then
--load all spells in the game
DF:LoadAllSpells (scriptingFrame.SpellHashTable, scriptingFrame.SpellIndexTable)
return true
end
end
--restore the values on the text fields and scroll boxes to the values on the object
function scriptingFrame.CancelEditing (is_deleting)
if (not is_deleting) then
--re fill all the text entried and dropdowns to the default from the script
--doing this to restore the script so it can do a hot reload
scriptingFrame.UpdateEditingPanel()
--hot reload restored scripts
scriptingFrame.ApplyScript()
end
--clear current editing script
currentEditingScript = nil
--lock the editing panel
scriptingFrame.EditScriptFrame:LockFrame()
--hide the editing frame
--scriptingFrame.HideEditPanel()
--reload the script selection scrollbox in case the script got renamed
scriptingFrame.ScriptSelectionScrollBox:Refresh()
end
--save all values
function scriptingFrame.SaveScript()
--get the current editing object
local scriptObject = scriptingFrame.GetCurrentScriptObject()
--script name
scriptObject.Name = scriptingFrame.ScriptNameTextEntry.text
--script icon
scriptObject.Icon = scriptingFrame.ScriptIconButtonTexture or scriptingFrame.ScriptIconButton:GetIconTexture()
--script description
scriptObject.Desc = scriptingFrame.ScriptDescTextEntry.text
--script prio
scriptObject.Prio = round(scriptingFrame.ScriptPrioSlideEntry.value)
--script type
scriptObject.ScriptType = scriptingFrame.ScriptTypeDropdown.value
--triggers are auto save
--transfer the temporarily code saved to the scrip object
for i = 1, #Plater.CodeTypeNames do
local memberName = Plater.CodeTypeNames [i]
scriptObject [memberName] = scriptObject ["Temp_" .. memberName]
end
--save the current code
scriptObject [Plater.CodeTypeNames [scriptingFrame.currentScriptType]] = scriptingFrame.CodeEditorLuaEntry:GetText()
scriptObject.Time = time()
scriptObject.Revision = scriptObject.Revision + 1
--do a hot reload on the script
scriptingFrame.ApplyScript(true)
--reload the script selection scrollbox in case the script got renamed
scriptingFrame.ScriptSelectionScrollBox:Refresh()
--remove the focus from the editing code textentry
scriptingFrame.CodeEditorLuaEntry:ClearFocus()
--update the overlapp button
scriptingFrame.UpdateOverlapButton()
--remove focus of everything
scriptingFrame.ScriptNameTextEntry:ClearFocus()
scriptingFrame.ScriptDescTextEntry:ClearFocus()
scriptingFrame.ScriptPrioSlideEntry:ClearFocus()
scriptingFrame.TriggerTextEntry:ClearFocus()
end
--hot reload the script by compiling it and applying it to the nameplates without saving
function scriptingFrame.ApplyScript(onSave)
--get the text from the text fields, compile and apply the changes to the nameplate without saving the script
--doing this since the framework send 'self' in the first parameter of the button click
onSave = type(onSave) == "boolean" and onSave
local code = {}
--prebuild the code table with the code types (constructor/onupdate etc)
for i = 1, #Plater.CodeTypeNames do
local memberName = Plater.CodeTypeNames[i]
code[memberName] = ""
end
local scriptObject = scriptingFrame.GetCurrentScriptObject()
if (not onSave) then
--is hot reload, get the code from the code editor
for i = 1, #Plater.CodeTypeNames do
local memberName = Plater.CodeTypeNames [i]
code [memberName] = scriptObject ["Temp_" .. memberName]
end
code [Plater.CodeTypeNames [scriptingFrame.currentScriptType]] = scriptingFrame.CodeEditorLuaEntry:GetText()
else
--it's a save, get the code from the object
for i = 1, #Plater.CodeTypeNames do
local memberName = Plater.CodeTypeNames [i]
code [memberName] = scriptObject [memberName]
end
end
do
--build a script table for the compiler
local allCodes = {}
for i = 1, #Plater.CodeTypeNames do
local memberName = Plater.CodeTypeNames [i]
tinsert (allCodes, code[memberName])
end
if (onSave) then
Plater.WipeAndRecompileAllScripts("script")
else
Plater.CompileScript(scriptObject, false, unpack(allCodes))
end
end
--remove the focus so the user can cast spells etc
scriptingFrame.CodeEditorLuaEntry:ClearFocus()
end
--when deleting or disabling a script object, it needs to stop any running script
function scriptingFrame.KillRunningScriptsForObject (scriptObject)
--kill scripts running for this script object
for _, plateFrame in ipairs (Plater.GetAllShownPlates()) do
local unitFrame = plateFrame.unitFrame
if (scriptObject.ScriptType == 1) then
--buff and debuffs
--iterate among all icons shown in the nameplate and attempt to kill the script by its trigger
for _, iconAuraFrame in ipairs (unitFrame.BuffFrame.PlaterBuffList) do
for _, spellID in ipairs (scriptObject.SpellIds) do
iconAuraFrame:KillScript (spellID)
end
end
for _, iconAuraFrame in ipairs (unitFrame.BuffFrame2.PlaterBuffList) do
for _, spellID in ipairs (scriptObject.SpellIds) do
iconAuraFrame:KillScript (spellID)
end
end
elseif (scriptObject.ScriptType == 2) then
--cast bar
for _, spellID in ipairs (scriptObject.SpellIds) do
unitFrame.castBar:KillScript (spellID)
end
elseif (scriptObject.ScriptType == 3) then
--nameplate
for _, triggerID in ipairs (scriptObject.NpcNames) do
unitFrame:KillScript (triggerID)
end
end
end
end
function scriptingFrame.RemoveScript (scriptId)
local scriptObjectToBeRemoved = scriptingFrame.GetScriptObject (scriptId)
local currentScript = scriptingFrame.GetCurrentScriptObject()
--check if the script to be removed is valid
if (not scriptObjectToBeRemoved) then
return
end
scriptingFrame.KillRunningScriptsForObject (scriptObjectToBeRemoved)
--if is the current script being edited, cancel the edit
if (currentScript == scriptObjectToBeRemoved) then
--cancel the editing process
scriptingFrame.CancelEditing (true)
end
--set the time when the script has been moved to trash
scriptObjectToBeRemoved.__TrashAt = time()
tinsert (Plater.db.profile.script_data_trash, scriptObjectToBeRemoved)
tremove (Plater.db.profile.script_data, scriptId)
--refresh the script selection scrollbox
scriptingFrame.ScriptSelectionScrollBox:Refresh()
GameCooltip:Hide()
Plater:Msg ("Script moved to trash.")
--reload all scripts
Plater.WipeAndRecompileAllScripts (scriptingFrame.ScriptType)
--update overlap button
scriptingFrame.UpdateOverlapButton()
end
function scriptingFrame.DuplicateScript (scriptId)
local scriptToBeCopied = scriptingFrame.GetScriptObject (scriptId)
local newScript = DF.table.copy ({}, scriptToBeCopied)
--generate a new unique id
newScript.UID = createUniqueIdentifier()
--cleanup:
newScript.url = nil
newScript.semver = nil
newScript.version = nil
newScript.scriptId = nil
tinsert (Plater.db.profile.script_data, newScript)
scriptingFrame.ScriptSelectionScrollBox:Refresh()
Plater:Msg ("Script duplicated. Make sure to use different triggers.")
--update overlap button
scriptingFrame.UpdateOverlapButton()
end
function scriptingFrame.ExportScriptAsLuaTable(scriptId)
local scriptObject = scriptingFrame.GetScriptObject(scriptId)
local stringToExport = DF.table.dump(scriptObject)
stringToExport = "local scriptObject = {\n" .. stringToExport .. "\n}"
scriptingFrame.ImportTextEditor.IsImporting = false
scriptingFrame.ImportTextEditor.IsExporting = true
scriptingFrame.ImportTextEditor:Show()
scriptingFrame.CodeEditorLuaEntry:Hide()
scriptingFrame.ScriptOptionsPanelAdmin:Hide()
scriptingFrame.ScriptOptionsPanelUser:Hide()
scriptingFrame.ImportTextEditor:SetText(stringToExport)
scriptingFrame.ImportTextEditor.TextInfo.text = "Exporting '" .. scriptObject.Name .. "' as Table"
--if there's anything being edited, start editing the script which is being exported
if (not scriptingFrame.GetCurrentScriptObject()) then
scriptingFrame.EditScript(scriptId)
end
scriptingFrame.EditScriptFrame:Show()
C_Timer.After (0.3, function()
scriptingFrame.ImportTextEditor.editbox:SetFocus(true)
scriptingFrame.ImportTextEditor.editbox:HighlightText()
end)
end
function scriptingFrame.ExportScriptTriggers(scriptId)
local scriptObject = scriptingFrame.GetScriptObject(scriptId)
local listOfTriggers = {}
for i = 1, #scriptObject.SpellIds do
listOfTriggers[#listOfTriggers+1] = scriptObject.SpellIds[i]
end
for i = 1, #scriptObject.NpcNames do
listOfTriggers[#listOfTriggers+1] = scriptObject.NpcNames[i]
end
local resultString = table.concat(listOfTriggers, ", ")
resultString = resultString .. ", "
scriptingFrame.ImportTextEditor.IsImporting = false
scriptingFrame.ImportTextEditor.IsExporting = true
scriptingFrame.ImportTextEditor:Show()
scriptingFrame.CodeEditorLuaEntry:Hide()
scriptingFrame.ScriptOptionsPanelAdmin:Hide()
scriptingFrame.ScriptOptionsPanelUser:Hide()
scriptingFrame.ImportTextEditor:SetText(resultString)
scriptingFrame.ImportTextEditor.TextInfo.text = "Exporting '" .. scriptObject.Name .. "'"
--if there's anything being edited, start editing the script which is being exported
if (not scriptingFrame.GetCurrentScriptObject()) then
scriptingFrame.EditScript(scriptId)
end
scriptingFrame.EditScriptFrame:Show()
C_Timer.After (0.3, function()
scriptingFrame.ImportTextEditor.editbox:SetFocus(true)
scriptingFrame.ImportTextEditor.editbox:HighlightText()
end)
end
--called from the context menu when right click an option in the script menu
function scriptingFrame.ExportScript (scriptId)
local scriptToBeExported = scriptingFrame.GetScriptObject (scriptId)
--convert the script table into an index table for smaller size
local tableToExport = Plater.PrepareTableToExport (scriptToBeExported)
--compress the index table
local encodedString = Plater.CompressData (tableToExport, "print")
scriptingFrame.ImportTextEditor.IsImporting = false
scriptingFrame.ImportTextEditor.IsExporting = true
scriptingFrame.ImportTextEditor:Show()
scriptingFrame.CodeEditorLuaEntry:Hide()
scriptingFrame.ScriptOptionsPanelAdmin:Hide()
scriptingFrame.ScriptOptionsPanelUser:Hide()
scriptingFrame.ImportTextEditor:SetText (encodedString)
scriptingFrame.ImportTextEditor.TextInfo.text = "Exporting '" .. scriptToBeExported.Name .. "'"
--if there's anything being edited, start editing the script which is being exported
if (not scriptingFrame.GetCurrentScriptObject()) then
scriptingFrame.EditScript (scriptId)
end
scriptingFrame.EditScriptFrame:Show()
C_Timer.After (0.3, function()
scriptingFrame.ImportTextEditor.editbox:SetFocus (true)
scriptingFrame.ImportTextEditor.editbox:HighlightText()
end)
end
function scriptingFrame.ShowImportTextField()
--if editing a script, save it and close it
local scriptObject = scriptingFrame.GetCurrentScriptObject()
if (scriptObject) then
scriptingFrame.SaveScript()
scriptingFrame.CancelEditing()
--refresh the script selection scrollbox
scriptingFrame.ScriptSelectionScrollBox:Refresh()
end
--lock the editing panel
scriptingFrame.EditScriptFrame:LockFrame()
scriptingFrame.EditScriptFrame:Show()
scriptingFrame.ImportTextEditor:Show()
scriptingFrame.ImportTextEditor:SetText ("")
scriptingFrame.ImportTextEditor.IsImporting = true
scriptingFrame.ImportTextEditor.IsExporting = false
scriptingFrame.ImportTextEditor:SetFocus (true)
scriptingFrame.ImportTextEditor.TextInfo.text = "Paste the string:"
end
--this is only called from the 'okay' button in the import text editor
function scriptingFrame.ImportScript()
--if clicked in the 'okay' button when the import text editor is showing a string to export, just hide the import editor
if (scriptingFrame.ImportTextEditor.IsExporting) then
scriptingFrame.ImportTextEditor.IsImporting = nil
scriptingFrame.ImportTextEditor.IsExporting = nil
scriptingFrame.ImportTextEditor:Hide()
return
end
local text = scriptingFrame.ImportTextEditor:GetText()
import_mod_or_script (text)
scriptingFrame.ImportTextEditor.IsImporting = nil
scriptingFrame.ImportTextEditor:Hide()
end
function scriptingFrame:OpenDocs()
if (PlaterDocsPanel) then
PlaterDocsPanel:Show()
return
end
local f = DF:CreateSimplePanel (UIParent, 460, 90, "Plater Script Documentation", "PlaterDocsPanel")
f:SetFrameStrata ("TOOLTIP")
f:SetPoint ("center", UIParent, "center")
DF:CreateBorder (f)
local LinkBox = DF:CreateTextEntry (f, function()end, 380, 20, "ExportLinkBox", _, _, options_dropdown_template)
LinkBox:SetPoint ("center", f, "center", 0, -10)
f:SetScript ("OnShow", function()
LinkBox:SetText ("https://www.curseforge.com/wow/addons/plater-nameplates/pages/scripts")
C_Timer.After (.1, function()
LinkBox:SetFocus (true)
LinkBox:HighlightText()
end)
end)
f:Hide()
f:Show()
end
--set all values from the current editing script object to all text entried and scroll fields
function scriptingFrame.UpdateEditingPanel()
--get the current editing object
local scriptObject = scriptingFrame.GetCurrentScriptObject()
--set the data from the object in the widgets
scriptingFrame.ScriptNameTextEntry.text = scriptObject.Name
scriptingFrame.ScriptNameTextEntry:ClearFocus()
scriptingFrame.ScriptIconButton:SetIcon (scriptObject.Icon)
scriptingFrame.ScriptIconButtonTexture = scriptObject.Icon
scriptingFrame.ScriptDescTextEntry.text = scriptObject.Desc or ""
scriptingFrame.ScriptDescTextEntry:ClearFocus()
scriptingFrame.ScriptPrioSlideEntry.value = round(scriptObject.Prio or 99)
scriptingFrame.ScriptPrioSlideEntry:ClearFocus()
scriptingFrame.ScriptTypeDropdown:Select (scriptObject.ScriptType, true)
scriptingFrame.TriggerTextEntry.text = ""
scriptingFrame.TriggerTextEntry:ClearFocus()
--trigger box data
if (scriptObject.ScriptType == 1 or scriptObject.ScriptType == 2) then
scriptingFrame.TriggerScrollBox:SetData (scriptObject.SpellIds)
elseif (scriptObject.ScriptType == 3) then
scriptingFrame.TriggerScrollBox:SetData (scriptObject.NpcNames)
end
scriptingFrame.TriggerScrollBox:Refresh()
--refresh the code editing
for i = 1, #Plater.CodeTypeNames do
local memberName = Plater.CodeTypeNames [i]
scriptObject ["Temp_" .. memberName] = scriptObject [memberName]
end
--use the runtime code as the default editing script
scriptingFrame.CodeEditorLuaEntry:SetText (scriptObject [Plater.CodeTypeNames [2]])
scriptingFrame.CodeEditorLuaEntry:ClearFocus()
--update the code type dropdown
scriptingFrame.CodeTypeDropdown:Select (2)
scriptingFrame.SetCurrentEditingScript(2)
end
--start editing a script
function scriptingFrame.EditScript (script_id)
local scriptObject
--> check if passed a script object
if (type (script_id) == "table") then
scriptObject = script_id
else
scriptObject = scriptingFrame.GetScriptObject (script_id)
end
if (not scriptObject) then
return
end
scriptingFrame.EditScriptFrame:UnlockFrame()
scriptingFrame.EditScriptFrame:Show()
--set the new editing script
currentEditingScript = scriptObject
--load the values in the frame
scriptingFrame.UpdateEditingPanel()
--hide other frames using the code editor space
scriptingFrame.ScriptOptionsPanelAdmin:Hide()
scriptingFrame.ScriptOptionsPanelUser:Hide()
end
--add a trigger to the current editing script
function scriptingFrame.AddTrigger()
--get the text on the addon trigger text entry
local text = scriptingFrame.TriggerTextEntry.text
scriptingFrame.TriggerTextEntry:ClearFocus()
--check the text if is valid
text = DF:trim (text)
if (text == "" or string.len (text) < 2) then
Plater:Msg ("Invalid trigger")
return
end
local scriptObject = scriptingFrame.GetCurrentScriptObject()
if (scriptObject.ScriptType == 1 or scriptObject.ScriptType == 2) then --require a spellId
--cast the string to number
local spellId = tonumber (text)
if (not spellId or not GetSpellInfo (spellId)) then
--load spell hash table
scriptingFrame.LoadGameSpells()
--attempt to get the spellId from the hash table
spellId = scriptingFrame.SpellHashTable [string.lower (text)]
--if still fail, stop here
if (not spellId) then
Plater:Msg ("Trigger requires a valid spell name or an ID of a spell")
return
end
end
--add the spell id
tinsert (scriptObject.SpellIds, spellId)
--refresh the trigger box
scriptingFrame.TriggerScrollBox:Refresh()
--check if the script has an icon, if not set the icon
if (not scriptObject.Icon or scriptObject.Icon == "") then
local _, _, spellIcon = GetSpellInfo (spellId)
scriptingFrame.ScriptIconButton:SetIcon (spellIcon)
scriptingFrame.ScriptIconButtonTexture = spellIcon
end
elseif (scriptObject.ScriptType == 3) then
--add the npc name
tinsert (scriptObject.NpcNames, text)
--refresh the trigger box
scriptingFrame.TriggerScrollBox:Refresh()
end
--update overlap button
scriptingFrame.UpdateOverlapButton()
--recompile all
Plater.WipeAndRecompileAllScripts (scriptingFrame.ScriptType)
--clear the trigger box
scriptingFrame.TriggerTextEntry:SetText ("")
scriptingFrame.TriggerTextEntry:ClearFocus()
Plater:Msg ("Trigger added!")
end
--store the script object which is currently being edited
function scriptingFrame.GetScriptTriggerTypeName (script_type)
return scriptingFrame.TriggerTypes [script_type] or "none", scriptingFrame.TriggerTypesDesc [script_type] or ""
end
do
local help_popup = DF:CreateSimplePanel (UIParent, 1000, 480, "Plater Scripting Help", "PlaterScriptingHelp")
help_popup:SetFrameStrata ("DIALOG")
help_popup:SetPoint ("center")
DF:ApplyStandardBackdrop (help_popup, false, 1.2)
help_popup:Hide()
scriptingFrame.HelpFrame = help_popup
local scripting_help_label = DF:CreateLabel (help_popup, "Script Name:", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
local frontpageText_Welcome = "Scripting allows you to apply a more depth customization into the nameplate.\n"
local frontpageText_Lua = "A basic knowledge of Lua programming may be required.\n\n"
local frontpageText_Triggers = "|cFFFFFF00How a Script Works:|r\n\nThere's three types of triggers: |cFFFF5500Auras|r, |cFFFF5500Spell Cast|r and |cFFFF5500Unit Name|r, when a condition for the trigger matches, it begins to run its code.\n\n"
local frontpageText_Scripts = "There's four types of code:\n|cFFFF5500Constructor|r: runs only once, use to create your custom frames, texture and animations.\n|cFFFF5500On Show|r: is executed each time the script triggers. Use this to show or play frames and animations created inside the constructor.\n|cFFFF5500On Update|r runs every time Plater updates the nameplate. Use this to override something that Plater have set, the nameplate color for example, or, update some information from your custom stuff.\n|cFFFF5500On Hide|r: executed when the trigger doesn't match the condition any more. Use this to hide and stop all your frames and animations.\n"
local frontpageText_Function = "\n|cFFFFFF00Function Parameters:|r\n\n|cFFC0C0C0function (self, unit, unitFrame, envTable)\n --code\nend|r\n\n|cFFFF5500self|r: is different for each trigger, for buffs is the frame of the icon, spell casting passes the frame of the cast bar and the unit frame is passed for unit names.\n|cFFFF5500unit|r: unitId of the unit shown in the nameplate, use to query data, for example: UnitName (unitId).\n|cFFFF5500unitFrame|r: is the nameplate unit frame (parent of all widgets), the tooltip of the ? button has all the members to access all components of the nameplate from the unit frame.\n|cFFFF5500envTable|r: a table where you can store data, it also store information about the aura, cast and the unit shown depending on the type of the trigger.\n"
local frontpageText_ReturnValues = "\nWhat is a |cFFFF5500ReturnValue|r?\nIs what a function returns after a calling it, example:\nenvTable.MyFlash = Plater.CreateFlash (unitFrame.healthBar, 0.05, 2, 'white')\nPlater.CreateFlash() returned an object with information about the flash created, then this information is stored inside '|cFFFF5500envTable.MyFlash|r'\nYou can use it later to play the flash with '|cFFFF5500envTable.MyFlash:Play()|r' or stop it with '|cFFFF5500envTable.MyFlash:Stop()|r'."
local frontpageText_Parent = "\n\nWhat is a |cFFFF5500Parent|r?\nThe parent field required for create some widgets is the frame which will hold it, in other words: where it will be attach to."
scripting_help_label.text = frontpageText_Welcome .. frontpageText_Lua .. frontpageText_Triggers .. frontpageText_Scripts .. frontpageText_Function .. frontpageText_ReturnValues .. frontpageText_Parent
scripting_help_label.fontsize = 14
scripting_help_label:SetPoint ("topleft", help_popup, "topleft", 5, -25)
end
--create the frame which will hold the create panel
local edit_script_frame = CreateFrame ("frame", "$parentCreateScript", scriptingFrame, BackdropTemplateMixin and "BackdropTemplate")
edit_script_frame:SetSize (unpack (main_frames_size))
edit_script_frame:SetScript ("OnShow", function()
end)
edit_script_frame:SetScript ("OnHide", function()
end)
edit_script_frame:Hide()
scriptingFrame.EditScriptFrame = edit_script_frame
function edit_script_frame.UnlockFrame()
scriptingFrame.ScriptNameTextEntry:Enable()
scriptingFrame.ScriptIconButton:Enable()
scriptingFrame.ScriptDescTextEntry:Enable()
scriptingFrame.ScriptPrioSlideEntry:Enable()
scriptingFrame.ScriptTypeDropdown:Enable()
scriptingFrame.TriggerTextEntry:Enable()
scriptingFrame.AddTriggerButton:Enable()
scriptingFrame.AddAPIDropdown:Enable()
scriptingFrame.AddFWDropdown:Enable()
scriptingFrame.CodeEditorLuaEntry:Enable()
--scriptingFrame.CodeTypeDropdown:Enable()
scriptingFrame.ApplyScriptButton:Enable()
scriptingFrame.SaveScriptButton:Enable()
scriptingFrame.CancelScriptButton:Enable()
scriptingFrame.ScriptOptionButton:Enable()
scriptingFrame.ScriptOptionButtonAdmin:Enable()
for i = 1, #scriptingFrame.scriptButtons do
scriptingFrame.scriptButtons[i]:Enable()
end
end
function edit_script_frame.LockFrame()
scriptingFrame.ScriptNameTextEntry:SetText ("")
scriptingFrame.ScriptNameTextEntry:Disable()
scriptingFrame.ScriptIconButton:SetIcon ("")
scriptingFrame.ScriptIconButton:Disable()
scriptingFrame.ScriptDescTextEntry:SetText ("")
scriptingFrame.ScriptDescTextEntry:Disable()
scriptingFrame.ScriptPrioSlideEntry:SetValue (99)
scriptingFrame.ScriptPrioSlideEntry:Disable()
scriptingFrame.ScriptTypeDropdown:Disable()
scriptingFrame.TriggerTextEntry:SetText ("")
scriptingFrame.TriggerTextEntry:Disable()
scriptingFrame.AddTriggerButton:Disable()
scriptingFrame.TriggerScrollBox:SetData ({})
scriptingFrame.TriggerScrollBox:Refresh()
scriptingFrame.AddAPIDropdown:Disable()
scriptingFrame.AddFWDropdown:Disable()
scriptingFrame.CodeEditorLuaEntry:SetText ("")
scriptingFrame.CodeEditorLuaEntry:Disable()
--scriptingFrame.CodeTypeDropdown:Disable()
scriptingFrame.ApplyScriptButton:Disable()
scriptingFrame.SaveScriptButton:Disable()
scriptingFrame.CancelScriptButton:Disable()
scriptingFrame.ScriptOptionButton:Disable()
scriptingFrame.ScriptOptionButtonAdmin:Disable()
scriptingFrame.ScriptOptionsPanelAdmin:Hide()
scriptingFrame.ScriptOptionsPanelUser:Hide()
for i = 1, #scriptingFrame.scriptButtons do
scriptingFrame.scriptButtons[i]:Disable()
end
end
function scriptingFrame.HideEditPanel()
edit_script_frame:Hide()
end
--create new script frame widgets
create_script_namedesc (scriptingFrame, edit_script_frame)
--triggers, this part is unique to scripts
--dropdown to select which type of trigger / frame it'll use
local on_select_tracking_option = function (self, fixed_parameter, value_selected)
local scriptObject = scriptingFrame.GetCurrentScriptObject()
scriptObject.ScriptType = value_selected
--change the trigger type
--auras or spellcast
if (value_selected == 1 or value_selected == 2) then
scriptingFrame.TriggerScrollBox:SetData (scriptObject.SpellIds)
scriptingFrame.TriggerLabel.text = "Add Trigger (Spell Id or Spell Name)"
--npc name
elseif (value_selected == 3) then
scriptingFrame.TriggerScrollBox:SetData (scriptObject.NpcNames)
scriptingFrame.TriggerLabel.text = "Add Trigger (Unit Name)"
end
scriptingFrame.TriggerScrollBox:Refresh()
--recompile all
Plater.WipeAndRecompileAllScripts ("script")
end
local build_script_type_dropdown_options = function()
local t = {
{label = scriptingFrame.GetScriptTriggerTypeName (1), value = 1, onclick = on_select_tracking_option, desc = select (2, scriptingFrame.GetScriptTriggerTypeName (1))},
{label = scriptingFrame.GetScriptTriggerTypeName (2), value = 2, onclick = on_select_tracking_option, desc = select (2, scriptingFrame.GetScriptTriggerTypeName (2))},
{label = scriptingFrame.GetScriptTriggerTypeName (3), value = 3, onclick = on_select_tracking_option, desc = select (2, scriptingFrame.GetScriptTriggerTypeName (3))},
}
return t
end
local script_type_label = DF:CreateLabel (edit_script_frame, "Trigger Type:", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
local script_type_dropdown = DF:CreateDropDown (edit_script_frame, build_script_type_dropdown_options, 1, 160, 20, "ScriptTypeDropdown", _, options_dropdown_template)
script_type_dropdown:SetPoint ("topleft", script_type_label, "bottomleft", 0, -2)
script_type_dropdown.tooltip = "The type of event when the script check for trigger matches, only the selected option is used.\n\n|cFFFFFF00Buffs & Debuffs|r: an aura shown in the nameplate.\n\n|cFFFFFF00Spell Casting|r: the spell the unit is casting.\n\n|cFFFFFF00Unit Name|r: the unit name shown in the nameplate."
scriptingFrame.ScriptTypeDropdown = script_type_dropdown
--button to add a spellId or npc name trigger
local add_trigger_label = DF:CreateLabel (edit_script_frame, "Add Trigger (Spell Id or Spell Name)", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
local add_trigger_textentry = DF:CreateTextEntry (edit_script_frame, function()end, 140, 20, "ScriptTriggerTextEntry", _, _, options_dropdown_template)
add_trigger_textentry:SetPoint ("topleft", add_trigger_label, "bottomleft", 0, -2)
add_trigger_textentry.tooltip = "Enter data based on the trigger selected:\n\n|cFFFFFF00Buff and Spell Cast|r: Enter the spell name using lower case letters.\n\n|cFFFFFF00Unit Name|r: Enter the unit name or the npcID."
scriptingFrame.TriggerTextEntry = add_trigger_textentry
scriptingFrame.TriggerLabel = add_trigger_label
add_trigger_textentry:SetHook ("OnEditFocusGained", function (self, capsule)
--if ithe script is for aura or castbar and if the textentry box doesnt have an auto complete table yet
local scriptObject = scriptingFrame.GetCurrentScriptObject()
if ((scriptObject.ScriptType == 1 or scriptObject.ScriptType == 2) and (not add_trigger_textentry.SpellAutoCompleteList or not scriptingFrame.SpellIndexTable[1])) then
--load spell hash table
scriptingFrame.LoadGameSpells()
add_trigger_textentry.SpellAutoCompleteList = scriptingFrame.SpellIndexTable
add_trigger_textentry:SetAsAutoComplete ("SpellAutoCompleteList", nil, true)
end
end)
local add_trigger_button = DF:CreateButton (edit_script_frame, scriptingFrame.AddTrigger, 50, 20, "Add", -1, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
add_trigger_button:SetIcon ([[Interface\BUTTONS\UI-PlusButton-Up]], 20, 20, "overlay", {0, 1, 0, 1})
add_trigger_button:SetPoint ("left", add_trigger_textentry, "right", 2, 0)
--add_trigger_button.tooltip =
add_trigger_button:SetHook ("OnEnter", function()
GameCooltip:Preset (2)
--GameCooltip:SetOption ("TextSize", 11)
GameCooltip:SetOption ("FixedWidth", 300)
local scriptObject = scriptingFrame.GetCurrentScriptObject()
if ((scriptObject.ScriptType == 1 or scriptObject.ScriptType == 2)) then
GameCooltip:AddLine ("|cFFFFFF00Important|r: it's normal for the Icon and Description of the spell you added to be different, The name of the spell is used to active the script.\n\nYou can enter the SpellID as well.")
else
GameCooltip:AddLine ("|cFFFFFF00Important|r: npc name isn't case-sensitive.\n\n|cFFFFFF00Important|r: you can use the npcId as well for the multi-language support of your script.")
end
GameCooltip:SetOwner (add_trigger_button.widget)
GameCooltip:Show()
end)
add_trigger_button:SetHook ("OnLeave", function()
GameCooltip:Hide()
end)
scriptingFrame.AddTriggerButton = add_trigger_button
--list of spells or npc names for this script
--refresh the list of scripts already created
local refresh_trigger_scrollbox = function (self, data, offset, total_lines)
local data
local scriptObject = scriptingFrame.GetCurrentScriptObject()
if (scriptObject) then
if (scriptObject.ScriptType == 1 or scriptObject.ScriptType == 2) then
data = scriptObject.SpellIds
elseif (scriptObject.ScriptType == 3) then
data = scriptObject.NpcNames
end
--update the scroll
for i = 1, total_lines do
local index = i + offset
local trigger = data [index]
if (trigger) then
--update the line
local line = self:GetLine (i)
line:UpdateLine (index, trigger)
end
end
end
--update overlap button
scriptingFrame.UpdateOverlapButton()
end
--when the user hover over a scrollbox line
local onenter_trigger_line = function (self)
if (self.SpellID) then
GameTooltip:SetOwner (self, "ANCHOR_RIGHT")
GameTooltip:SetSpellByID (self.SpellID)
GameTooltip:AddLine (" ")
GameTooltip:Show()
end
self:SetBackdropColor (.3, .3, .3, 0.7)
end
--when the user leaves a scrollbox line from a hover over
local onleave_trigger_line = function (self)
GameTooltip:Hide()
self:SetBackdropColor (unpack (scrollbox_line_backdrop_color))
end
--update the trigger line
local update_trigger_line = function (self, trigger_id, trigger)
local scriptObject = scriptingFrame.GetCurrentScriptObject()
if (scriptObject.ScriptType == 1 or scriptObject.ScriptType == 2) then
--spellname
local spellName, _, spellIcon = GetSpellInfo (trigger)
self.Icon:SetTexture (spellIcon)
self.Icon:SetTexCoord (.1, .9, .1, .9)
self.Icon:SetDesaturated (false)
self.Icon:SetAlpha (1)
self.SpellID = trigger
self.TriggerName:SetText (spellName)
self.TriggerID:SetText (trigger)
elseif (scriptObject.ScriptType == 3) then
--npc name
self.Icon:SetTexture ([[Interface\ICONS\INV_Misc_SeagullPet_01]])
self.Icon:SetTexCoord (.9, .1, .1, .9)
self.Icon:SetDesaturated (true)
self.Icon:SetAlpha (0.5)
self.SpellID = nil
self.TriggerName:SetText (trigger)
self.TriggerID:SetText ("")
end
self.TriggerId = trigger_id
end
local onclick_remove_trigger_line = function (self)
local scriptObject = scriptingFrame.GetCurrentScriptObject()
local parent = self:GetParent()
local triggerId = parent.TriggerId
--remove the trigger
if (scriptObject.ScriptType == 1 or scriptObject.ScriptType == 2) then
--spellname
tremove (scriptObject.SpellIds, triggerId)
elseif (scriptObject.ScriptType == 3) then
--npc name
tremove (scriptObject.NpcNames, triggerId)
end
--refresh the trigger box
scriptingFrame.TriggerScrollBox:Refresh()
--update overlap button
scriptingFrame.UpdateOverlapButton()
--recompile all
Plater.WipeAndRecompileAllScripts ("script")
end
--create a line in the scroll box
local create_line_triggerbox = function (self, index)
--create a new line
local line = CreateFrame ("button", "$parentLine" .. index, self, BackdropTemplateMixin and "BackdropTemplate")
--set its parameters
line:SetPoint ("topleft", self, "topleft", 0, -((index-1) * (triggerbox_line_height+1)))
line:SetSize (triggerbox_size[1], triggerbox_line_height)
line:SetScript ("OnEnter", onenter_trigger_line)
line:SetScript ("OnLeave", onleave_trigger_line)
line:SetBackdrop ({bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
line:SetBackdropColor (unpack (scrollbox_line_backdrop_color))
local icon = line:CreateTexture ("$parentIcon", "overlay")
icon:SetSize (triggerbox_line_height - 2, triggerbox_line_height - 2)
local trigger_name = DF:CreateLabel (line, "", DF:GetTemplate ("font", "PLATER_SCRIPTS_NAME"))
local trigger_id = DF:CreateLabel (line, "", DF:GetTemplate ("font", "PLATER_SCRIPTS_TRIGGER_SPELLID"))
local remove_button = CreateFrame ("button", "$parentRemoveButton", line, "UIPanelCloseButton")
remove_button:SetSize (16, 16)
remove_button:SetScript ("OnClick", onclick_remove_trigger_line)
remove_button:SetPoint ("topright", line, "topright")
remove_button:GetNormalTexture():SetDesaturated (true)
icon:SetPoint ("left", line, "left", 2, 0)
trigger_name:SetPoint ("topleft", icon, "topright", 4, -2)
trigger_id:SetPoint ("topleft", trigger_name, "bottomleft", 0, 0)
line.Icon = icon
line.TriggerName = trigger_name
line.TriggerID = trigger_id
line.RemoveButton = remove_button
line.UpdateLine = update_trigger_line
line:Hide()
return line
end
--scroll showing all triggers of the script
local trigger_scrollbox_label = DF:CreateLabel (edit_script_frame, "Triggers:", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
local trigger_scrollbox = DF:CreateScrollBox (edit_script_frame, "$parentTriggerScrollBox", refresh_trigger_scrollbox, {}, triggerbox_size[1], triggerbox_size[2], triggerbox_lines, triggerbox_line_height)
trigger_scrollbox:SetPoint ("topleft", trigger_scrollbox_label.widget, "bottomleft", 0, -4)
trigger_scrollbox:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
trigger_scrollbox:SetBackdropColor (0, 0, 0, 0.2)
trigger_scrollbox:SetBackdropBorderColor (0, 0, 0, 1)
scriptingFrame.TriggerScrollBox = trigger_scrollbox
DF:ReskinSlider (trigger_scrollbox)
local overlapFrame = DF:CreateSimplePanel (UIParent, 600, 400, "Trigger Overlap", "PlaterScriptTriggerOverlap")
overlapFrame:SetFrameStrata ("DIALOG")
overlapFrame:SetPoint ("center")
DF:ApplyStandardBackdrop (overlapFrame, false, 1.2)
overlapFrame.OverlappedScriptFrames = {}
overlapFrame:Hide()
local enableScriptFromOverlapPanel = function (self, fixedParameter, scriptObject, value2)
scriptObject.Enabled = true
scriptingFrame.UpdateOverlapButton()
scriptingFrame.ScriptSelectionScrollBox:Refresh()
overlapFrame.RefreshPanel()
end
local disableScriptFromOverlapPanel = function (self, fixedParameter, scriptObject, value2)
scriptObject.Enabled = false
scriptingFrame.UpdateOverlapButton()
scriptingFrame.ScriptSelectionScrollBox:Refresh()
overlapFrame.RefreshPanel()
end
local removeTriggerFromOverlapPanel = function (self, fixedParameter, scriptObject, triggerId)
if (scriptObject.ScriptType == 0x1 or scriptObject.ScriptType == 0x2) then
for index, trigger in ipairs (scriptObject.SpellIds) do
if (trigger == triggerId) then
tremove (scriptObject.SpellIds, index)
break
end
end
else
for index, trigger in ipairs (scriptObject.NpcNames) do
if (trigger == triggerId) then
tremove (scriptObject.NpcNames, index)
break
end
end
end
scriptingFrame.UpdateOverlapButton()
overlapFrame.RefreshPanel()
--reload all scripts
Plater.WipeAndRecompileAllScripts ("script")
end
local onEnterOverlapPanelLine = function (self)
self:SetBackdropColor (0.5, 0.5, 0.5, 1)
end
local onLeaveOverlapPanelLine = function (self)
self:SetBackdropColor (unpack (self.OriginalBackdropColor))
end
local onClickOverlapPanelLine = function (self)
if (self.ScriptObject) then
local currentScriptObject = scriptingFrame.GetCurrentScriptObject()
--check if isn't the same script
local scriptToBeEdited = self.ScriptObject
if (scriptToBeEdited == currentScriptObject) then
--no need to load the new script if is the same
return
end
--save the current script if any
if (currentScriptObject) then
scriptingFrame.SaveScript()
end
--select the script to start edit
scriptingFrame.EditScript (self.ScriptObject)
--refresh the script list to update the backdrop color of the selected script
scriptingFrame.ScriptSelectionScrollBox:Refresh()
--check if the import/export text field is shown and hide it
if (scriptingFrame.ImportTextEditor:IsShown()) then
scriptingFrame.ImportTextEditor:Hide()
end
end
end
overlapFrame.RefreshPanel = function()
if (not overlapFrame:IsShown()) then
return
end
if (not overlapFrame.CreateNewFrameTable) then
local reset = function (f)
f.TriggerName.text = ""
f.TriggerId.text = ""
for i = 1, #f.Scripts do
f.Scripts [i].Parent:Hide()
end
end
function overlapFrame:CreateNewFrameTable()
local i = #overlapFrame.OverlappedScriptFrames + 1
local f = CreateFrame ("frame", "$parentTriggerCluster" .. i, overlapFrame, BackdropTemplateMixin and "BackdropTemplate")
f:SetSize (590, 20)
f.Reset = reset
DF:ApplyStandardBackdrop (f, true, 0.1)
if (i == 1) then
f:SetPoint ("topleft", overlapFrame, "topleft", 5, -26)
else
f:SetPoint ("topleft", overlapFrame.OverlappedScriptFrames [i - 1], "bottomleft", 0, -2)
end
f.TriggerName = DF:CreateLabel (f)
f.TriggerIcon = DF:CreateImage (f, "", 18, 18)
f.TriggerIcon:SetPoint (5, -5)
f.TriggerName:SetPoint ("left", f.TriggerIcon, "right", 2, 0)
f.TriggerId = DF:CreateLabel (f)
f.TriggerId:SetPoint (250, -5)
f.Scripts = {}
for o = 1, 2 do
overlapFrame:CreateFrameForScript (f, o)
end
tinsert (overlapFrame.OverlappedScriptFrames, f)
return f
end
function overlapFrame:CreateFrameForScript (f, i)
local ff = CreateFrame ("frame", "$parentLine" .. i, f, BackdropTemplateMixin and "BackdropTemplate")
ff:SetSize (580, 22)
ff:SetPoint ("topleft", f, "topleft", 0, -24 - ((i - 1) * 23))
DF:ApplyStandardBackdrop (ff, true, 0.8)
ff:SetBackdropBorderColor (0, 0, 0, 0)
ff:SetFrameLevel (f:GetFrameLevel() + 5)
ff.OriginalBackdropColor = {ff:GetBackdropColor()}
local scriptName = DF:CreateLabel (ff)
local enableScript = DF:CreateButton (ff, enableScriptFromOverlapPanel, 120, 20, "Enable Script", nil, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
local disableScript = DF:CreateButton (ff, disableScriptFromOverlapPanel, 120, 20, "Disable Script", nil, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
local removeTrigger = DF:CreateButton (ff, removeTriggerFromOverlapPanel, 120, 20, "Remove Trigger", nil, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
--> create a background below the script name to make an impression it's a button
local nameBackdrop = CreateFrame ("frame", nil, ff, BackdropTemplateMixin and "BackdropTemplate")
nameBackdrop:SetSize (140, 20)
DF:ApplyStandardBackdrop (nameBackdrop)
nameBackdrop:SetPoint ("topleft", ff, "topleft", 3, 0)
nameBackdrop:EnableMouse (false)
nameBackdrop:SetBackdropColor (0, 0, 0, 0)
nameBackdrop.__background:Hide()
scriptName:SetPoint (5, -4)
enableScript:SetPoint (160, 0)
disableScript:SetPoint ("left", enableScript, "right", 2, 0)
removeTrigger:SetPoint ("left", disableScript, "right", 2, 0)
ff:SetScript ("OnEnter", onEnterOverlapPanelLine)
ff:SetScript ("OnLeave", onLeaveOverlapPanelLine)
ff:SetScript ("OnMouseDown", onClickOverlapPanelLine)
tinsert (f.Scripts, {ScriptName = scriptName, EnableButton = enableScript, DisableButton = disableScript, RemoveButton = removeTrigger, Parent = ff})
return f.Scripts [#f.Scripts]
end
end
local overlaps = scriptingFrame.OverlapButton.OverlapTable
if (overlaps) then
--reset frames
for i, frame in ipairs (overlapFrame.OverlappedScriptFrames) do
frame:Reset()
frame:Hide()
end
local i = 1
for triggerTypeName, overlapTable in pairs (scriptingFrame.OverlapButton.OverlapTable) do
for triggerId, scriptsTable in pairs (overlapTable) do
local frameTable = overlapFrame.OverlappedScriptFrames [i]
if (not frameTable) then
frameTable = overlapFrame:CreateNewFrameTable()
end
frameTable:Reset()
frameTable:Show()
local triggerName = triggerId
local triggerIcon = ""
if (scriptsTable[1].ScriptType == 0x1 or scriptsTable[1].ScriptType == 0x2) then
triggerName, _, triggerIcon = GetSpellInfo (triggerId)
frameTable.TriggerIcon.texture = triggerIcon
frameTable.TriggerIcon:SetTexCoord (.1, .9, .1, .9)
else
frameTable.TriggerIcon.texture = ""
end
frameTable.TriggerName.text = triggerName
frameTable.TriggerId.text = triggerId .. " [" .. ((scriptingFrame.TriggerTypes [triggerTypeName == "Auras" and 1 or triggerTypeName == "Casts" and 2 or triggerTypeName == "Npcs" and 3]) or "") .. "]"
for o = 1, #scriptsTable do
local scriptF = frameTable.Scripts [o]
if (not scriptF) then
scriptF = overlapFrame:CreateFrameForScript (frameTable, o)
end
local scriptObject = scriptsTable [o]
scriptF.ScriptName.text = scriptObject.Name
scriptF.Parent.ScriptObject = scriptObject
if (not scriptObject.Enabled) then
scriptF.EnableButton:SetClickFunction (enableScriptFromOverlapPanel, scriptObject)
scriptF.EnableButton:Enable()
else
scriptF.EnableButton:Disable()
end
if (scriptObject.Enabled) then
scriptF.DisableButton:SetClickFunction (disableScriptFromOverlapPanel, scriptObject)
scriptF.DisableButton:Enable()
else
scriptF.DisableButton:Disable()
end
scriptF.RemoveButton:SetClickFunction (removeTriggerFromOverlapPanel, scriptObject, triggerId)
scriptF.Parent:Show()
end
frameTable:SetHeight (22 + (#scriptsTable * 26))
i = i + 1
end
end
else
overlapFrame:Hide()
end
end
overlapFrame:SetScript ("OnShow", function()
overlapFrame.RefreshPanel()
end)
--add script overlap button / frame
local overlapButton = Plater:CreateButton (scriptingFrame, function() overlapFrame:Show() end, 160, 20, "Trigger Overlaps: 0", -1, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
overlapButton:SetPoint ("topleft", trigger_scrollbox, "bottomleft", 0, -2)
overlapButton:SetPoint ("topright", trigger_scrollbox, "bottomright", 0, -2)
scriptingFrame.OverlapButton = overlapButton
overlapButton:SetHook ("OnEnter", function (self)
GameCooltip:Preset (2)
GameCooltip:SetOption ("TextSize", 11)
GameCooltip:SetOption ("FixedWidth", 300)
GameCooltip:AddLine ("Trigger Overlaps", "", 1, "yellow", "yellow", 12, nil, "OUTLINE")
GameCooltip:AddLine ("A SpellID, NpcName or NpcID cannot be used in more than 1 script with the same Trigger Type.")
GameCooltip:AddLine (" ")
GameCooltip:AddLine ("Trigger Name", "Trigger ID", 1, "yellow", "yellow", 12)
if (overlapButton.OverlapAmount and overlapButton.OverlapAmount > 0) then
for triggerId, scriptsTable in pairs (overlapButton.OverlapTable.Auras) do
local triggerName = GetSpellInfo (triggerId)
GameCooltip:AddLine (triggerName, triggerId .. " [" .. scriptingFrame.TriggerTypes [1] .. "]")
end
for triggerId, scriptsTable in pairs (overlapButton.OverlapTable.Casts) do
local triggerName = GetSpellInfo (triggerId)
GameCooltip:AddLine (triggerName, triggerId .. " [" .. scriptingFrame.TriggerTypes [1] .. "]")
end
for triggerId, scriptsTable in pairs (overlapButton.OverlapTable.Npcs) do
local triggerName = triggerId
GameCooltip:AddLine (triggerName, triggerId .. " [" .. scriptingFrame.TriggerTypes [1] .. "]")
end
GameCooltip:AddLine (" ")
GameCooltip:AddLine ("click for more information", "", 1, "green")
end
GameCooltip:SetOwner (self)
GameCooltip:Show()
end)
overlapButton:SetHook ("OnLeave", function()
GameCooltip:Hide()
end)
function scriptingFrame.UpdateOverlapButton()
local overlappedTriggers, amoutOfOverlaps = Plater.CheckScriptTriggerOverlap()
overlapButton:SetText ("Trigger Overlaps: " .. amoutOfOverlaps)
if (amoutOfOverlaps > 0) then
overlapButton:SetTemplate (options_button_template)
overlapButton:SetTextColor (DF:GetTemplate ("font", "PLATER_BUTTON").color)
else
overlapButton:SetTemplate (DF:GetTemplate ("button", "PLATER_BUTTON_DISABLED"))
local r, g, b = unpack (DF:GetTemplate ("font", "PLATER_BUTTON").color)
overlapButton:SetTextColor (r/2, g/2, b/2)
end
overlapButton.OverlapAmount = amoutOfOverlaps
overlapButton.OverlapTable = overlappedTriggers
PlaterScriptTriggerOverlap.RefreshPanel()
end
--create the scrollbox lines
for i = 1, scrollbox_lines do
trigger_scrollbox:CreateLine (create_line_triggerbox)
end
create_import_box (edit_script_frame, scriptingFrame)
create_code_editor (edit_script_frame, scriptingFrame)
--api help small frame
local unit_frame_components_menu = DF:CreateButton (scriptingFrame.CodeEditorLuaEntry, function() end, 100, 20, "Components", -1, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
unit_frame_components_menu:SetIcon ([[Interface\FriendsFrame\UI-FriendsList-Large-Up]], 16, 16, "overlay", {.2, .74, .27, .75}, nil, 4)
local onSelectComponentMember = function (a, d, member)
scriptingFrame.CodeEditorLuaEntry.editbox:Insert (member)
GameCooltip:Hide()
end
local buildComponentTableMenu = function()
GameCooltip:Preset (2)
GameCooltip:SetOption ("TextSize", 11)
GameCooltip:SetOption ("FixedWidth", 300)
GameCooltip:AddLine ("Nameplate Components", "", 1, "yellow", "yellow", 12, nil, "OUTLINE")
local backgroundAlpha = 0.2
for i = 1, #Plater.UnitFrameMembers do
GameCooltip:AddLine (Plater.UnitFrameMembers [i])
GameCooltip:AddMenu (1, onSelectComponentMember, Plater.UnitFrameMembers [i])
GameCooltip:AddStatusBar (100, 1, 0, 0, 0, backgroundAlpha)
end
end
unit_frame_components_menu.CoolTip = {
Type = "menu",
BuildFunc = buildComponentTableMenu,
ShowSpeed = 0.05,
}
GameCooltip2:CoolTipInject (unit_frame_components_menu)
--script env helper
local script_env_helper = DF:CreateButton (scriptingFrame.CodeEditorLuaEntry, function() end, 100, 20, "envTable", -1, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
script_env_helper:SetIcon ([[Interface\FriendsFrame\UI-FriendsList-Small-Up]], 16, 16, "overlay", {.2, .74, .27, .75}, nil, 4)
local onSelectEnvTableMember = function (a, d, member)
scriptingFrame.CodeEditorLuaEntry.editbox:Insert (member)
GameCooltip:Hide()
end
local buildEnvTableMenu = function()
local scriptObject = scriptingFrame.GetCurrentScriptObject()
if (not scriptObject) then
GameCooltip:Preset (2)
GameCooltip:SetOption ("TextSize", 11)
GameCooltip:SetOption ("FixedWidth", 400)
GameCooltip:AddLine ("*No script loaded", "", 1, "red")
GameCooltip:AddLine ("Use this menu to quick add to your code a member from envTable")
return
end
GameCooltip:Preset (2)
GameCooltip:SetOption ("TextSize", 11)
GameCooltip:SetOption ("FixedWidth", 400)
local backgroundAlpha = 0.2
--if (scriptObject.ScriptType == 0x1) then
if (not scriptObject or scriptObject.ScriptType == 0x1) then
GameCooltip:AddLine ("envTable Members for Trigger Buffs and Debuffs", "", 1, "yellow", "yellow", 12, nil, "OUTLINE")
for index, member in ipairs (Plater.TriggerDefaultMembers [1]) do
GameCooltip:AddLine (member, "", 1, "orange", "white"); GameCooltip:AddStatusBar (100, 1, 0, 0, 0, backgroundAlpha)
GameCooltip:AddMenu (1, onSelectEnvTableMember, member)
end
--adds a space to separate from the infor of the next trigger
if (not scriptObject) then
GameCooltip:AddLine (" ")
end
end
if (not scriptObject or scriptObject.ScriptType == 0x2) then
GameCooltip:AddLine ("envTable Members for Trigger Spell Casting", "", 1, "yellow", "yellow", 12, nil, "OUTLINE")
for index, member in ipairs (Plater.TriggerDefaultMembers [2]) do
GameCooltip:AddLine (member, "", 1, "orange", "white"); GameCooltip:AddStatusBar (100, 1, 0, 0, 0, backgroundAlpha)
GameCooltip:AddMenu (1, onSelectEnvTableMember, member)
end
--adds a space to separate from the infor of the next trigger
if (not scriptObject) then
GameCooltip:AddLine (" ")
end
end
if (not scriptObject or scriptObject.ScriptType == 0x3) then
GameCooltip:AddLine ("envTable Members for Trigger Unit Name", "", 1, "yellow", "yellow", 12, nil, "OUTLINE")
for index, member in ipairs (Plater.TriggerDefaultMembers [3]) do
GameCooltip:AddLine (member, "", 1, "orange", "white"); GameCooltip:AddStatusBar (100, 1, 0, 0, 0, backgroundAlpha)
GameCooltip:AddMenu (1, onSelectEnvTableMember, member)
end
end
GameCooltip:AddLine (" ")
GameCooltip:AddLine ("envTable Members From Constructor Code:", "", 1, "yellow", "yellow", 12, nil, "OUTLINE")
--> get the constructor code from the editor if the current editing is the constructor or get the temporarily saved script from the script object
local code = scriptingFrame.currentScriptType == 2 and scriptingFrame.CodeEditorLuaEntry:GetText() or scriptObject ["Temp_" .. Plater.CodeTypeNames [2]]
if (code) then
--> find all member names added to the envTable
--> add all members in the comments too
local alreadyAdded = {}
for _, memberName in code:gmatch ("(envTable%.)(.-)(%s)") do
memberName = DF:Trim (memberName)
if (not memberName:find ("%s") and not alreadyAdded [memberName]) then
alreadyAdded [memberName] = memberName
GameCooltip:AddLine ("envTable." .. memberName, "", 1, "orange", "white"); GameCooltip:AddStatusBar (100, 1, 0, 0, 0, backgroundAlpha)
GameCooltip:AddMenu (1, onSelectEnvTableMember, "envTable." .. memberName)
end
end
end
end
script_env_helper.CoolTip = {
Type = "menu",
BuildFunc = buildEnvTableMenu,
ShowSpeed = 0.05,
}
GameCooltip2:CoolTipInject (script_env_helper)
--top left of the code editor
script_env_helper:SetPoint ("bottomleft", scriptingFrame.CodeEditorLuaEntry, "topleft", 0, 2)
unit_frame_components_menu:SetPoint ("left", script_env_helper, "right", 2, 0)
--change the script code type (when the user select from normal runtime code or constructor code)
local on_select_code_type = function (self, fixed_parameter, value_selected)
--get the current editing script
local scriptObject = scriptingFrame.GetCurrentScriptObject()
local formerScriptType = scriptingFrame.currentScriptType
local newScriptType = value_selected
--save the current code
scriptObject ["Temp_" .. Plater.CodeTypeNames [formerScriptType]] = scriptingFrame.CodeEditorLuaEntry:GetText()
--ensure consistency (!=nil) TODO: mod migration on login/import would make this redundant
if newScriptType == 5 and scriptObject ["Temp_" .. Plater.CodeTypeNames [newScriptType]] == nil then
scriptObject ["Temp_" .. Plater.CodeTypeNames [newScriptType]] = scriptingFrame.DefaultScriptNoNameplate
end
--load the code
scriptingFrame.CodeEditorLuaEntry:SetText (scriptObject ["Temp_" .. Plater.CodeTypeNames [newScriptType]])
--update the code type
scriptingFrame.SetCurrentEditingScript(newScriptType)
--show hide frames
scriptingFrame.ImportTextEditor:Hide()
scriptingFrame.CodeEditorLuaEntry:Show()
scriptingFrame.ScriptOptionsPanelAdmin:Hide()
scriptingFrame.ScriptOptionsPanelUser:Hide()
end
local build_script_code_dropdown_options = function()
local t = {}
for i = 1, #scriptingFrame.CodeTypes do
local thisType = scriptingFrame.CodeTypes [i]
tinsert (t, {label = thisType.Name, value = thisType.Value, desc = thisType.Desc, onclick = on_select_code_type})
end
return t
end
local code_type_label = DF:CreateLabel (scriptingFrame, "Edit Script For:", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
local code_type_dropdown = DF:CreateDropDown (scriptingFrame, build_script_code_dropdown_options, 1, 160, 20, "CodeTypeDropdown", _, options_dropdown_template)
--code_type_dropdown:SetPoint ("left", code_type_label, "right", 2, 0)
code_type_dropdown.CodeType = 1
scriptingFrame.CodeTypeDropdown = code_type_dropdown
function scriptingFrame.SetCurrentEditingScript(scriptId)
scriptingFrame.currentScriptType = scriptId
_G.C_Timer.After(0.05, scriptingFrame.UpdateScriptsButton)
end
scriptingFrame.currentScriptType = 1 --default value
--> script buttons
--constructor
local codeButtonSize = {100, 20}
scriptingFrame.scriptButtons = {}
local code_oninit_button = DF:CreateButton(scriptingFrame, on_select_code_type, codeButtonSize[1], codeButtonSize[2], "Initialization", 5, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
code_oninit_button:SetPoint("topleft", scriptingFrame.CodeEditorLuaEntry, "bottomleft", 0, -15)
local code_constructor_button = DF:CreateButton(scriptingFrame, on_select_code_type, codeButtonSize[1], codeButtonSize[2], "Constructor", 2, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
code_constructor_button:SetPoint("left", code_oninit_button, "right", 2, 0)
local code_onshow_button = DF:CreateButton(scriptingFrame, on_select_code_type, codeButtonSize[1], codeButtonSize[2], "On Show", 4, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
code_onshow_button:SetPoint("left", code_constructor_button, "right", 2, 0)
local code_onupdate_button = DF:CreateButton(scriptingFrame, on_select_code_type, codeButtonSize[1], codeButtonSize[2], "On Update", 1, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
code_onupdate_button:SetPoint("left", code_onshow_button, "right", 2, 0)
local code_hide_button = DF:CreateButton(scriptingFrame, on_select_code_type, codeButtonSize[1], codeButtonSize[2], "On Hide", 3, nil, nil, nil, nil, nil, options_button_template, DF:GetTemplate ("font", "PLATER_BUTTON"))
code_hide_button:SetPoint("left", code_onupdate_button, "right", 2, 0)
tinsert(scriptingFrame.scriptButtons, code_onupdate_button)
tinsert(scriptingFrame.scriptButtons, code_constructor_button)
tinsert(scriptingFrame.scriptButtons, code_hide_button)
tinsert(scriptingFrame.scriptButtons, code_onshow_button)
tinsert(scriptingFrame.scriptButtons, code_oninit_button)
function scriptingFrame.UpdateScriptsButton()
local canShowSelection = scriptingFrame.CodeEditorLuaEntry:IsShown()
for i = 1, #scriptingFrame.scriptButtons do
local button = scriptingFrame.scriptButtons[i]
if (i == scriptingFrame.currentScriptType and canShowSelection) then
button:SetTemplate(DF:GetTemplate("button", "PLATER_BUTTON_SELECTED"))
else
button:SetTemplate(DF:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"))
end
end
end
--create the header
create_script_control_header (scriptingFrame, "script")
create_script_scroll(scriptingFrame)
--
--when the profile has changed
function scriptingFrame:RefreshOptions()
--update the script data for the scroll and refresh
scriptingFrame.ScriptSelectionScrollBox:SetData (Plater.db.profile.script_data)
scriptingFrame.ScriptSelectionScrollBox:Refresh()
end
--create the options script box for scripts
Plater.CreateScriptingOptionsPanel(edit_script_frame, scriptingFrame)
--anchors
--scroll to select which script to edit
--script_scrollbox_label:SetPoint ("topleft", create_new_script_button.widget, "bottomleft", 0, -12)
scriptingFrame.ScriptSelectionScrollBox:SetPoint ("topleft", scriptingFrame.ScriptSearchTextEntry.widget, "bottomleft", 0, -20)
scriptingFrame.ScriptScrollLabel:SetPoint ("bottomleft", scriptingFrame.ScriptSelectionScrollBox, "topleft", 0, 2)
scriptingFrame.ScriptEnabledLabel:SetPoint ("bottomright", scriptingFrame.ScriptSelectionScrollBox, "topright", 0, 2)
--create frame holding the script options
edit_script_frame:SetPoint ("topleft", scriptingFrame, "topleft", scrollbox_size[1] + 30, start_y)
--script options
edit_script_frame.ScriptNameLabel:SetPoint ("topleft", edit_script_frame, "topleft", 10, 2)
edit_script_frame.ScriptIconLabel:SetPoint ("topleft", edit_script_frame, "topleft", 170, 0)
edit_script_frame.ScriptDescLabel:SetPoint ("topleft", edit_script_frame, "topleft", 10, -40)
edit_script_frame.ScriptPrioLabel:SetPoint ("topleft", edit_script_frame, "topleft", 10, -80)
script_type_label:SetPoint ("topleft", edit_script_frame, "topleft", 10, -140)
add_trigger_label:SetPoint ("topleft", edit_script_frame, "topleft", 10, -177)
trigger_scrollbox_label:SetPoint ("topleft", edit_script_frame, "topleft", 10, -216)
--lua code editor
scriptingFrame.CodeEditorLuaEntry:SetPoint ("topleft", edit_script_frame, "topleft", 230, -20)
--import editor
scriptingFrame.ImportTextEditor:SetPoint ("topleft", edit_script_frame, "topleft", 230, -20)
--button on code editors
scriptingFrame.SaveScriptButton:SetPoint ("bottomright", scriptingFrame.CodeEditorLuaEntry, "bottomright", 0, 1)
scriptingFrame.CancelScriptButton:SetPoint ("right", scriptingFrame.SaveScriptButton, "left", -10, 0)
scriptingFrame.DocsButton:SetPoint ("right", scriptingFrame.CancelScriptButton, "left", -10, 0)
scriptingFrame.SaveScriptButton:SetSize(buttons_size[1]*0.7, buttons_size[2] - 1)
scriptingFrame.CancelScriptButton:SetSize(buttons_size[1]*0.7, buttons_size[2] - 1)
scriptingFrame.DocsButton:SetSize(buttons_size[1]*0.7, buttons_size[2] - 1)
--import control buttons
scriptingFrame.ImportTextEditor.OkayButton:SetPoint ("topright", scriptingFrame.CodeEditorLuaEntry, "bottomright", 0, -10)
scriptingFrame.ImportTextEditor.CancelButton:SetPoint ("right", scriptingFrame.ImportTextEditor.OkayButton, "left", -20, 0)
--code type
code_type_label:SetPoint ("topleft", scriptingFrame.CodeEditorLuaEntry, "bottomleft", 0, -4)
scriptingFrame.ScriptOptionsPanelAdmin:SetPoint("topleft", edit_script_frame, "topleft", 230, -20)
scriptingFrame.ScriptOptionsPanelUser:SetPoint("topleft", edit_script_frame, "topleft", 230, -20)
scriptingFrame.EditScriptFrame:LockFrame()
scriptingFrame.EditScriptFrame:Show()
end
--endd ends