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.

1293 lines
44 KiB

local Plater = Plater
local GameCooltip = GameCooltip2
local DF = DetailsFramework
local _
local GetSpellInfo = GetSpellInfo or function(spellID) if not spellID then return nil end local si = C_Spell.GetSpellInfo(spellID) if si then return si.name, nil, si.iconID, si.castTime, si.minRange, si.maxRange, si.spellID, si.originalIconID end end
--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")
local scrollbox_size = {201, 405}
local scrollbox_lines = 11
local scrollbox_line_height = 28.7
local scrollbox_line_backdrop_color = {0, 0, 0, 0.5}
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}
local debugmode = false
local PLATER_OPTIONS_ANIMATION_TAB = 20
function Plater.CreateSpellAnimationPanel()
local f = PlaterOptionsPanelFrame
local mainFrame = PlaterOptionsPanelContainer
local animationFrame = mainFrame.AllFrames [PLATER_OPTIONS_ANIMATION_TAB]
--store which animation is being edited
local currentAnimation
local currentCopy
local previewEnabled = true
local previewLoopTime = 1
animationFrame.CurrentIndex = 1
animationFrame.SearchString = ""
animationFrame.AvailableSpells = {}
--set points
local startX = 10
local startY = -220 --menu and settings panel
local startYGeneralSettings = -150
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local CLEUFrame = CreateFrame ("frame")
CLEUFrame.SpellCaptured = {}
CLEUFrame.PlayerSerial = UnitGUID ("player")
CLEUFrame:SetScript ("OnEvent", function (self, event)
local time, token, hidding, sourceGUID, sourceName, sourceFlag, sourceFlag2, targetGUID, targetName, targetFlag, targetFlag2, spellID, spellName, spellType, amount, overKill, school, resisted, blocked, absorbed, isCritical = CombatLogGetCurrentEventInfo()
if (token == "SPELL_DAMAGE" or token == "SPELL_PERIODIC_DAMAGE") then
if (CLEUFrame.PlayerSerial == sourceGUID) then
if (not CLEUFrame.SpellCaptured [spellID]) then
CLEUFrame.SpellCaptured [spellID] = {Token = token, Name = spellName, ID = spellID}
animationFrame.SelectSpellDropdown:Refresh()
end
end
end
end)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--> logic
function animationFrame.LoopPreview()
--simulate a hit in the nameplate
if (currentAnimation and #currentAnimation > 0) then
local spellName = GetSpellInfo (currentAnimation.info.spellid)
if (spellName and Plater.SPELL_WITH_ANIMATIONS [spellName]) then
for _, plateFrame in ipairs (Plater.GetAllShownPlates()) do
Plater.DoNameplateAnimation (plateFrame, Plater.SPELL_WITH_ANIMATIONS [spellName], spellName, false)
end
end
end
end
function animationFrame.StopPreview()
if (animationFrame.PreviewTicker) then
animationFrame.PreviewTicker:Cancel()
end
end
function animationFrame.UpdatePreview (newLoopTime)
if (animationFrame.PreviewTicker) then
animationFrame.PreviewTicker:Cancel()
end
previewLoopTime = newLoopTime or previewLoopTime
if (previewEnabled) then
animationFrame.PreviewTicker = C_Timer.NewTicker (previewLoopTime, animationFrame.LoopPreview)
end
end
animationFrame:HookScript ("OnShow", function()
animationFrame.BuildAnimationDataForScroll()
CLEUFrame:RegisterEvent ("COMBAT_LOG_EVENT_UNFILTERED")
Plater.RefreshIsEditingAnimations (true)
if (previewEnabled) then
animationFrame.UpdatePreview()
end
end)
animationFrame:HookScript ("OnHide", function()
CLEUFrame:UnregisterEvent ("COMBAT_LOG_EVENT_UNFILTERED")
Plater.RefreshIsEditingAnimations (false)
animationFrame.StopPreview()
end)
function animationFrame.GetAnimation (spellID)
return Plater.db.profile.spell_animation_list [spellID]
end
--runs when clicking in the add animation button
function animationFrame.AddNewAnimation()
--get the option selected in the dropdown
local spellID = animationFrame.SelectSpellDropdown.value
if (not spellID or type (spellID) ~= "number") then
return
end
--check if there's an animation for this spell
local db = Plater.db.profile.spell_animation_list
if (db [spellID]) then
Plater:Msg ("an animation for this spell already exists.")
return
end
local _, playerClass = UnitClass ("player")
--add the spell to the animation list
local newAnimationTable = {
info = {
time = time(),
desc = "",
class = playerClass,
spellid = spellID,
}
}
db [spellID] = newAnimationTable
--refresh the scrollbox
animationFrame.BuildAnimationDataForScroll()
--start editing this new animation
animationFrame.EditAnimation (spellID)
end
function animationFrame.ShowImportTextField()
animationFrame.ImportAnimation()
end
--when a text in the searchi field is changed, get the text and update the animation list
function animationFrame.OnSearchBoxTextChanged()
local text = animationFrame.AnimationSearchTextEntry:GetText()
animationFrame.SearchString = text:lower()
animationFrame.AnimationScrollBox:Refresh()
end
--build an index table to be used in the scroll selection
function animationFrame.BuildAnimationDataForScroll()
local db = Plater.db.profile.spell_animation_list
local t = {}
--get the player class and only show animations that is used on its class
local _, playerClass = UnitClass ("player")
for spellID, animationTable in pairs (db) do
if (animationTable.info.class == playerClass) then
tinsert (t, animationTable)
end
end
animationFrame.AnimationScrollBox:SetData (t)
animationFrame.AnimationScrollBox:Refresh()
end
--sort by name, index 5 holds the name:lower()
function animationFrame.SortScroll (t1, t2)
return t1[5] < t2[5]
end
--update the scroll list in the left side
function animationFrame.RefreshAnimationSelectScrollBox (self, data, offset, total_lines)
--animationFrame.SearchString
local dataInOrder = {}
if (animationFrame.SearchString ~= "") then
for i = 1, #data do
local animationTable = data[i]
local spellID = animationTable.info.spellid
local spellName, _, spellIcon = GetSpellInfo (spellID)
if (spellName) then
local spellNameLower = spellName:lower()
if (spellNameLower:find (animationFrame.SearchString)) then
dataInOrder [#dataInOrder+1] = {spellID, data[i], spellName, spellIcon, spellNameLower}
end
end
end
else
for i = 1, #data do
local animationTable = data[i]
local spellID = animationTable.info.spellid
local spellName, _, spellIcon = GetSpellInfo (spellID)
if (spellName) then
local spellNameLower = spellName:lower()
dataInOrder [#dataInOrder+1] = {spellID, data[i], spellName, spellIcon, spellNameLower}
end
end
end
table.sort (dataInOrder, animationFrame.SortScroll)
--update the scroll
for i = 1, total_lines do
local index = i + offset
local t = dataInOrder [index]
if (t) then
--get the data
local spellID = t[1]
local data = t[2]
local spellName = t[3]
local spellIcon = t[4]
--update the line
local line = self:GetLine (i)
line:UpdateLine (spellID, data, spellName, spellIcon)
if (data == currentAnimation) then
line:SetBackdropColor (unpack (scrollbox_line_backdrop_color_selected))
else
line:SetBackdropColor (unpack (scrollbox_line_backdrop_color))
end
end
end
end
function animationFrame.OnEnterScrollSelectionLine (self)
self:SetBackdropColor (.3, .3, .3, .6)
end
function animationFrame.OnLeaveScrollSelectionLine (self)
--check if the hover overed button is the current animation being edited
if (currentAnimation == self.Data) then
self:SetBackdropColor (unpack (scrollbox_line_backdrop_color_selected))
else
self:SetBackdropColor (unpack (scrollbox_line_backdrop_color))
end
end
function animationFrame.EditAnimation (spellID)
local animationObject = animationFrame.GetAnimation (spellID)
if (not animationObject) then
Plater:Msg ("animation not found")
return
end
currentAnimation = animationObject
--refresh the spell selection box
animationFrame.AnimationScrollBox:Refresh()
--update the editing animation
--animationFrame:HideAllConfigFrames()
animationFrame.EffectSelectionDropdown:Refresh()
animationFrame.EffectSelectionDropdown:Select (1, true)
animationFrame.OnSelectEffect (_, _, 1)
animationFrame.RefreshAddAnimationButtons()
if (animationFrame.IsExporting or animationFrame.IsImporting) then
animationFrame.HideStringField()
end
end
--user selected 'paste' in the context menu of 'self'
--copy the settings from the 'currentCopy' variable into the animation table for this widget
function animationFrame.PasteAnimationSettings (self)
if (not currentCopy or #currentCopy == 0) then
Plater:Msg ("there's no animation to paste.")
return
end
local spellID = self.SpellID
if (spellID) then
local animationObject = animationFrame.GetAnimation (spellID)
if (animationObject) then
--iterate among all copied animations
for i = 1, #currentCopy do
local thisCopiedEffect = currentCopy [i]
local copiedEffectType = thisCopiedEffect.animation_type
--below it iterates among all animation in the target animation object, if it doesn't find an effect table like the copied one, it needs to add it then
local shouldAdd = true
for i = 1, #animationObject do
local animationEffect = animationObject [i]
if (animationEffect.animation_type == copiedEffectType) then
--replace the effect settings
DF.table.copy (animationEffect, thisCopiedEffect)
shouldAdd = false
break
end
end
--if it fails to find a similar effect, add it
if (shouldAdd) then
tinsert (animationObject, DF.table.copy ({}, thisCopiedEffect))
end
end
animationFrame.EditAnimation (spellID)
Plater.RefreshDBUpvalues()
Plater:Msg ("settings applied!")
else
Plater:Msg ("animation net found")
end
else
Plater:Msg ("invalid spellID")
end
end
function animationFrame.OnClickMenuLine (self, spellID, option, value)
if (option == "editanimation") then
animationFrame.EditAnimation (spellID)
elseif (option == "copy") then
local animationObject = animationFrame.GetAnimation (self.SpellID)
--make a new table for the copied effects
currentCopy = {}
--animations stay in the indexed part of the animtion object
--copy the settings of these indexes into the copy table
for i = 1, #animationObject do
local effect = animationObject [i]
tinsert (currentCopy, DF.table.copy ({}, effect))
end
local spellName = GetSpellInfo (spellID)
if (spellName) then
Plater:Msg (spellName .. " copied.")
end
elseif (option == "export") then
animationFrame.ExportAnimation (self)
elseif (option == "paste") then
animationFrame.PasteAnimationSettings (self)
elseif (option == "remove") then
animationFrame.RemoveAnimation (self)
elseif (option == "export_table") then
animationFrame.ExportAnimation (self, true)
end
GameCooltip:Hide()
end
function animationFrame.OnClickScrollSelectionLine (self, button)
local spellID = self.SpellID
if (spellID) then
if (button == "LeftButton") then
animationFrame.EditAnimation (spellID)
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 (spellID)
GameCooltip:AddLine ("Edit Animation")
GameCooltip:AddMenu (1, animationFrame.OnClickMenuLine, "editanimation")
GameCooltip:AddIcon ([[Interface\BUTTONS\UI-GuildButton-PublicNote-Up]], 1, 1, 16, 16)
GameCooltip:AddLine ("Copy Settings")
GameCooltip:AddMenu (1, animationFrame.OnClickMenuLine, "copy")
GameCooltip:AddIcon ([[Interface\AddOns\Plater\images\icons]], 1, 1, 16, 16, 3/512, 21/512, 215/512, 233/512)
if (currentCopy) then
GameCooltip:AddLine ("Paste Settings")
GameCooltip:AddMenu (1, animationFrame.OnClickMenuLine, "paste")
GameCooltip:AddIcon ([[Interface\AddOns\Plater\images\icons]], 1, 1, 16, 16, 3/512, 21/512, 215/512, 233/512)
else
GameCooltip:AddLine ("Paste Settings", "", 1, "gray")
GameCooltip:AddMenu (1, animationFrame.OnClickMenuLine, "paste")
GameCooltip:AddIcon ([[Interface\AddOns\Plater\images\icons]], 1, 1, 16, 16, 3/512, 21/512, 215/512, 233/512, false, false, true)
end
GameCooltip:AddLine ("Export As a Text String", "", 1)
GameCooltip:AddIcon ([[Interface\BUTTONS\UI-GuildButton-MOTD-Up]], 1, 1, 16, 16, 1, 0, 0, 1)
GameCooltip:AddMenu (1, animationFrame.OnClickMenuLine, "export")
GameCooltip:AddLine ("Remove")
GameCooltip:AddMenu (1, animationFrame.OnClickMenuLine, "remove")
GameCooltip:AddIcon ([[Interface\AddOns\Plater\images\icons]], 1, 1, 16, 16, 3/512, 21/512, 235/512, 257/512)
--dev tool to export in database format
if (GetRealmName() == "Azralon") then
GameCooltip:AddLine ("$div")
GameCooltip:AddLine ("Export To Table (dev)", "", 1)
GameCooltip:AddIcon ([[Interface\BUTTONS\UI-GuildButton-MOTD-Up]], 1, 1, 16, 16, 1, 0, 0, 1)
GameCooltip:AddMenu (1, animationFrame.OnClickMenuLine, "export_table")
end
GameCooltip:Show()
end
end
end
--update a single line in the scroll list
function animationFrame.UpdateScrollLine (self, spellID, data, spellName, spellIcon)
self.Icon:SetTexture (spellIcon)
self.Icon:SetTexCoord (.1, .9, .1, .9)
self.AnimationName:SetText (spellName)
self.SpellID = spellID
self.Data = data
end
function animationFrame:HideAllConfigFrames()
for _, frame in pairs (animationFrame.AllConfigFrames) do
frame:Hide()
end
end
function animationFrame.OnSelectEffect (self, _, effectIndex)
if (not currentAnimation [effectIndex]) then
animationFrame.DisableOptions()
return
else
animationFrame.EnableOptions()
end
animationFrame.CurrentIndex = effectIndex
animationFrame:HideAllConfigFrames()
local animationData = currentAnimation [animationFrame.CurrentIndex]
local configFrame = animationFrame.AllConfigFrames [animationData.animation_type]
configFrame.Data = animationData
configFrame:RefreshOptions()
configFrame:Show()
end
function animationFrame.RefreshEffectListDropdown (self)
local t = {}
if (currentAnimation) then
for animationIndex, animationTable in ipairs (currentAnimation) do
tinsert (t, {label = " #" .. animationIndex .. " " .. animationTable.animation_type, value = animationIndex, onclick = animationFrame.OnSelectEffect})
end
end
return t
end
function animationFrame.AddNewShakeEffect()
if (currentAnimation) then
tinsert (currentAnimation, {
enabled = true,
animation_type = "frameshake",
scaleX = .1,
scaleY = 1,
absolute_sineX = false,
absolute_sineY = false,
duration = 0.1,
amplitude = 3,
frequency = 1,
fade_in = 0.01,
fade_out = 0.09,
cooldown = 0.5,
critical_scale = 1.05,
})
animationFrame.EffectSelectionDropdown:Refresh()
animationFrame.CurrentIndex = #currentAnimation
animationFrame.EffectSelectionDropdown:Select (#currentAnimation, true)
animationFrame.OnSelectEffect (_, _, #currentAnimation)
animationFrame.RefreshAddAnimationButtons()
end
end
function animationFrame.AddNewScaleEffect()
if (currentAnimation) then
tinsert (currentAnimation, {
enabled = true,
duration = 0.05, --seconds
animation_type = "scale",
cooldown = 0.75, --seconds
scale_upX = 1.03,
scale_upY = 1.03,
scale_downX = 0.97,
scale_downY = 0.97,
})
animationFrame.EffectSelectionDropdown:Refresh()
animationFrame.CurrentIndex = #currentAnimation
animationFrame.EffectSelectionDropdown:Select (#currentAnimation, true)
animationFrame.OnSelectEffect (_, _, #currentAnimation)
animationFrame.RefreshAddAnimationButtons()
end
end
function animationFrame.RefreshAddAnimationButtons()
animationFrame.AddShakeButton:Enable()
animationFrame.AddScaleButton:Enable()
if (not currentAnimation) then
animationFrame.AddShakeButton:Disable()
animationFrame.AddScaleButton:Disable()
return
end
for animationIndex, animationTable in ipairs (currentAnimation) do
if (animationTable.animation_type == "scale") then
animationFrame.AddScaleButton:Disable()
end
if (animationTable.animation_type == "frameshake") then
animationFrame.AddShakeButton:Disable()
end
end
end
local cooltipInjectionScrollLine = function (self, fixed_parameter)
GameCooltip:Preset (2)
GameCooltip:SetOption ("TextSize", 10)
GameCooltip:SetOption ("FixedWidth", 200)
local animationObject = animationFrame.GetAnimation (self.SpellID)
local lastEdited = date ("%d/%m/%Y", animationObject.info.time)
local spellName, _, spellIcon = GetSpellInfo (self.SpellID)
GameCooltip:AddLine (spellName, nil, 1, "yellow", "yellow", 11, "Friz Quadrata TT", "OUTLINE")
GameCooltip:AddIcon (spellIcon, 1, 1, 18, 18, .1, .9, .1, .9)
GameCooltip:AddLine ("Last Edited:", lastEdited)
if (animationObject.info.desc and animationObject.info.desc ~= "") then
GameCooltip:AddLine (animationObject.info.desc, "", 1, "gray")
end
end
local cooltipInjectionTable_ScrollLine = {
Type = "tooltip",
BuildFunc = cooltipInjectionScrollLine,
ShowSpeed = 0.016,
MyAnchor = "topleft",
HisAnchor = "topright",
X = 10,
Y = 0,
}
function animationFrame.RemoveAnimation (self)
local spellID = self.SpellID
if (spellID) then
--is removing the animation which is currently being edited?
if (currentAnimation == Plater.db.profile.spell_animation_list [spellID]) then
animationFrame.DisableOptions()
animationFrame.AddShakeButton:Disable()
animationFrame.AddScaleButton:Disable()
currentAnimation = nil
animationFrame.EffectSelectionDropdown:Refresh()
end
Plater.db.profile.spell_animation_list [spellID] = nil
Plater.RefreshDBUpvalues()
animationFrame.BuildAnimationDataForScroll()
end
end
function animationFrame.ImportAnimation()
animationFrame.IsExporting = nil
animationFrame.IsImporting = true
animationFrame.ImportStringField:Show()
animationFrame.AnimationConfigFrame:Hide()
animationFrame.ImportStringField:SetText ("")
animationFrame.ImportStringField:SetFocus (true)
end
function animationFrame.ExportDev (self)
local spellID = self.SpellID
local animationToExport = animationFrame.GetAnimation (spellID)
local copy = DF.table.copy ({}, animationToExport)
copy = {
[spellID] = copy
}
local spellName = GetSpellInfo (spellID)
local class = UnitClass ("player")
animationFrame.ImportStringField:SetText ("--" .. spellName .. " (" .. class .. ")\n" .. DF.table.dump (copy))
animationFrame.ImportStringField:SetFocus (true)
animationFrame.ImportStringField.editbox:HighlightText()
animationFrame.AnimationConfigFrame:Hide()
return
end
function animationFrame.ExportAnimation (self, isDev)
animationFrame.IsExporting = true
animationFrame.IsImporting = nil
animationFrame.ImportStringField:Show()
if (isDev) then
animationFrame.ExportDev (self)
return
end
local spellID = self.SpellID
local animationToExport = animationFrame.GetAnimation (spellID)
if (animationToExport) then
--export to string
animationFrame.ImportStringField:SetText (Plater.CompressData (animationToExport, "print") or "failed to export")
C_Timer.After (.1, function()
animationFrame.ImportStringField:SetFocus (true)
animationFrame.ImportStringField.editbox:HighlightText()
end)
animationFrame.AnimationConfigFrame:Hide()
end
end
function animationFrame.DoImportAnimation (animationObject)
local spellID = tonumber(animationObject.info.spellid)
local spellName = GetSpellInfo (spellID)
if not spellName then return end
local db = Plater.db.profile.spell_animation_list
db [spellID] = animationObject
Plater:Msg ("animation for spell " .. spellName .. " added!")
local _, class = UnitClass ("player")
if (class ~= animationObject.info.class) then
Plater:Msg ("this animation is for " .. animationObject.info.class .. " and won't show on this character.")
end
animationFrame.EditAnimation (spellID)
animationFrame.BuildAnimationDataForScroll()
Plater.RefreshDBUpvalues()
end
function animationFrame.ConfirmImportAnimation()
if (animationFrame.IsExporting) then
animationFrame.HideStringField()
return
end
local text = animationFrame.ImportStringField:GetText()
local animationObject = Plater.DecompressData (text, "print")
animationFrame.HideStringField()
if (animationObject) then
local db = Plater.db.profile.spell_animation_list
local spellID = tonumber(animationObject.info.spellid)
if (not spellID) then
Plater:Msg ("invalid animation.")
return
end
local spellName = GetSpellInfo (spellID)
if (not spellName) then
Plater:Msg ("the spell for this animation doesn't exists.")
return
end
--already have
if (db [spellID]) then
--show a box to confirm
DF:ShowPromptPanel ("Animation for " .. spellName .. " already exists, overwrite?", function()
--true
animationFrame.DoImportAnimation (animationObject)
end,
function()
return
end)
else
animationFrame.DoImportAnimation (animationObject)
end
else
Plater:Msg ("invalid animation.")
end
end
function animationFrame.HideStringField()
animationFrame.IsExporting = nil
animationFrame.IsImporting = nil
animationFrame.ImportStringField:Hide()
animationFrame.ImportStringField:SetText ("")
animationFrame.AnimationConfigFrame:Show()
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--> build the frames
local optionsTable = {
{type = "label", get = function() return "General Settings:" end, text_template = DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE")},
{
type = "toggle",
get = function() return Plater.db.profile.spell_animations end,
set = function (self, fixedparam, value)
Plater.db.profile.spell_animations = value
Plater.RefreshDBUpvalues()
end,
name = "Spell Animations Enabled",
desc = "If enabled some of your abilities will cause the nameplate to shake or play a special effect when the ability hits the enemy.\n\nCustomize each animation in the Animations tab.",
},
{
type = "range",
get = function() return Plater.db.profile.spell_animations_scale end,
set = function (self, fixedparam, value)
Plater.db.profile.spell_animations_scale = value
end,
min = 0.75,
max = 2.75,
step = 0.1,
name = "Overall Intensity",
desc = "Overall intensity scale of the spell animations.",
thumbscale = 1.8,
usedecimals = true,
},
}
DF:BuildMenu (animationFrame, optionsTable, 10, startYGeneralSettings, 330, true, options_text_template, options_dropdown_template, options_switch_template, true, options_slider_template, options_button_template, animationFrame.OnDataChange)
local scrollBoxHeight = 396 - 70
--dropdown select spell to add
local buildAddSpellOptions = function()
local t = {}
local db = Plater.db.profile.spell_animation_list
for spellID, spellInfo in pairs (CLEUFrame.SpellCaptured) do
if (not db [spellInfo.ID]) then
local _, _, spellIcon = GetSpellInfo (spellInfo.ID)
if (spellIcon) then
tinsert (t, {label = spellInfo.Name, value = spellInfo.ID, onclick = function()end, desc = "Spell ID: " .. spellInfo.ID, icon = spellIcon, texcoord = {.1, .9, .1, .9}})
end
end
end
return t
end
local selectSpellLabel = DF:CreateLabel (animationFrame, "Select Spell to Add Animation:", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
local selectSpellDropdown = DF:CreateDropDown (animationFrame, buildAddSpellOptions, 1, 130, 20, "SelectSpellDropdown", _, DF:GetTemplate ("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
selectSpellDropdown:SetPoint ("topleft", selectSpellLabel, "bottomleft", 0, -2)
--button add spell
local addSpellButton = DF:CreateButton (animationFrame, animationFrame.AddNewAnimation, 40, 20, "Add", -1, nil, nil, nil, nil, nil, DF:GetTemplate ("button", "OPTIONS_BUTTON_TEMPLATE"), DF:GetTemplate ("font", "PLATER_BUTTON"))
addSpellButton:SetPoint ("left", selectSpellDropdown, "right", 2, 0)
addSpellButton.tooltip = function()
if (not next (CLEUFrame.SpellCaptured)) then
return "No spells to add?\n\nHit any npc with spells while this window is open to fill the dropdown with options."
else
return "Add animation for the selected spell."
end
end
--button import animation
local importButton = DF:CreateButton (animationFrame, animationFrame.ShowImportTextField, 26, 20, "", -1, nil, nil, nil, nil, nil, DF:GetTemplate ("button", "OPTIONS_BUTTON_TEMPLATE"), DF:GetTemplate ("font", "PLATER_BUTTON"))
importButton:SetIcon ([[Interface\AddOns\Plater\images\icons]], 16, 16, "overlay", {5/512, 19/512, 195/512, 210/512}, {1, .8, .2}, nil, nil, nil, false)
importButton:SetPoint ("left", addSpellButton, "right", 2, 0)
importButton:HookScript ("OnEnter", function()
GameCooltip:Preset (2)
GameCooltip:SetOption ("TextSize", 10)
GameCooltip:SetOption ("FixedWidth", 200)
GameCooltip:SetOwner (importButton.widget)
GameCooltip:AddLine ("Import Animation", "", 1, "yellow", "yellow", 12, nil, "OUTLINE")
GameCooltip:AddLine ("Add an animation from a string.\n\nYou can export to string by right clicking an animation in the menu below.")
GameCooltip:Show()
end)
importButton:HookScript ("OnLeave", function()
GameCooltip:Hide()
end)
--search box
local searchLabel = DF:CreateLabel (animationFrame, "Search:", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
searchLabel:SetPoint ("topleft", selectSpellDropdown, "bottomleft", 0, -5)
local searchAnimationTextEntry = DF:CreateTextEntry (animationFrame, function()end, 200, 20, "AnimationSearchTextEntry", _, _, options_dropdown_template)
searchAnimationTextEntry:SetHook ("OnChar", animationFrame.OnSearchBoxTextChanged)
searchAnimationTextEntry:SetHook ("OnTextChanged", animationFrame.OnSearchBoxTextChanged)
searchAnimationTextEntry:SetPoint ("topleft", searchLabel, "bottomleft", 0, -2)
--scrollbox to select the spell animation to edit
local spellLabel = DF:CreateLabel (animationFrame, "Spell Animations", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
spellLabel:SetPoint ("topleft", searchAnimationTextEntry, "bottomleft", 0, -5)
local animationSelectScrollBox = DF:CreateScrollBox (animationFrame, "$parentScrollBox", animationFrame.RefreshAnimationSelectScrollBox, {}, 200, scrollBoxHeight, scrollbox_lines, scrollbox_line_height)
animationSelectScrollBox:SetPoint ("topleft", spellLabel.widget, "bottomleft", 0, -2)
DF:ReskinSlider (animationSelectScrollBox)
animationFrame.AnimationScrollBox = animationSelectScrollBox
local createNewLineFunc = 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", 1, -((index-1) * (scrollbox_line_height+1)) - 1)
line:SetSize (scrollbox_size[1]-2, scrollbox_line_height)
line:RegisterForClicks ("LeftButtonDown", "RightButtonDown")
line:SetScript ("OnEnter", animationFrame.OnEnterScrollSelectionLine)
line:SetScript ("OnLeave", animationFrame.OnLeaveScrollSelectionLine)
line:SetScript ("OnClick", animationFrame.OnClickScrollSelectionLine)
line.CoolTip = cooltipInjectionTable_ScrollLine
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 animationName = DF:CreateLabel (line, "", DF:GetTemplate ("font", "PLATER_SCRIPTS_NAME"))
--setup anchors
icon:SetPoint ("left", line, "left", 2, 0)
animationName:SetPoint ("topleft", icon, "topright", 2, -2)
line.Icon = icon
line.AnimationName = animationName
line.UpdateLine = animationFrame.UpdateScrollLine
return line
end
--create the scrollbox lines
for i = 1, scrollbox_lines do
animationSelectScrollBox:CreateLine (createNewLineFunc)
end
--import box
--text editor
local luaeditor_backdrop_color = {.2, .2, .2, .5}
local luaeditor_border_color = {0, 0, 0, 1}
local edit_script_size = {620, 431}
local buttons_size = {120, 20}
local importStringField = DF:NewSpecialLuaEditorEntry (animationFrame, 825, edit_script_size[2] - 75, "ImportEditor", "$parentImportEditor", true)
importStringField:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
importStringField:SetBackdropBorderColor (unpack (luaeditor_border_color))
importStringField:SetBackdropColor (unpack (luaeditor_backdrop_color))
importStringField:Hide()
animationFrame.ImportStringField = importStringField
DF:ReskinSlider (importStringField.scroll)
--import button
local okayButton = DF:CreateButton (importStringField, animationFrame.ConfirmImportAnimation, buttons_size[1], buttons_size[2], "Okay", -1, nil, nil, nil, nil, nil, DF:GetTemplate ("button", "OPTIONS_BUTTON_TEMPLATE"), DF:GetTemplate ("font", "PLATER_BUTTON"))
okayButton:SetIcon ([[Interface\BUTTONS\UI-Panel-BiggerButton-Up]], 20, 20, "overlay", {0.1, .9, 0.1, .9})
--cancel button
local cancelButton = DF:CreateButton (importStringField, animationFrame.HideStringField, buttons_size[1], buttons_size[2], "Cancel", -1, nil, nil, nil, nil, nil, DF:GetTemplate ("button", "OPTIONS_BUTTON_TEMPLATE"), DF:GetTemplate ("font", "PLATER_BUTTON"))
cancelButton:SetIcon ([[Interface\BUTTONS\UI-Panel-MinimizeButton-Up]], 20, 20, "overlay", {0.1, .9, 0.1, .9})
okayButton:SetPoint ("topright", importStringField, "bottomright", 0, -7)
cancelButton:SetPoint ("right", okayButton, "left", -20, 0)
--editing settings of the animation
local animationConfigFrame = CreateFrame ("frame", "$parentAnimationConfig", animationFrame, BackdropTemplateMixin and "BackdropTemplate")
DF:ApplyStandardBackdrop (animationConfigFrame)
animationConfigFrame:SetPoint ("topleft", animationSelectScrollBox, "topright", 45, 53 + 70)
animationConfigFrame:SetSize (825, scrollBoxHeight + 53 + 5)
animationFrame.AnimationConfigFrame = animationConfigFrame
local animationPreviewFrame = CreateFrame ("frame", "$parentPreviewConfig", animationFrame, BackdropTemplateMixin and "BackdropTemplate")
DF:ApplyStandardBackdrop (animationPreviewFrame)
animationPreviewFrame:SetPoint ("topleft", animationConfigFrame, "bottomleft", 0, -5)
animationPreviewFrame:SetPoint ("topright", animationConfigFrame, "bottomright", 0, -5)
animationPreviewFrame:SetHeight (60)
animationFrame.AnimationPreviewFrame = animationPreviewFrame
local previewHeaderLabel = DF:CreateLabel (animationPreviewFrame, "Preview Settings:", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
previewHeaderLabel:SetPoint ("topleft", animationPreviewFrame, "topleft", 5, -5)
--select effect dropdown (scale, shake)
local effectSelectionLabel = DF:CreateLabel (animationConfigFrame, "Effect:", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
local effectSelectionDropdown = DF:CreateDropDown (animationConfigFrame, animationFrame.RefreshEffectListDropdown, 1, 160, 20, "EffectSelectionDropdown", _, DF:GetTemplate ("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
effectSelectionDropdown:SetPoint ("left", effectSelectionLabel, "right", 2, 0)
animationFrame.EffectSelectionDropdown = effectSelectionDropdown
--add shake effect
local addShakeButton = DF:CreateButton (animationConfigFrame, animationFrame.AddNewShakeEffect, 120, 20, "Add Shake Effect", -1, nil, nil, nil, nil, nil, DF:GetTemplate ("button", "OPTIONS_BUTTON_TEMPLATE"), DF:GetTemplate ("font", "PLATER_BUTTON"))
animationFrame.AddShakeButton = addShakeButton
--add scale effect
local addScaleButton = DF:CreateButton (animationConfigFrame, animationFrame.AddNewScaleEffect, 120, 20, "Add Scale Effect", -1, nil, nil, nil, nil, nil, DF:GetTemplate ("button", "OPTIONS_BUTTON_TEMPLATE"), DF:GetTemplate ("font", "PLATER_BUTTON"))
addScaleButton:SetPoint ("left", addShakeButton, "right", 2, 0)
animationFrame.AddScaleButton = addScaleButton
animationFrame.AllConfigFrames = {}
local scaleOptionsFrame = CreateFrame ("frame", "$parentScaleFrame", animationConfigFrame, BackdropTemplateMixin and "BackdropTemplate")
scaleOptionsFrame:Hide()
animationFrame.AllConfigFrames ["scale"] = scaleOptionsFrame
local shakeOptionsFrame = CreateFrame ("frame", "$parentShakeFrame", animationConfigFrame, BackdropTemplateMixin and "BackdropTemplate")
animationFrame.AllConfigFrames ["frameshake"] = shakeOptionsFrame
function animationFrame.DisableOptions()
for _, widget in ipairs (scaleOptionsFrame.widget_list) do
if (widget.Disable) then
widget:Disable()
end
end
for _, widget in ipairs (shakeOptionsFrame.widget_list) do
if (widget.Disable) then
widget:Disable()
end
end
end
function animationFrame.EnableOptions()
for _, widget in ipairs (scaleOptionsFrame.widget_list) do
if (widget.Enable) then
widget:Enable()
end
end
for _, widget in ipairs (shakeOptionsFrame.widget_list) do
if (widget.Enable) then
widget:Enable()
end
end
end
for _, frame in pairs (animationFrame.AllConfigFrames) do
frame:SetSize (460, 250)
frame:SetPoint ("topleft", animationConfigFrame, "topleft", 5, -5)
--frame:Hide()
frame.Data = {}
end
local scaleOptionsTable = {
{
type = "toggle",
get = function() return scaleOptionsFrame.Data.enabled end,
set = function (self, fixedparam, value)
scaleOptionsFrame.Data.enabled = value
end,
name = "Enabled",
},
{type = "blank"},
{
type = "range",
get = function() return scaleOptionsFrame.Data.duration end,
set = function (self, fixedparam, value)
scaleOptionsFrame.Data.duration = value
end,
min = 0.05,
max = 1,
step = 0.05,
usedecimals = true,
name = "Duration",
},
{type = "blank"},
{
type = "range",
get = function() return scaleOptionsFrame.Data.scale_upX end,
set = function (self, fixedparam, value)
scaleOptionsFrame.Data.scale_upX = value
end,
min = 0,
max = 20,
step = 0.05,
usedecimals = true,
name = "Scale Up X",
},
{
type = "range",
get = function() return scaleOptionsFrame.Data.scale_upY end,
set = function (self, fixedparam, value)
scaleOptionsFrame.Data.scale_upY = value
end,
min = 0,
max = 20,
step = 0.05,
usedecimals = true,
name = "Scale Up Y",
},
{
type = "range",
get = function() return scaleOptionsFrame.Data.scale_downX end,
set = function (self, fixedparam, value)
scaleOptionsFrame.Data.scale_downX = value
end,
min = 0,
max = 20,
step = 0.05,
usedecimals = true,
name = "Scale Down X",
},
{
type = "range",
get = function() return scaleOptionsFrame.Data.scale_downY end,
set = function (self, fixedparam, value)
scaleOptionsFrame.Data.scale_downY = value
end,
min = 0,
max = 20,
step = 0.05,
usedecimals = true,
name = "Scale Down Y",
},
{type = "blank"},
{
type = "range",
get = function() return scaleOptionsFrame.Data.cooldown end,
set = function (self, fixedparam, value)
scaleOptionsFrame.Data.cooldown = value
end,
min = 0,
max = 20,
step = 0.05,
usedecimals = true,
name = "Cooldown",
},
{type = "blank"},
{
type = "range",
get = function() return scaleOptionsFrame.Data.critical_scale end,
set = function (self, fixedparam, value)
scaleOptionsFrame.Data.critical_scale = value
end,
min = 1,
max = 2,
step = 0.05,
usedecimals = true,
name = "Critical Hit Scale",
},
}
local shakeOptionsTable = {
{
type = "toggle",
get = function() return shakeOptionsFrame.Data.enabled end,
set = function (self, fixedparam, value)
shakeOptionsFrame.Data.enabled = value
end,
name = "Enabled",
},
{type = "blank"},
{
type = "range",
get = function() return shakeOptionsFrame.Data.duration end,
set = function (self, fixedparam, value)
shakeOptionsFrame.Data.duration = value
end,
min = 0.05,
max = 1,
step = 0.05,
usedecimals = true,
name = "Duration",
desc = "Animation duration time.",
},
{
type = "range",
get = function() return shakeOptionsFrame.Data.amplitude end,
set = function (self, fixedparam, value)
shakeOptionsFrame.Data.amplitude = value
end,
min = 0,
max = 50,
step = 0.05,
usedecimals = true,
name = "Amplitude",
desc = "Scale the strength of the animation.",
},
{
type = "range",
get = function() return shakeOptionsFrame.Data.frequency end,
set = function (self, fixedparam, value)
shakeOptionsFrame.Data.frequency = value
end,
min = 0,
max = 200,
step = 0.05,
usedecimals = true,
name = "Frequency",
desc = "Scale how fast and often the animation plays within its duration time.",
},
{type = "blank"},
{
type = "range",
get = function() return shakeOptionsFrame.Data.scaleX end,
set = function (self, fixedparam, value)
shakeOptionsFrame.Data.scaleX = value
end,
min = -50,
max = 50,
step = 0.05,
usedecimals = true,
name = "Scale X",
desc = "Scale the animation on its horizontal axis.",
},
{
type = "range",
get = function() return shakeOptionsFrame.Data.scaleY end,
set = function (self, fixedparam, value)
shakeOptionsFrame.Data.scaleY = value
end,
min = -50,
max = 50,
step = 0.05,
usedecimals = true,
name = "Scale Y",
desc = "Scale the animation on its vertical axis.",
},
{
type = "toggle",
get = function() return shakeOptionsFrame.Data.absolute_sineX end,
set = function (self, fixedparam, value)
shakeOptionsFrame.Data.absolute_sineX = value
end,
name = "Absolute Sine X",
desc = "Makes the sine wave of the animation to not use its negative part making it always to the right side.\n\nIf the |cFFFFFF00Scale X|r option has a negative value the animation goes to the left side.",
},
{
type = "toggle",
get = function() return shakeOptionsFrame.Data.absolute_sineY end,
set = function (self, fixedparam, value)
shakeOptionsFrame.Data.absolute_sineY = value
end,
name = "Absolute Sine Y",
desc = "Makes the sine wave of the animation to not use its negative part making it always to go up.\n\nIf the |cFFFFFF00Scale Y|r option has a negative value the animation goes down instead.",
},
{type = "blank"},
{
type = "range",
get = function() return shakeOptionsFrame.Data.fade_in end,
set = function (self, fixedparam, value)
shakeOptionsFrame.Data.fade_in = value
end,
min = 0,
max = 2,
step = 0.05,
usedecimals = true,
name = "Fade In Time",
desc = "Time the animation takes to go from not playing at all to its full effect strength.\n\nThis time is within the animation duration time.",
},
{
type = "range",
get = function() return shakeOptionsFrame.Data.fade_out end,
set = function (self, fixedparam, value)
shakeOptionsFrame.Data.fade_out = value
end,
min = 0,
max = 2,
step = 0.05,
usedecimals = true,
name = "Fade Out Time",
desc = "Time the animation takes to go from playing its full effect to not playing at all.\n\nThis time is within the animation duration time.",
},
{type = "blank"},
{
type = "range",
get = function() return shakeOptionsFrame.Data.cooldown end,
set = function (self, fixedparam, value)
shakeOptionsFrame.Data.cooldown = value
end,
min = 0,
max = 20,
step = 0.05,
usedecimals = true,
name = "Cooldown",
desc = "Won't play this animation again while its cooldown time isn't passed.",
},
{type = "blank"},
{
type = "range",
get = function() return scaleOptionsFrame.Data.critical_scale end,
set = function (self, fixedparam, value)
scaleOptionsFrame.Data.critical_scale = value
end,
min = 1,
max = 2,
step = 0.05,
usedecimals = true,
name = "Critical Hit Scale",
},
}
--the callback function seems to be firing before the OnValueChanged function in the widget
--delaying the update a little bit fixes this
local updateAnimationOnPlater = function()
Plater.RefreshDBLists()
--invalidate the timer
animationFrame.RefreshTimer:Cancel()
end
function animationFrame.OnDataChange()
if (animationFrame.RefreshTimer) then
if (not animationFrame.RefreshTimer._cancelled) then
return
end
end
animationFrame.RefreshTimer = C_Timer.NewTimer (.1, updateAnimationOnPlater)
end
DF:BuildMenu (scaleOptionsFrame, scaleOptionsTable, 0, 0, 330, true, options_text_template, options_dropdown_template, options_switch_template, true, options_slider_template, options_button_template, animationFrame.OnDataChange)
DF:BuildMenu (shakeOptionsFrame, shakeOptionsTable, 0, 0, 330, true, options_text_template, options_dropdown_template, options_switch_template, true, options_slider_template, options_button_template, animationFrame.OnDataChange)
local animationPreviewOptionsTable = {
{
type = "toggle",
get = function() return previewEnabled end,
set = function (self, fixedparam, value)
previewEnabled = value
animationFrame.UpdatePreview()
end,
name = "Enabled",
},
{
type = "range",
get = function() return previewLoopTime end,
set = function (self, fixedparam, value)
animationFrame.UpdatePreview (value)
end,
min = .1,
max = 10,
step = 0.05,
usedecimals = true,
name = "Loop Time",
},
}
DF:BuildMenu (animationPreviewFrame, animationPreviewOptionsTable, 5, -25, 10, true, options_text_template, options_dropdown_template, options_switch_template, true, options_slider_template, options_button_template, animationFrame.OnDataChange)
animationFrame.DisableOptions()
selectSpellLabel:SetPoint ("topleft", animationFrame, "topleft", startX, startY)
effectSelectionLabel:SetPoint ("bottomleft", animationConfigFrame, "topleft", 0, 8)
addShakeButton:SetPoint ("left", effectSelectionDropdown, "right", 2, 0)
importStringField:SetPoint ("topleft", animationSelectScrollBox, "topright", 45, 53 + 70)
animationFrame.RefreshAddAnimationButtons()
animationFrame.BuildAnimationDataForScroll()
end
-- endd doo thend thens ends elses