Framework Update
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
|
||||
--[=[
|
||||
for this example, let's consider the name of your addon is "Slice And Dance"
|
||||
addon folder name on World of Warcraft/_retail_/Interface/AddOns/SliceAndDance/
|
||||
toc file example /World of Warcraft/_retail_/Interface/AddOns/SliceAndDance/SliceAndDance.toc:
|
||||
## Interface: 100107
|
||||
## Title: "Slice And Dance"
|
||||
## Notes: Show a slice and dice bar for rogues
|
||||
## SavedVariables: SliceAndDanceDatabase
|
||||
SliceAndDance_Core.lua
|
||||
--]=]
|
||||
|
||||
--create a new file on your addon folder called "SliceAndDance_Core.lua"
|
||||
--this are the contents to add to the file
|
||||
|
||||
--each file of your addon receives a payload with the addon name and a private table
|
||||
--this private table is shared between all files of your addon and cannot be accessed by other addons or scripts
|
||||
--the addon name is the ToC name of your addon, the toc is also the folder name of your addon in the addons folder
|
||||
local addonName, priviteTable = ...
|
||||
|
||||
--saved variables name
|
||||
--this is the name of the global table where your addon will store it's saved variables
|
||||
--you define this on the addon.toc file under the line "## SavedVariables: SliceAndDanceDatabase"
|
||||
local savedVariablesName = "SliceAndDanceDatabase"
|
||||
|
||||
--default settings
|
||||
--a simple table with default settings for your addon, any value modified by the user will be stored in the saved variables table
|
||||
--if your addon doesn't have any settings, you can just pass an empty table
|
||||
local defaultSettingsExample = {
|
||||
width = 500,
|
||||
height = 500,
|
||||
name = "John",
|
||||
}
|
||||
|
||||
local detailsFramework = DetailsFramework
|
||||
--create the core addon object, this is a table which will all public functions of your addon
|
||||
local myNewAddonObject = detailsFramework:CreateNewAddOn(addonName, savedVariablesName, defaultSettingsExample)
|
||||
|
||||
--by default, the table generated by the CreateNewAddOn() isn't placed in the global environment
|
||||
--if this is desired for some reason, you can do it manually
|
||||
_G.MyNewAddon = myNewAddonObject
|
||||
|
||||
--this function is called when the savedVariables of your addon is ready to be used
|
||||
function myNewAddonObject.OnLoad(self, profile)
|
||||
--self is: myNewAddonObject
|
||||
--profile is a table with defaultSettingsExample
|
||||
end
|
||||
|
||||
--this function is called when when the loading screen is done and the player character is ready to play
|
||||
function myNewAddonObject.OnInit(self, profile) --fired from detailsFramework at PLAYER_LOGIN
|
||||
--self is: myNewAddonObject
|
||||
--profile is a table with defaultSettingsExample
|
||||
end
|
||||
+1
-1
@@ -119,7 +119,7 @@ function detailsFramework:CreateNewAddOn(addonName, globalSavedVariablesName, sa
|
||||
end
|
||||
|
||||
|
||||
--old create addon
|
||||
--old create addon using ace3
|
||||
function detailsFramework:CreateAddOn(name, global_saved, global_table, options_table, broker)
|
||||
|
||||
local addon = LibStub("AceAddon-3.0"):NewAddon (name, "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0", "DetailsFramework-1.0", "AceComm-3.0")
|
||||
|
||||
+488
-496
File diff suppressed because it is too large
Load Diff
+9
-4
@@ -382,6 +382,7 @@ detailsFramework:Mixin(ButtonMetaFunctions, detailsFramework.ScriptHookMixin)
|
||||
end
|
||||
|
||||
---add an icon to the left of the button text
|
||||
---short method truncates the text: false = do nothing, nil = increate the button width, 1 = decrease the font size, 2 = truncate the text
|
||||
---@param texture any
|
||||
---@param width number|nil
|
||||
---@param height number|nil
|
||||
@@ -464,6 +465,9 @@ detailsFramework:Mixin(ButtonMetaFunctions, detailsFramework.ScriptHookMixin)
|
||||
textSize = textSize - 1
|
||||
end
|
||||
end
|
||||
|
||||
elseif (shortMethod == 2) then
|
||||
detailsFramework:TruncateText(self.button.text, self:GetWidth() - self.icon:GetWidth() - 15)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -810,8 +814,8 @@ end
|
||||
--object constructor
|
||||
local onDisableFunc = function(self)
|
||||
self.texture_disabled:Show()
|
||||
self.texture_disabled:SetVertexColor(0, 0, 0)
|
||||
self.texture_disabled:SetAlpha(.5)
|
||||
self.texture_disabled:SetVertexColor(0.1, 0.1, 0.1)
|
||||
self.texture_disabled:SetAlpha(.834)
|
||||
end
|
||||
|
||||
local onEnableFunc = function(self)
|
||||
@@ -836,7 +840,7 @@ end
|
||||
self:SetScript("OnEnable", onEnableFunc)
|
||||
end
|
||||
|
||||
---@class df_button : button
|
||||
---@class df_button : button, df_scripthookmixin
|
||||
---@field widget button
|
||||
---@field tooltip string
|
||||
---@field shown boolean
|
||||
@@ -852,13 +856,14 @@ end
|
||||
---@field textcolor any
|
||||
---@field textfont string
|
||||
---@field textsize number
|
||||
---@field icon texture created after calling SetIcon()
|
||||
---@field SetTemplate fun(self: df_button, template: table) set the button visual by a template
|
||||
---@field RightClick fun(self: df_button) right click the button executing its right click function
|
||||
---@field Exec fun(self: df_button) execute the button function for the left button
|
||||
---@field Disable fun(self: df_button) disable the button
|
||||
---@field Enable fun(self: df_button) enable the button
|
||||
---@field IsEnabled fun(self: df_button) : boolean returns true if the button is enabled
|
||||
---@field SetIcon fun(self: df_button,texture: string, width: number|nil, height: number|nil, layout: string|nil, texcoord: table|nil, overlay: table|nil, textDistance: number|nil, leftPadding: number|nil, textHeight: number|nil, shortMethod: any|nil)
|
||||
---@field SetIcon fun(self: df_button,texture: string|number, width: number|nil, height: number|nil, layout: string|nil, texcoord: table|nil, overlay: table|nil, textDistance: number|nil, leftPadding: number|nil, textHeight: number|nil, shortMethod: any|nil)
|
||||
---@field GetIconTexture fun(self: df_button) : string returns the texture path of the button icon
|
||||
---@field SetTexture fun(self: df_button, normalTexture: string, highlightTexture: string, pressedTexture: string, disabledTexture: string) set the regular button textures
|
||||
---@field SetFontFace fun(self: df_button, font: string) set the button font
|
||||
|
||||
+7
-8
@@ -1,13 +1,12 @@
|
||||
do
|
||||
|
||||
do
|
||||
local DF = _G ["DetailsFramework"]
|
||||
|
||||
if (not DF or not DetailsFrameworkCanLoad) then
|
||||
return
|
||||
return
|
||||
end
|
||||
|
||||
DF.alias_text_colors = DF.alias_text_colors or {}
|
||||
|
||||
|
||||
local defaultColors = {
|
||||
["HUNTER"] = {0.67, 0.83, 0.45},
|
||||
["WARLOCK"] = {0.58, 0.51, 0.79},
|
||||
@@ -172,13 +171,13 @@ do
|
||||
["yellow"] = {1, 1, 0, 1},
|
||||
["yellowgreen"] = {0.603922, 0.803922, 0.196078, 1}
|
||||
}
|
||||
|
||||
|
||||
function DF:GetDefaultColorList()
|
||||
return defaultColors
|
||||
end
|
||||
|
||||
|
||||
for colorName, colorTable in pairs(defaultColors) do
|
||||
DF.alias_text_colors [colorName] = colorTable
|
||||
DF.alias_text_colors[colorName] = colorTable
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
+17
-2
@@ -23,9 +23,14 @@
|
||||
---@field RoundedCornerPanelMixin df_roundedcornermixin
|
||||
---@field Schedules df_schedule
|
||||
---@field HeaderFunctions df_headerfunctions
|
||||
---@field KeybindMixin df_keybindmixin
|
||||
---@field Math df_math
|
||||
---@field table df_table_functions
|
||||
---@field IsValidSpecId fun(self:table, specId:number):boolean check if the passed specId is valid for the player class, also return false for tutorial specs
|
||||
---@field DebugVisibility fun(self:table, object:uiobject) print the reason why the frame isn't shown in the screen
|
||||
---@field Dispatch fun(self:table, callback:function, ...) : any dispatch a function call using xpcall
|
||||
---@field QuickDispatch fun(self:table, callback:function, ...) : any dispatch a function call without errors if the function passed is invalid
|
||||
---@field CoreDispatch fun(self:table, context:string, callback:function, ...) : any deprecated at this point, use Dispatch instead
|
||||
---@field GetDefaultBackdropColor fun(self:table) : red, green, blue, alpha return the standard backdrop color used by blizzard on their own frames
|
||||
---@field Msg fun(self:table, message:string, ...) show a message in the chat frame
|
||||
---@field MsgWarning fun(self:table, message:string, ...) show a warning message in the chat frame
|
||||
@@ -64,7 +69,17 @@
|
||||
---@field NewColor fun(self:table, colorName:string, red:number, green:number, blue:number, alpha:number)
|
||||
---@field CreateKeybindFrame fun(self:table, parent:frame, name:string?, options:table?, setKeybindCallback:function?, keybindData:table?) : df_keybindframe
|
||||
---@field CreateStatusBar fun(self:table, parent:frame, options:table?) : frame
|
||||
---@field CreateScrollBox fun(self:table, parent:frame, name:string, refreshFunc:function, data:table, width:number, height:number, lineAmount:number, lineHeight:number, createLineFunc:function?, autoAmount:boolean?, noScroll:boolean?) : df_scrollbox
|
||||
---@field CreateScrollBox fun(self:table, parent:frame, name:string, refreshFunc:function, data:table, width:number, height:number, lineAmount:number, lineHeight:number, createLineFunc:function?, autoAmount:boolean?, noScroll:boolean?, noBackdrop:boolean?) : df_scrollbox
|
||||
---@field GetTemplate fun(self:table, templateType:templatetype, templateName:string) : table
|
||||
---@field UpdateLoadConditionsTable fun(self:table, loadConditionsTable:table)
|
||||
---@field IconPick fun(self:table, callback:function, bCloseWhenSelect:boolean?, param1:any?, param2:any?)
|
||||
---@field OpenLoadConditionsPanel fun(self:table, optionsTable:table, callback:function, frameOptions:table?)
|
||||
---@field InstallTemplate fun(self:table, widgetType:string, templateName:string, template:table, parentName:any) : table
|
||||
---@field NewSpecialLuaEditorEntry fun(self:table, parent:frame, width:number, height:number, member:string?, name:string?, nointent:boolean?, showLineNumbers:boolean?, bNoName:boolean?) : df_luaeditor
|
||||
---@field PassLoadFilters fun(self:table, loadTable:table, encounterID:number?) : boolean, string
|
||||
---@field CreateLoadFilterParser fun(self:table, callback:fun(encounterId:number?)) create a helper which will callback when encounterId, spec, talent, role, combatstate changes
|
||||
---@field CreateSwitch fun(self:table, parent:frame, onSwitch:function, defaultValue:boolean, width:number?, height:number?, leftText:string?, rightText:string?, member:string?, name:string?, colorInverted:boolean?, switchFunc:function?, returnFunc:function?, withLabel:string?, switch_template:table?, label_template:table?) : df_checkbox, df_label?
|
||||
---@field CreateCheckboxGroup fun(self:table, parent:frame, radioOptions:df_radiooptions[], name:string?, options:table?, anchorOptions:table?) : df_checkboxgroup
|
||||
---@field CreateRadioGroup fun(self:table, parent:frame, radioOptions:df_radiooptions[], name:string?, options:table?, anchorOptions:table?) : df_radiogroup
|
||||
---@field
|
||||
---@field
|
||||
|
||||
|
||||
@@ -1334,7 +1334,7 @@ function DF:CreateNewDropdownFrame(parent, name)
|
||||
child.mouseover = mouseover
|
||||
|
||||
scroll:SetScrollChild(child)
|
||||
tinsert(UISpecialFrames, newDropdownFrame.dropdownborder:GetName())
|
||||
table.insert(UISpecialFrames, newDropdownFrame.dropdownborder:GetName())
|
||||
--tinsert(UISpecialFrames, f.dropdownframe:GetName()) --not adding this solves an issue with ConsolePort addon and stackoverflows on Hide...
|
||||
|
||||
return newDropdownFrame
|
||||
|
||||
+148
-21
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||
local dversion = 470
|
||||
local dversion = 474
|
||||
local major, minor = "DetailsFramework-1.0", dversion
|
||||
local DF, oldminor = LibStub:NewLibrary(major, minor)
|
||||
|
||||
@@ -19,7 +19,7 @@ local type = type
|
||||
local unpack = unpack
|
||||
local upper = string.upper
|
||||
local string_match = string.match
|
||||
local tinsert = _G.tinsert
|
||||
local tinsert = table.insert
|
||||
local abs = _G.abs
|
||||
local tremove = _G.tremove
|
||||
|
||||
@@ -1434,6 +1434,45 @@ function DF:GetSpellBookSpells()
|
||||
return spellNamesInSpellBook, spellIdsInSpellBook
|
||||
end
|
||||
|
||||
---return a table of passive talents, format: [spellId] = true
|
||||
---@return {Name: string, ID: number, Texture: any, IsSelected: boolean}[]
|
||||
function DF:GetAllTalents()
|
||||
local allTalents = {}
|
||||
|
||||
local configId = C_ClassTalents.GetActiveConfigID()
|
||||
if (configId) then
|
||||
local configInfo = C_Traits.GetConfigInfo(configId)
|
||||
--get the spells from the SPEC from talents
|
||||
for treeIndex, treeId in ipairs(configInfo.treeIDs) do
|
||||
local treeNodes = C_Traits.GetTreeNodes(treeId)
|
||||
for nodeIdIndex, treeNodeID in ipairs(treeNodes) do
|
||||
local traitNodeInfo = C_Traits.GetNodeInfo(configId, treeNodeID)
|
||||
if (traitNodeInfo) then
|
||||
local activeEntry = traitNodeInfo.activeEntry
|
||||
local entryIds = traitNodeInfo.entryIDs
|
||||
for i = 1, #entryIds do
|
||||
local entryId = entryIds[i] --number
|
||||
local traitEntryInfo = C_Traits.GetEntryInfo(configId, entryId)
|
||||
local borderTypes = Enum.TraitNodeEntryType
|
||||
if (traitEntryInfo.type) then -- == borderTypes.SpendCircle
|
||||
local definitionId = traitEntryInfo.definitionID
|
||||
local traitDefinitionInfo = C_Traits.GetDefinitionInfo(definitionId)
|
||||
local spellId = traitDefinitionInfo.overriddenSpellID or traitDefinitionInfo.spellID
|
||||
local spellName, _, spellTexture = GetSpellInfo(spellId)
|
||||
if (spellName) then
|
||||
local talentInfo = {Name = spellName, ID = spellId, Texture = spellTexture, IsSelected = (activeEntry and activeEntry.rank and activeEntry.rank > 0) or false}
|
||||
allTalents[#allTalents+1] = talentInfo
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return allTalents
|
||||
end
|
||||
|
||||
---return a table where keys are spellIds (number) and the value is true
|
||||
---@return table<number, boolean>
|
||||
function DF:GetAvailableSpells()
|
||||
@@ -1528,7 +1567,7 @@ function DF:GetAvailableSpells()
|
||||
return HasPetSpells()
|
||||
end
|
||||
|
||||
--get pet spells from the pet spellbook
|
||||
--get pet spells from the pet spellbook
|
||||
local numPetSpells = getNumPetSpells()
|
||||
if (numPetSpells) then
|
||||
for i = 1, numPetSpells do
|
||||
@@ -1772,7 +1811,7 @@ end
|
||||
--add a new color name, the color can be query using DetailsFramework:ParseColors(colorName)
|
||||
function DF:NewColor(colorName, red, green, blue, alpha)
|
||||
assert(type(colorName) == "string", "DetailsFramework:NewColor(): colorName must be a string.")
|
||||
assert(not DF.alias_text_colors[colorName], "DetailsFramework:NewColor(): colorName already exists.")
|
||||
--assert(not DF.alias_text_colors[colorName], "DetailsFramework:NewColor(): colorName already exists.")
|
||||
|
||||
red, green, blue, alpha = DetailsFramework:ParseColors(red, green, blue, alpha)
|
||||
local colorTable = DetailsFramework:FormatColor("table", red, green, blue, alpha)
|
||||
@@ -3475,6 +3514,12 @@ DF.button_templates["OPTIONS_BUTTON_TEMPLATE"] = {
|
||||
backdropbordercolor = {0, 0, 0, 1},
|
||||
}
|
||||
|
||||
DF.button_templates["OPTIONS_BUTTON_GOLDENBORDER_TEMPLATE"] = {
|
||||
backdrop = {edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true},
|
||||
backdropcolor = {1, 1, 1, .5},
|
||||
backdropbordercolor = {1, 0.785, 0, 1},
|
||||
}
|
||||
|
||||
--sliders
|
||||
DF.slider_templates = DF.slider_templates or {}
|
||||
DF.slider_templates["OPTIONS_SLIDER_TEMPLATE"] = {
|
||||
@@ -3489,6 +3534,12 @@ DF.slider_templates["OPTIONS_SLIDER_TEMPLATE"] = {
|
||||
thumbcolor = {0, 0, 0, 0.5},
|
||||
}
|
||||
|
||||
---install a template
|
||||
---@param widgetType string
|
||||
---@param templateName string
|
||||
---@param template table
|
||||
---@param parentName any
|
||||
---@return table
|
||||
function DF:InstallTemplate(widgetType, templateName, template, parentName)
|
||||
local newTemplate = {}
|
||||
|
||||
@@ -4986,13 +5037,13 @@ function DF:GetCharacterRaceList()
|
||||
end
|
||||
|
||||
for i = 1, 100 do
|
||||
local raceInfo = C_CreatureInfo.GetRaceInfo (i)
|
||||
local raceInfo = C_CreatureInfo.GetRaceInfo(i)
|
||||
if (raceInfo and DF.RaceList [raceInfo.raceID]) then
|
||||
tinsert(DF.RaceCache, {Name = raceInfo.raceName, FileString = raceInfo.clientFileString, ID = raceInfo.raceID})
|
||||
end
|
||||
|
||||
if IS_WOW_PROJECT_MAINLINE then
|
||||
local alliedRaceInfo = C_AlliedRaces.GetRaceInfoByID (i)
|
||||
local alliedRaceInfo = C_AlliedRaces.GetRaceInfoByID(i)
|
||||
if (alliedRaceInfo and DF.AlliedRaceList [alliedRaceInfo.raceID]) then
|
||||
tinsert(DF.RaceCache, {Name = alliedRaceInfo.maleName, FileString = alliedRaceInfo.raceFileString, ID = alliedRaceInfo.raceID})
|
||||
end
|
||||
@@ -5005,24 +5056,72 @@ end
|
||||
--get a list of talents for the current spec the player is using
|
||||
--if onlySelected return an index table with only the talents the character has selected
|
||||
--if onlySelectedHash return a hash table with [spelID] = true
|
||||
function DF:GetCharacterTalents (onlySelected, onlySelectedHash)
|
||||
function DF:GetCharacterTalents(bOnlySelected, bOnlySelectedHash)
|
||||
local talentList = {}
|
||||
local version, build, date, tocversion = GetBuildInfo()
|
||||
|
||||
for i = 1, 7 do
|
||||
for o = 1, 3 do
|
||||
local talentID, name, texture, selected, available = GetTalentInfo (i, o, 1)
|
||||
if (onlySelectedHash) then
|
||||
if (selected) then
|
||||
talentList [talentID] = true
|
||||
break
|
||||
if (tocversion >= 70000 and tocversion <= 99999) then
|
||||
for i = 1, 7 do
|
||||
for o = 1, 3 do
|
||||
local talentID, name, texture, selected, available = GetTalentInfo(i, o, 1)
|
||||
if (bOnlySelectedHash) then
|
||||
if (selected) then
|
||||
talentList[talentID] = true
|
||||
break
|
||||
end
|
||||
elseif (bOnlySelected) then
|
||||
if (selected) then
|
||||
table.insert(talentList, {Name = name, ID = talentID, Texture = texture, IsSelected = selected})
|
||||
break
|
||||
end
|
||||
else
|
||||
table.insert(talentList, {Name = name, ID = talentID, Texture = texture, IsSelected = selected})
|
||||
end
|
||||
elseif (onlySelected) then
|
||||
if (selected) then
|
||||
tinsert(talentList, {Name = name, ID = talentID, Texture = texture, IsSelected = selected})
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
elseif (tocversion >= 100000) then
|
||||
if (not bOnlySelected) then
|
||||
return DF:GetAllTalents()
|
||||
end
|
||||
|
||||
local configId = C_ClassTalents.GetActiveConfigID()
|
||||
if (configId) then
|
||||
local configInfo = C_Traits.GetConfigInfo(configId)
|
||||
--get the spells from the SPEC from talents
|
||||
for treeIndex, treeId in ipairs(configInfo.treeIDs) do
|
||||
local treeNodes = C_Traits.GetTreeNodes(treeId)
|
||||
|
||||
for nodeIdIndex, treeNodeID in ipairs(treeNodes) do
|
||||
local traitNodeInfo = C_Traits.GetNodeInfo(configId, treeNodeID)
|
||||
|
||||
if (traitNodeInfo) then
|
||||
local activeEntry = traitNodeInfo.activeEntry
|
||||
local entryIds = traitNodeInfo.entryIDs
|
||||
|
||||
for i = 1, #entryIds do
|
||||
local entryId = entryIds[i] --number
|
||||
local traitEntryInfo = C_Traits.GetEntryInfo(configId, entryId)
|
||||
local borderTypes = Enum.TraitNodeEntryType
|
||||
|
||||
if (traitEntryInfo.type) then -- == borderTypes.SpendCircle
|
||||
local definitionId = traitEntryInfo.definitionID
|
||||
local traitDefinitionInfo = C_Traits.GetDefinitionInfo(definitionId)
|
||||
local spellId = traitDefinitionInfo.overriddenSpellID or traitDefinitionInfo.spellID
|
||||
local spellName, _, spellTexture = GetSpellInfo(spellId)
|
||||
local bIsSelected = (activeEntry and activeEntry.rank and activeEntry.rank > 0) or false
|
||||
if (spellName and bIsSelected) then
|
||||
local talentInfo = {Name = spellName, ID = spellId, Texture = spellTexture, IsSelected = true}
|
||||
if (bOnlySelectedHash) then
|
||||
talentList[spellId] = talentInfo
|
||||
else
|
||||
table.insert(talentList, talentInfo)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
tinsert(talentList, {Name = name, ID = talentID, Texture = texture, IsSelected = selected})
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -5030,7 +5129,7 @@ function DF:GetCharacterTalents (onlySelected, onlySelectedHash)
|
||||
return talentList
|
||||
end
|
||||
|
||||
function DF:GetCharacterPvPTalents (onlySelected, onlySelectedHash)
|
||||
function DF:GetCharacterPvPTalents(onlySelected, onlySelectedHash)
|
||||
if (onlySelected or onlySelectedHash) then
|
||||
local talentsSelected = C_SpecializationInfo.GetAllSelectedPvpTalentIDs()
|
||||
local talentList = {}
|
||||
@@ -5294,6 +5393,15 @@ DF.SpecListByClass = {
|
||||
},
|
||||
}
|
||||
|
||||
---return if the specId is a valid spec, it'll return false for specIds from the tutorial area
|
||||
---@param self table
|
||||
---@param specId number
|
||||
function DF:IsValidSpecId(specId)
|
||||
local _, class = UnitClass("player")
|
||||
local specs = DF.SpecListByClass[class]
|
||||
return specs and specs[specId] and true or false
|
||||
end
|
||||
|
||||
--given a class and a specId, return if the specId is a spec from the class passed
|
||||
function DF:IsSpecFromClass(class, specId)
|
||||
return DF.ClassSpecs[class] and DF.ClassSpecs[class][specId]
|
||||
@@ -5808,4 +5916,23 @@ function DF:DebugVisibility(UIObject)
|
||||
|
||||
local numPoints = UIObject:GetNumPoints()
|
||||
print("Num Points:", numPoints > 0 and "|cFF00FF00" .. numPoints .. "|r" or "|cFFFF00000|r")
|
||||
end
|
||||
|
||||
local beenchmarkTime = 0
|
||||
local beenchmarkEnabled = false
|
||||
function _G.__benchmark(bNotPrintResult)
|
||||
if (not beenchmarkEnabled) then
|
||||
beenchmarkEnabled = true
|
||||
beenchmarkTime = debugprofilestop()
|
||||
else
|
||||
local elapsed = debugprofilestop() - beenchmarkTime
|
||||
beenchmarkEnabled = false
|
||||
|
||||
if (bNotPrintResult) then
|
||||
return elapsed
|
||||
end
|
||||
|
||||
print("Elapsed Time:", elapsed)
|
||||
return elapsed
|
||||
end
|
||||
end
|
||||
+3
-2
@@ -638,8 +638,8 @@ local default_header_options = {
|
||||
---each column is placed on the right side of the previous column.
|
||||
---@param parent frame
|
||||
---@param headerTable table
|
||||
---@param options table|nil
|
||||
---@param frameName string|nil
|
||||
---@param options table?
|
||||
---@param frameName string?
|
||||
---@return df_headerframe
|
||||
function detailsFramework:CreateHeader(parent, headerTable, options, frameName)
|
||||
---create the header frame which is returned by this function
|
||||
@@ -649,6 +649,7 @@ function detailsFramework:CreateHeader(parent, headerTable, options, frameName)
|
||||
detailsFramework:Mixin(newHeader, detailsFramework.OptionsFunctions)
|
||||
detailsFramework:Mixin(newHeader, detailsFramework.HeaderMixin)
|
||||
|
||||
options = options or {}
|
||||
newHeader:BuildOptionsTable(default_header_options, options)
|
||||
|
||||
--set the backdrop and backdrop color following the values in the options table
|
||||
|
||||
+1101
-460
File diff suppressed because it is too large
Load Diff
+3
-1
@@ -23,7 +23,7 @@
|
||||
<Script file="charts.lua"/>
|
||||
<Script file="scripting.lua"/>
|
||||
<Script file="externals.lua"/>
|
||||
<Script file="frames.lua"/>
|
||||
<Script file="rounded_panel.lua"/>
|
||||
|
||||
<Include file="tutorial_alert.xml"/>
|
||||
<Include file="split_bar.xml"/>
|
||||
@@ -32,8 +32,10 @@
|
||||
<Include file="cooltip.xml"/>
|
||||
<Include file="dropdown.xml"/>
|
||||
<Include file="normal_bar.xml"/>
|
||||
<Script file="scrollbox.lua"/>
|
||||
<Include file="panel.xml"/>
|
||||
|
||||
<Script file="loadconditions.lua"/>
|
||||
<Include file="unitframe.lua"/>
|
||||
<Script file="icon.lua"/>
|
||||
<Script file="icongeneric.lua"/>
|
||||
|
||||
@@ -0,0 +1,869 @@
|
||||
|
||||
local detailsFramework = _G ["DetailsFramework"]
|
||||
if (not detailsFramework or not DetailsFrameworkCanLoad) then
|
||||
return
|
||||
end
|
||||
|
||||
local _
|
||||
--lua locals
|
||||
local rawset = rawset
|
||||
local rawget = rawget
|
||||
local setmetatable = setmetatable
|
||||
local unpack = unpack ---@diagnostic disable-line
|
||||
local type = type
|
||||
local floor = math.floor
|
||||
local loadstring = loadstring ---@diagnostic disable-line
|
||||
local CreateFrame = CreateFrame ---@diagnostic disable-line
|
||||
local UnitIsUnit = UnitIsUnit ---@diagnostic disable-line
|
||||
local UnitClass = UnitClass ---@diagnostic disable-line
|
||||
local GetInstanceInfo = GetInstanceInfo ---@diagnostic disable-line
|
||||
local C_ChallengeMode = C_ChallengeMode ---@diagnostic disable-line
|
||||
local C_Map = C_Map ---@diagnostic disable-line
|
||||
local GetTalentInfoByID = GetTalentInfoByID ---@diagnostic disable-line
|
||||
|
||||
local IS_WOW_PROJECT_MAINLINE = WOW_PROJECT_ID == WOW_PROJECT_MAINLINE ---@diagnostic disable-line
|
||||
local IS_WOW_PROJECT_NOT_MAINLINE = WOW_PROJECT_ID ~= WOW_PROJECT_MAINLINE ---@diagnostic disable-line
|
||||
local IS_WOW_PROJECT_CLASSIC_ERA = WOW_PROJECT_ID == WOW_PROJECT_CLASSIC ---@diagnostic disable-line
|
||||
|
||||
local PixelUtil = PixelUtil or DFPixelUtil ---@diagnostic disable-line
|
||||
local UnitGroupRolesAssigned = detailsFramework.UnitGroupRolesAssigned
|
||||
local loadConditionsFrame
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
--load conditions panel
|
||||
|
||||
--this is the table prototype to hold load conditions settings
|
||||
local default_load_conditions = {
|
||||
class = {},
|
||||
spec = {},
|
||||
race = {},
|
||||
talent = {},
|
||||
pvptalent = {},
|
||||
group = {},
|
||||
role = {},
|
||||
affix = {},
|
||||
encounter_ids = {},
|
||||
map_ids = {},
|
||||
}
|
||||
|
||||
--[=[
|
||||
Skittish 135994 2
|
||||
Volcanic 451169 3
|
||||
Necrotic 1029009 4
|
||||
Teeming 136054 5
|
||||
Raging 132345 6
|
||||
Bolstering 132333 7
|
||||
Sanguine 136124 8
|
||||
Tyrannical 236401 9
|
||||
Fortified 463829 10
|
||||
Bursting 1035055 11
|
||||
Grievous 132090 12
|
||||
Explosive 2175503 13
|
||||
Quaking 136025 14
|
||||
Infested 2032223 16
|
||||
Reaping 2446016 117
|
||||
Beguiling 237565 119
|
||||
Awakened 442737 120
|
||||
Prideful 3528307 121
|
||||
Inspiring 135946 122
|
||||
Spiteful 135945 123
|
||||
Storming 136018 124
|
||||
Tormented 3528304 128
|
||||
Infernal 1394959 129
|
||||
Encrypted 4038106 130
|
||||
Shrouded 136177 131
|
||||
Thundering 1385910 132
|
||||
[PH] 0 133
|
||||
Entangling 134412 134
|
||||
Afflicted 237555 135
|
||||
Incorporeal 298642 136
|
||||
Shielding 535593 137
|
||||
--]=]
|
||||
|
||||
local deprecatedAffixes = {
|
||||
[2] = true, --Skittish
|
||||
[5] = true, --Teeming
|
||||
[16] = true, --Infested
|
||||
[117] = true, --Reaping
|
||||
[119] = true, --Beguiling
|
||||
[13] = true, --Explosive
|
||||
[14] = true, --Quaking
|
||||
[120] = true, --Awakened
|
||||
[121] = true, --Prideful
|
||||
[130] = true, --Encrypted
|
||||
}
|
||||
|
||||
local default_load_conditions_frame_options = {
|
||||
title = "Details! Framework: Load Conditions",
|
||||
name = "Object",
|
||||
}
|
||||
|
||||
function detailsFramework:CreateLoadFilterParser(callback)
|
||||
local filterFrame = CreateFrame("frame")
|
||||
filterFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
|
||||
if IS_WOW_PROJECT_MAINLINE then
|
||||
filterFrame:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED")
|
||||
filterFrame:RegisterEvent("PLAYER_TALENT_UPDATE")
|
||||
end
|
||||
|
||||
filterFrame:RegisterEvent("PLAYER_ROLES_ASSIGNED")
|
||||
filterFrame:RegisterEvent("ZONE_CHANGED_NEW_AREA")
|
||||
|
||||
if IS_WOW_PROJECT_MAINLINE then
|
||||
filterFrame:RegisterEvent("CHALLENGE_MODE_START")
|
||||
end
|
||||
|
||||
filterFrame:RegisterEvent("ENCOUNTER_START")
|
||||
filterFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
|
||||
filterFrame:RegisterEvent("PLAYER_REGEN_DISABLED")
|
||||
|
||||
filterFrame:SetScript("OnEvent", function(self, event, ...)
|
||||
if (event == "ENCOUNTER_START") then --triggers before regen_disabled
|
||||
local encounterID = ...
|
||||
filterFrame.EncounterIDCached = encounterID
|
||||
|
||||
elseif (event == "PLAYER_REGEN_DISABLED") then
|
||||
|
||||
elseif (event == "ENCOUNTER_END") then
|
||||
filterFrame.EncounterIDCached = nil
|
||||
|
||||
elseif (event == "PLAYER_REGEN_ENABLED") then
|
||||
--f.EncounterIDCached = nil
|
||||
--when the player dies during an encounter, the game is triggering regen enabled
|
||||
|
||||
elseif (event == "PLAYER_SPECIALIZATION_CHANGED") then
|
||||
if (loadConditionsFrame and loadConditionsFrame:IsShown()) then
|
||||
loadConditionsFrame:Refresh()
|
||||
end
|
||||
|
||||
local unit = ...
|
||||
if (not unit or not UnitIsUnit("player", unit)) then
|
||||
return
|
||||
end
|
||||
|
||||
elseif (event == "PLAYER_ROLES_ASSIGNED") then
|
||||
local assignedRole = UnitGroupRolesAssigned("player")
|
||||
if (assignedRole == "NONE") then
|
||||
local spec = DetailsFramework.GetSpecialization()
|
||||
if (spec) then
|
||||
assignedRole = DetailsFramework.GetSpecializationRole(spec)
|
||||
end
|
||||
end
|
||||
|
||||
if (detailsFramework.CurrentPlayerRole == assignedRole) then
|
||||
return
|
||||
end
|
||||
|
||||
detailsFramework.CurrentPlayerRole = assignedRole
|
||||
end
|
||||
|
||||
detailsFramework:QuickDispatch(callback, filterFrame.EncounterIDCached)
|
||||
end)
|
||||
end
|
||||
|
||||
function detailsFramework:PassLoadFilters(loadTable, encounterID)
|
||||
--class
|
||||
local passLoadClass
|
||||
if (loadTable.class.Enabled) then
|
||||
local _, classFileName = UnitClass("player")
|
||||
if (not loadTable.class[classFileName]) then
|
||||
return false, _G["CLASS"]
|
||||
else
|
||||
passLoadClass = true
|
||||
end
|
||||
end
|
||||
|
||||
--spec
|
||||
if (IS_WOW_PROJECT_MAINLINE and loadTable.spec.Enabled) then
|
||||
local canCheckTalents = true
|
||||
|
||||
if (passLoadClass) then
|
||||
--if is allowed to load on this class, check if the talents isn't from another class
|
||||
local _, classFileName = UnitClass("player")
|
||||
local specsForThisClass = detailsFramework:GetClassSpecIDs(classFileName)
|
||||
|
||||
canCheckTalents = false
|
||||
|
||||
for _, specID in ipairs(specsForThisClass) do
|
||||
if (loadTable.spec[specID] or loadTable.spec[specID..""]) then
|
||||
--theres a talent for this class
|
||||
canCheckTalents = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (canCheckTalents) then
|
||||
local specIndex = DetailsFramework.GetSpecialization()
|
||||
if (specIndex) then
|
||||
local specID = DetailsFramework.GetSpecializationInfo(specIndex)
|
||||
if not specID or(not loadTable.spec[specID] and not loadTable.spec[specID .. ""]) then
|
||||
return false, _G["SPECIALIZATION"]
|
||||
end
|
||||
else
|
||||
return false, _G["SPECIALIZATION"]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--race
|
||||
if (loadTable.race.Enabled) then
|
||||
local raceName, raceFileName, raceID = UnitRace("player")
|
||||
if (not loadTable.race [raceFileName]) then
|
||||
return false, _G["RACE"]
|
||||
end
|
||||
end
|
||||
|
||||
--talents
|
||||
if (IS_WOW_PROJECT_MAINLINE and loadTable.talent.Enabled) then
|
||||
local bOnlySelected, bUseHashTable = true, true
|
||||
local talentsInUse = detailsFramework:GetCharacterTalents(bOnlySelected, bUseHashTable)
|
||||
|
||||
local hasTalent
|
||||
|
||||
for talentId in pairs(talentsInUse) do
|
||||
if talentId and(loadTable.talent[talentId] or loadTable.talent[talentId .. ""]) then
|
||||
hasTalent = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if (not hasTalent) then
|
||||
return false, _G["TALENTS"]
|
||||
end
|
||||
end
|
||||
|
||||
--pvptalent
|
||||
if (IS_WOW_PROJECT_MAINLINE and loadTable.pvptalent.Enabled) then
|
||||
local talentsInUse = detailsFramework:GetCharacterPvPTalents(false, true)
|
||||
local hasTalent
|
||||
for talentID, _ in pairs(talentsInUse) do
|
||||
if talentID and(loadTable.pvptalent [talentID] or loadTable.pvptalent [talentID .. ""]) then
|
||||
hasTalent = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if (not hasTalent) then
|
||||
return false, (_G["PVP"] or "") .. " " .. (_G["TALENTS"] or "")
|
||||
end
|
||||
end
|
||||
|
||||
--group
|
||||
if (loadTable.group.Enabled) then
|
||||
local _, zoneType = GetInstanceInfo()
|
||||
if (not loadTable.group[zoneType]) then
|
||||
return false, _G["GROUP"]
|
||||
end
|
||||
end
|
||||
|
||||
--role
|
||||
if (loadTable.role.Enabled) then
|
||||
local assignedRole = UnitGroupRolesAssigned("player")
|
||||
if (assignedRole == "NONE") then
|
||||
local spec = DetailsFramework.GetSpecialization()
|
||||
if (spec) then
|
||||
assignedRole = DetailsFramework.GetSpecializationRole(spec)
|
||||
end
|
||||
end
|
||||
if (not loadTable.role [assignedRole]) then
|
||||
return false, _G["ROLE"]
|
||||
end
|
||||
end
|
||||
|
||||
--affix
|
||||
if (IS_WOW_PROJECT_MAINLINE and loadTable.affix.Enabled) then
|
||||
local isInMythicDungeon = C_ChallengeMode.IsChallengeModeActive()
|
||||
if (not isInMythicDungeon) then
|
||||
return false, "M+ Affix"
|
||||
end
|
||||
|
||||
local level, affixes, wasEnergized = C_ChallengeMode.GetActiveKeystoneInfo()
|
||||
local hasAffix = false
|
||||
for _, affixID in ipairs(affixes) do
|
||||
if affixID and(loadTable.affix[affixID] or loadTable.affix[affixID .. ""]) then
|
||||
hasAffix = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if (not hasAffix) then
|
||||
return false, "M+ Affix"
|
||||
end
|
||||
end
|
||||
|
||||
--encounter id
|
||||
if (loadTable.encounter_ids.Enabled) then
|
||||
if (not encounterID) then
|
||||
return
|
||||
end
|
||||
|
||||
local bHasEncounter
|
||||
for _, userEnteredEncounterId in pairs(loadTable.encounter_ids) do
|
||||
if (userEnteredEncounterId == encounterID) then
|
||||
bHasEncounter = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if (not bHasEncounter) then
|
||||
return false, _G["GUILD_NEWS_FILTER3"] --"raid encounters"
|
||||
end
|
||||
end
|
||||
|
||||
--map id
|
||||
if (loadTable.map_ids.Enabled) then
|
||||
local _, _, _, _, _, _, _, zoneMapID = GetInstanceInfo()
|
||||
local uiMapID = C_Map.GetBestMapForUnit("player")
|
||||
local bHasMapID = false
|
||||
|
||||
for _, userEnteredMapId in pairs(loadTable.map_ids) do
|
||||
if (userEnteredMapId == zoneMapID or userEnteredMapId == uiMapID) then
|
||||
bHasMapID = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if (not bHasMapID) then
|
||||
return false, _G["BATTLEFIELD_MINIMAP"] --"zone map"
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--this func will deploy the default values from the prototype into the config table
|
||||
function detailsFramework:UpdateLoadConditionsTable(configTable)
|
||||
configTable = configTable or {}
|
||||
detailsFramework.table.deploy(configTable, default_load_conditions)
|
||||
return configTable
|
||||
end
|
||||
|
||||
--/run Plater.OpenOptionsPanel()PlaterOptionsPanelContainer:SelectIndex(Plater, 14)
|
||||
|
||||
function detailsFramework:OpenLoadConditionsPanel(optionsTable, callback, frameOptions)
|
||||
frameOptions = frameOptions or {}
|
||||
detailsFramework.table.deploy(frameOptions, default_load_conditions_frame_options)
|
||||
|
||||
detailsFramework:UpdateLoadConditionsTable(optionsTable)
|
||||
|
||||
if (not loadConditionsFrame) then
|
||||
loadConditionsFrame = detailsFramework:CreateSimplePanel(UIParent, 1024, 600, "Load Conditions", "loadConditionsFrame")
|
||||
loadConditionsFrame:SetBackdropColor(0, 0, 0, 1)
|
||||
loadConditionsFrame.AllRadioGroups = {}
|
||||
loadConditionsFrame.AllTextEntries = {}
|
||||
loadConditionsFrame.OptionsTable = optionsTable
|
||||
|
||||
detailsFramework:ApplyStandardBackdrop(loadConditionsFrame, false, 1.1)
|
||||
|
||||
local xStartAt = 10
|
||||
local x2StartAt = 500
|
||||
local anchorPositions = {
|
||||
class = {xStartAt, -70},
|
||||
spec = {xStartAt, -200},
|
||||
race = {xStartAt, -250},
|
||||
role = {xStartAt, -380},
|
||||
talent = {xStartAt, -440},
|
||||
pvptalent = {x2StartAt, -70},
|
||||
group = {x2StartAt, -170},
|
||||
affix = {x2StartAt, -240},
|
||||
encounter_ids = {x2StartAt+1, -375},
|
||||
map_ids = {x2StartAt + 210, -375},
|
||||
}
|
||||
|
||||
local editingLabel = detailsFramework:CreateLabel(loadConditionsFrame, "Load Conditions For:")
|
||||
local editingWhatLabel = detailsFramework:CreateLabel(loadConditionsFrame, "")
|
||||
editingLabel:SetPoint("topleft", loadConditionsFrame, "topleft", 10, -35)
|
||||
editingWhatLabel:SetPoint("left", editingLabel, "right", 2, 0)
|
||||
|
||||
--this label store the name of what is being edited
|
||||
loadConditionsFrame.EditingLabel = editingWhatLabel
|
||||
|
||||
--when the user click on an option, run the callback
|
||||
loadConditionsFrame.RunCallback = function()
|
||||
detailsFramework:Dispatch(loadConditionsFrame.CallbackFunc)
|
||||
end
|
||||
|
||||
--when the user click on an option or when the panel is opened
|
||||
--check if there's an option enabled and fadein all options, fadeout otherwise
|
||||
loadConditionsFrame.OnRadioStateChanged = function(radioGroup, subConfigTable)
|
||||
subConfigTable.Enabled = nil
|
||||
subConfigTable.Enabled = next(subConfigTable) and true or nil
|
||||
radioGroup:SetFadeState(subConfigTable.Enabled)
|
||||
end
|
||||
|
||||
--create the radio group for character class
|
||||
loadConditionsFrame.OnRadioCheckboxClick = function(self, key, value)
|
||||
--hierarchy: DBKey ["class"] key ["HUNTER"] value TRUE
|
||||
local DBKey = self:GetParent().DBKey
|
||||
loadConditionsFrame.OptionsTable [DBKey] [key and key .. ""] = value and true or nil
|
||||
|
||||
if not value then -- cleanup "number" type values
|
||||
loadConditionsFrame.OptionsTable [DBKey] [key] = nil
|
||||
end
|
||||
|
||||
loadConditionsFrame.OnRadioStateChanged(self:GetParent(), loadConditionsFrame.OptionsTable [DBKey])
|
||||
loadConditionsFrame.RunCallback()
|
||||
end
|
||||
|
||||
--create the radio group for classes
|
||||
local classes = {}
|
||||
for _, classTable in pairs(detailsFramework:GetClassList()) do
|
||||
table.insert(classes, {
|
||||
name = classTable.Name,
|
||||
set = loadConditionsFrame.OnRadioCheckboxClick,
|
||||
param = classTable.FileString,
|
||||
get = function() return loadConditionsFrame.OptionsTable.class[classTable.FileString] end,
|
||||
texture = classTable.Texture,
|
||||
texcoord = classTable.TexCoord,
|
||||
})
|
||||
end
|
||||
|
||||
local classGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, classes, nil, {width = 430, height = 200, title = "Character Class", backdrop_color = {0, 0, 0, 0}}, {offset_x = 130, amount_per_line = 3})
|
||||
classGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.class[1], anchorPositions.class[2])
|
||||
classGroup.DBKey = "class"
|
||||
table.insert(loadConditionsFrame.AllRadioGroups, classGroup)
|
||||
|
||||
--create the radio group for character spec
|
||||
if IS_WOW_PROJECT_MAINLINE then
|
||||
local specs = {}
|
||||
for _, specID in ipairs(detailsFramework:GetClassSpecIDs(select(2, UnitClass("player")))) do
|
||||
local specID, specName, specDescription, specIcon, specBackground, specRole, specClass = DetailsFramework.GetSpecializationInfoByID(specID)
|
||||
table.insert(specs, {
|
||||
name = specName,
|
||||
set = loadConditionsFrame.OnRadioCheckboxClick,
|
||||
param = specID,
|
||||
get = function() return loadConditionsFrame.OptionsTable.spec[specID] or loadConditionsFrame.OptionsTable.spec[specID..""] end,
|
||||
texture = specIcon,
|
||||
})
|
||||
end
|
||||
|
||||
local specGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, specs, nil, {width = 200, height = 200, title = "Character Spec", backdrop_color = {0, 0, 0, 0}}, {offset_x = 120, amount_per_line = 4})
|
||||
specGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.spec[1], anchorPositions.spec[2])
|
||||
specGroup.DBKey = "spec"
|
||||
table.insert(loadConditionsFrame.AllRadioGroups, specGroup)
|
||||
end
|
||||
|
||||
--create radio group for character races
|
||||
local raceList = {}
|
||||
for _, raceTable in ipairs(detailsFramework:GetCharacterRaceList()) do
|
||||
table.insert(raceList, {
|
||||
name = raceTable.Name:sub(1, 15),
|
||||
set = loadConditionsFrame.OnRadioCheckboxClick,
|
||||
param = raceTable.FileString,
|
||||
get = function() return loadConditionsFrame.OptionsTable.race [raceTable.FileString] end,
|
||||
})
|
||||
end
|
||||
|
||||
local raceGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, raceList, nil, {width = 200, height = 200, title = "Character Race", backdrop_color = {0, 0, 0, 0}})
|
||||
raceGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.race [1], anchorPositions.race [2])
|
||||
raceGroup.DBKey = "race"
|
||||
table.insert(loadConditionsFrame.AllRadioGroups, raceGroup)
|
||||
|
||||
--create radio group for talents
|
||||
if IS_WOW_PROJECT_MAINLINE then
|
||||
--[=[ 7.0 to 9.0 talents schema
|
||||
local talentList = {}
|
||||
for _, talentTable in ipairs(detailsFramework:GetCharacterTalents()) do
|
||||
if talentTable.ID then
|
||||
table.insert(talentList, {
|
||||
name = talentTable.Name:sub(1, 15),
|
||||
set = loadConditionsFrame.OnRadioCheckboxClick,
|
||||
param = talentTable.ID,
|
||||
get = function() return loadConditionsFrame.OptionsTable.talent[talentTable.ID] or loadConditionsFrame.OptionsTable.talent[talentTable.ID .. ""] end,
|
||||
texture = talentTable.Texture,
|
||||
})
|
||||
end
|
||||
end
|
||||
--]=]
|
||||
|
||||
--10.0 talents schema
|
||||
local talentList = {}
|
||||
local talentGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, talentList, nil, {width = 200, height = 200, title = "Character Talents", backdrop_color = {0, 0, 0, 0}}, {offset_x = 64, amount_per_line = 16})
|
||||
talentGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.talent[1], anchorPositions.talent[2])
|
||||
talentGroup.DBKey = "talent"
|
||||
|
||||
table.insert(loadConditionsFrame.AllRadioGroups, talentGroup)
|
||||
loadConditionsFrame.TalentGroup = talentGroup
|
||||
|
||||
do
|
||||
if (false) then --disabled, isn't in use
|
||||
--create a frame to show talents selected in other specs or characters
|
||||
local otherTalents = CreateFrame("frame", nil, loadConditionsFrame, "BackdropTemplate")
|
||||
otherTalents:SetSize(26, 26)
|
||||
otherTalents:SetPoint("left", talentGroup.Title.widget, "right", 10, -2)
|
||||
otherTalents.Texture = detailsFramework:CreateImage(otherTalents, [[Interface\BUTTONS\AdventureGuideMicrobuttonAlert]], 24, 24)
|
||||
otherTalents.Texture:SetAllPoints()
|
||||
|
||||
local removeTalent = function(_, _, talentID)
|
||||
loadConditionsFrame.OptionsTable.talent[talentID] = nil
|
||||
GameCooltip2:Hide()
|
||||
loadConditionsFrame.OnRadioStateChanged(talentGroup, loadConditionsFrame.OptionsTable[talentGroup.DBKey])
|
||||
--loadConditionsFrame.CanShowTalentWarning()
|
||||
end
|
||||
|
||||
local buildTalentMenu = function()
|
||||
local playerTalents = detailsFramework:GetCharacterTalents()
|
||||
local indexedTalents = {}
|
||||
for _, talentTable in ipairs(playerTalents) do
|
||||
table.insert(indexedTalents, talentTable.ID)
|
||||
end
|
||||
|
||||
--talents selected to load
|
||||
GameCooltip2:AddLine("select a talent to remove it (added from a different spec or character)", "", 1, "orange", "orange", 9)
|
||||
GameCooltip2:AddLine("$div", nil, nil, -1, -1)
|
||||
|
||||
for talentID, _ in pairs(loadConditionsFrame.OptionsTable.talent) do
|
||||
if (type(talentID) == "number" and not detailsFramework.table.find(indexedTalents, talentID)) then
|
||||
local talentID, name, texture, selected, available = GetTalentInfoByID(talentID)
|
||||
if (name) then
|
||||
GameCooltip2:AddLine(name)
|
||||
GameCooltip2:AddIcon(texture, 1, 1, 16, 16, .1, .9, .1, .9)
|
||||
GameCooltip2:AddMenu(1, removeTalent, talentID)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
otherTalents.CoolTip = {
|
||||
Type = "menu",
|
||||
BuildFunc = buildTalentMenu,
|
||||
OnEnterFunc = function(self) end,
|
||||
OnLeaveFunc = function(self) end,
|
||||
FixedValue = "none",
|
||||
ShowSpeed = 0.05,
|
||||
Options = function()
|
||||
GameCooltip2:SetOption("TextFont", "Friz Quadrata TT")
|
||||
GameCooltip2:SetOption("TextColor", "orange")
|
||||
GameCooltip2:SetOption("TextSize", 12)
|
||||
GameCooltip2:SetOption("FixedWidth", 220)
|
||||
GameCooltip2:SetOption("ButtonsYMod", -4)
|
||||
GameCooltip2:SetOption("YSpacingMod", -4)
|
||||
GameCooltip2:SetOption("IgnoreButtonAutoHeight", true)
|
||||
|
||||
GameCooltip2:SetColor(1, 0.5, 0.5, 0.5, 0)
|
||||
|
||||
local preset2_backdrop = {bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], edgeFile = [[Interface\Buttons\WHITE8X8]], tile = true, edgeSize = 1, tileSize = 16, insets = {left = 0, right = 0, top = 0, bottom = 0}}
|
||||
local gray_table = {0.37, 0.37, 0.37, 0.95}
|
||||
local black_table = {0.2, 0.2, 0.2, 1}
|
||||
GameCooltip2:SetBackdrop(1, preset2_backdrop, gray_table, black_table)
|
||||
GameCooltip2:SetBackdrop(2, preset2_backdrop, gray_table, black_table)
|
||||
end,
|
||||
}
|
||||
GameCooltip2:CoolTipInject(otherTalents)
|
||||
|
||||
--[=[
|
||||
function loadConditionsFrame.CanShowTalentWarning() --not in use
|
||||
local playerTalents = detailsFramework:GetCharacterTalents()
|
||||
local indexedTalents = {}
|
||||
for _, talentTable in ipairs(playerTalents) do
|
||||
table.insert(indexedTalents, talentTable.ID)
|
||||
end
|
||||
for talentID, _ in pairs(loadConditionsFrame.OptionsTable.talent) do
|
||||
if (type(talentID) == "number" and not detailsFramework.table.find(indexedTalents, talentID)) then
|
||||
otherTalents:Show()
|
||||
return
|
||||
end
|
||||
end
|
||||
otherTalents:Hide()
|
||||
end
|
||||
--]=]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--create radio group for pvp talents
|
||||
if IS_WOW_PROJECT_MAINLINE then
|
||||
local pvpTalentList = {}
|
||||
for _, talentTable in ipairs(detailsFramework:GetCharacterPvPTalents()) do
|
||||
table.insert(pvpTalentList, {
|
||||
name = talentTable.Name:sub(1, 15),
|
||||
set = loadConditionsFrame.OnRadioCheckboxClick,
|
||||
param = talentTable.ID,
|
||||
get = function() return loadConditionsFrame.OptionsTable.pvptalent [talentTable.ID] or loadConditionsFrame.OptionsTable.pvptalent [talentTable.ID .. ""] end,
|
||||
texture = talentTable.Texture,
|
||||
})
|
||||
end
|
||||
local pvpTalentGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, pvpTalentList, nil, {width = 200, height = 200, title = "Characer PvP Talents", backdrop_color = {0, 0, 0, 0}}, {offset_x = 160, amount_per_line = 3})
|
||||
pvpTalentGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.pvptalent [1], anchorPositions.pvptalent [2])
|
||||
pvpTalentGroup.DBKey = "pvptalent"
|
||||
table.insert(loadConditionsFrame.AllRadioGroups, pvpTalentGroup)
|
||||
loadConditionsFrame.PvPTalentGroup = pvpTalentGroup
|
||||
|
||||
do
|
||||
if (false) then
|
||||
--create a frame to show talents selected in other specs or characters
|
||||
local otherTalents = CreateFrame("frame", nil, loadConditionsFrame, "BackdropTemplate")
|
||||
otherTalents:SetSize(26, 26)
|
||||
otherTalents:SetPoint("left", pvpTalentGroup.Title.widget, "right", 10, -2)
|
||||
otherTalents.Texture = detailsFramework:CreateImage(otherTalents, [[Interface\BUTTONS\AdventureGuideMicrobuttonAlert]], 24, 24)
|
||||
otherTalents.Texture:SetAllPoints()
|
||||
|
||||
local removeTalent = function(_, _, talentID)
|
||||
loadConditionsFrame.OptionsTable.pvptalent [talentID] = nil
|
||||
GameCooltip2:Hide()
|
||||
loadConditionsFrame.OnRadioStateChanged(pvpTalentGroup, loadConditionsFrame.OptionsTable [pvpTalentGroup.DBKey])
|
||||
--loadConditionsFrame.CanShowPvPTalentWarning()
|
||||
end
|
||||
|
||||
local buildTalentMenu = function()
|
||||
local playerTalents = detailsFramework:GetCharacterPvPTalents()
|
||||
local indexedTalents = {}
|
||||
for _, talentTable in ipairs(playerTalents) do
|
||||
table.insert(indexedTalents, talentTable.ID)
|
||||
end
|
||||
|
||||
--talents selected to load
|
||||
GameCooltip2:AddLine("select a talent to remove it(added from a different spec or character)", "", 1, "orange", "orange", 9)
|
||||
GameCooltip2:AddLine("$div", nil, nil, -1, -1)
|
||||
|
||||
for talentID, _ in pairs(loadConditionsFrame.OptionsTable.pvptalent) do
|
||||
if (type(talentID) == "number" and not detailsFramework.table.find(indexedTalents, talentID)) then
|
||||
local _, name, texture = GetPvpTalentInfoByID(talentID)
|
||||
if (name) then
|
||||
GameCooltip2:AddLine(name)
|
||||
GameCooltip2:AddIcon(texture, 1, 1, 16, 16, .1, .9, .1, .9)
|
||||
GameCooltip2:AddMenu(1, removeTalent, talentID)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
otherTalents.CoolTip = {
|
||||
Type = "menu",
|
||||
BuildFunc = buildTalentMenu,
|
||||
OnEnterFunc = function(self) end,
|
||||
OnLeaveFunc = function(self) end,
|
||||
FixedValue = "none",
|
||||
ShowSpeed = 0.05,
|
||||
Options = function()
|
||||
GameCooltip2:SetOption("TextFont", "Friz Quadrata TT")
|
||||
GameCooltip2:SetOption("TextColor", "orange")
|
||||
GameCooltip2:SetOption("TextSize", 12)
|
||||
GameCooltip2:SetOption("FixedWidth", 220)
|
||||
GameCooltip2:SetOption("ButtonsYMod", -4)
|
||||
GameCooltip2:SetOption("YSpacingMod", -4)
|
||||
GameCooltip2:SetOption("IgnoreButtonAutoHeight", true)
|
||||
|
||||
GameCooltip2:SetColor(1, 0.5, 0.5, 0.5, 0)
|
||||
|
||||
local preset2_backdrop = {edgeFile = [[Interface\Buttons\WHITE8X8]], tile = true, edgeSize = 1, tileSize = 16, insets = {left = 0, right = 0, top = 0, bottom = 0}}
|
||||
local gray_table = {0.37, 0.37, 0.37, 0.95}
|
||||
local black_table = {0.2, 0.2, 0.2, 1}
|
||||
GameCooltip2:SetBackdrop(1, preset2_backdrop, gray_table, black_table)
|
||||
GameCooltip2:SetBackdrop(2, preset2_backdrop, gray_table, black_table)
|
||||
end,
|
||||
}
|
||||
GameCooltip2:CoolTipInject(otherTalents)
|
||||
|
||||
function loadConditionsFrame.CanShowPvPTalentWarning()
|
||||
local playerTalents = detailsFramework:GetCharacterPvPTalents()
|
||||
local indexedTalents = {}
|
||||
for _, talentTable in ipairs(playerTalents) do
|
||||
table.insert(indexedTalents, talentTable.ID)
|
||||
end
|
||||
for talentID, _ in pairs(loadConditionsFrame.OptionsTable.pvptalent) do
|
||||
if (type(talentID) == "number" and not detailsFramework.table.find(indexedTalents, talentID)) then
|
||||
otherTalents:Show()
|
||||
return
|
||||
end
|
||||
end
|
||||
otherTalents:Hide()
|
||||
end
|
||||
--]=]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--create radio for group types
|
||||
local groupTypes = {}
|
||||
for _, groupTable in ipairs(detailsFramework:GetGroupTypes()) do
|
||||
table.insert(groupTypes, {
|
||||
name = groupTable.Name,
|
||||
set = loadConditionsFrame.OnRadioCheckboxClick,
|
||||
param = groupTable.ID,
|
||||
get = function() return loadConditionsFrame.OptionsTable.group [groupTable.ID] or loadConditionsFrame.OptionsTable.group [groupTable.ID .. ""] end,
|
||||
})
|
||||
end
|
||||
local groupTypesGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, groupTypes, nil, {width = 200, height = 200, title = "Group Types", backdrop_color = {0, 0, 0, 0}}, {offset_x = 125})
|
||||
groupTypesGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.group[1], anchorPositions.group[2])
|
||||
groupTypesGroup.DBKey = "group"
|
||||
table.insert(loadConditionsFrame.AllRadioGroups, groupTypesGroup)
|
||||
|
||||
--create radio for character roles
|
||||
local roleTypes = {}
|
||||
for _, roleTable in ipairs(detailsFramework:GetRoleTypes()) do
|
||||
table.insert(roleTypes, {
|
||||
name = (roleTable.Texture .. " " .. roleTable.Name),
|
||||
set = loadConditionsFrame.OnRadioCheckboxClick,
|
||||
param = roleTable.ID,
|
||||
get = function() return loadConditionsFrame.OptionsTable.role [roleTable.ID] or loadConditionsFrame.OptionsTable.role [roleTable.ID .. ""] end,
|
||||
})
|
||||
end
|
||||
|
||||
local roleTypesGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, roleTypes, nil, {width = 200, height = 200, title = "Role Types", backdrop_color = {0, 0, 0, 0}})
|
||||
roleTypesGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.role[1], anchorPositions.role[2])
|
||||
roleTypesGroup.DBKey = "role"
|
||||
table.insert(loadConditionsFrame.AllRadioGroups, roleTypesGroup)
|
||||
|
||||
--create radio group for mythic+ affixes
|
||||
if IS_WOW_PROJECT_MAINLINE then
|
||||
local affixes = {}
|
||||
for i = 2, 1000 do
|
||||
local affixName, desc, texture = C_ChallengeMode.GetAffixInfo(i)
|
||||
if (affixName and not deprecatedAffixes[i]) then
|
||||
table.insert(affixes, {
|
||||
name = affixName,
|
||||
set = loadConditionsFrame.OnRadioCheckboxClick,
|
||||
param = i,
|
||||
get = function() return loadConditionsFrame.OptionsTable.affix[i] or loadConditionsFrame.OptionsTable.affix[i .. ""] end,
|
||||
texture = texture,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
local affixTypesGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, affixes, nil, {width = 200, height = 200, title = "M+ Affixes", backdrop_color = {0, 0, 0, 0}}, {offset_x = 125})
|
||||
affixTypesGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.affix [1], anchorPositions.affix [2])
|
||||
affixTypesGroup.DBKey = "affix"
|
||||
table.insert(loadConditionsFrame.AllRadioGroups, affixTypesGroup)
|
||||
end
|
||||
|
||||
--text entries functions
|
||||
local textEntryRefresh = function(self)
|
||||
local idList = loadConditionsFrame.OptionsTable [self.DBKey]
|
||||
self:SetText("")
|
||||
for _, id in pairs(idList) do
|
||||
if tonumber(id) then
|
||||
self:SetText(self:GetText() .. " " .. id)
|
||||
end
|
||||
end
|
||||
self:SetText(self:GetText():gsub("^ ", ""))
|
||||
end
|
||||
|
||||
local textEntryOnEnterPressed = function(_, self)
|
||||
table.wipe(loadConditionsFrame.OptionsTable [self.DBKey])
|
||||
local text = self:GetText()
|
||||
|
||||
for _, ID in ipairs({strsplit(" ", text)}) do
|
||||
ID = detailsFramework:trim(ID)
|
||||
ID = tonumber(ID)
|
||||
if (ID) then
|
||||
table.insert(loadConditionsFrame.OptionsTable [self.DBKey], ID)
|
||||
loadConditionsFrame.OptionsTable [self.DBKey].Enabled = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--create the text entry to type the encounter ID
|
||||
local encounterIDLabel = detailsFramework:CreateLabel(loadConditionsFrame, "Encounter ID", detailsFramework:GetTemplate("font", "ORANGE_FONT_TEMPLATE"))
|
||||
local encounterIDEditbox = detailsFramework:CreateTextEntry(loadConditionsFrame, function() loadConditionsFrame.RunCallback() end, 200, 20, "EncounterEditbox", _, _, detailsFramework:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
|
||||
encounterIDLabel:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.encounter_ids[1], anchorPositions.encounter_ids[2])
|
||||
encounterIDEditbox:SetPoint("topleft", encounterIDLabel, "bottomleft", 0, -2)
|
||||
encounterIDEditbox.DBKey = "encounter_ids"
|
||||
encounterIDEditbox.Refresh = textEntryRefresh
|
||||
encounterIDEditbox.tooltip = "Enter multiple IDs separating with a whitespace.\nExample: 35 45 95\n\nSanctum of Domination:\n"
|
||||
|
||||
for _, encounterTable in ipairs(detailsFramework:GetCLEncounterIDs()) do
|
||||
encounterIDEditbox.tooltip = encounterIDEditbox.tooltip .. encounterTable.ID .. " - " .. encounterTable.Name .. "\n"
|
||||
end
|
||||
|
||||
encounterIDEditbox:SetHook("OnEnterPressed", textEntryOnEnterPressed)
|
||||
table.insert(loadConditionsFrame.AllTextEntries, encounterIDEditbox)
|
||||
|
||||
--create the text entry for map ID
|
||||
local mapIDLabel = detailsFramework:CreateLabel(loadConditionsFrame, "Map ID", detailsFramework:GetTemplate("font", "ORANGE_FONT_TEMPLATE"))
|
||||
local mapIDEditbox = detailsFramework:CreateTextEntry(loadConditionsFrame, function() loadConditionsFrame.RunCallback() end, 200, 20, "MapEditbox", _, _, detailsFramework:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
|
||||
mapIDLabel:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.map_ids[1], anchorPositions.map_ids[2])
|
||||
mapIDEditbox:SetPoint("topleft", mapIDLabel, "bottomleft", 0, -2)
|
||||
mapIDEditbox.DBKey = "map_ids"
|
||||
mapIDEditbox.Refresh = textEntryRefresh
|
||||
mapIDEditbox.tooltip = "Enter multiple IDs separating with a whitespace\nExample: 35 45 95"
|
||||
mapIDEditbox:SetHook("OnEnterPressed", textEntryOnEnterPressed)
|
||||
table.insert(loadConditionsFrame.AllTextEntries, mapIDEditbox)
|
||||
|
||||
function loadConditionsFrame.Refresh(self)
|
||||
if IS_WOW_PROJECT_MAINLINE then
|
||||
---@type {Name: string, ID: number, Texture: any, IsSelected: boolean}[]
|
||||
local allTalents = detailsFramework:GetAllTalents()
|
||||
local talentList = {}
|
||||
for _, talentTable in ipairs(allTalents) do
|
||||
if (talentTable.ID) then
|
||||
table.insert(talentList, {
|
||||
name = "", --talentTable.Name:sub(1, 15),
|
||||
set = loadConditionsFrame.OnRadioCheckboxClick,
|
||||
param = talentTable.ID,
|
||||
get = function() return loadConditionsFrame.OptionsTable.talent[talentTable.ID] or loadConditionsFrame.OptionsTable.talent[talentTable.ID .. ""] end,
|
||||
texture = talentTable.Texture,
|
||||
tooltip = talentTable.Name,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
--[=[]]
|
||||
--update the talents(might have changed if the player changed its specializationid)
|
||||
local talentList = {}
|
||||
for _, talentTable in ipairs(detailsFramework:GetCharacterTalents()) do
|
||||
if talentTable.ID then
|
||||
table.insert(talentList, {
|
||||
name = talentTable.Name,
|
||||
set = loadConditionsFrame.OnRadioCheckboxClick,
|
||||
param = talentTable.ID,
|
||||
get = function() return loadConditionsFrame.OptionsTable.talent [talentTable.ID] or loadConditionsFrame.OptionsTable.talent [talentTable.ID .. ""] end,
|
||||
texture = talentTable.Texture,
|
||||
})
|
||||
end
|
||||
end
|
||||
--]=]
|
||||
|
||||
loadConditionsFrame.TalentGroup:SetOptions(talentList)
|
||||
end
|
||||
|
||||
if IS_WOW_PROJECT_MAINLINE then
|
||||
local pvpTalentList = {}
|
||||
for _, talentTable in ipairs(detailsFramework:GetCharacterPvPTalents()) do
|
||||
table.insert(pvpTalentList, {
|
||||
name = talentTable.Name:sub(1, 15),
|
||||
set = loadConditionsFrame.OnRadioCheckboxClick,
|
||||
param = talentTable.ID,
|
||||
get = function() return loadConditionsFrame.OptionsTable.pvptalent [talentTable.ID] or loadConditionsFrame.OptionsTable.pvptalent [talentTable.ID .. ""] end,
|
||||
texture = talentTable.Texture,
|
||||
})
|
||||
end
|
||||
loadConditionsFrame.PvPTalentGroup:SetOptions(pvpTalentList)
|
||||
end
|
||||
|
||||
--refresh the radio group
|
||||
for _, radioGroup in ipairs(loadConditionsFrame.AllRadioGroups) do
|
||||
radioGroup:Refresh()
|
||||
loadConditionsFrame.OnRadioStateChanged(radioGroup, loadConditionsFrame.OptionsTable [radioGroup.DBKey])
|
||||
end
|
||||
|
||||
--refresh text entries
|
||||
for _, textEntry in ipairs(loadConditionsFrame.AllTextEntries) do
|
||||
textEntry:Refresh()
|
||||
end
|
||||
|
||||
if IS_WOW_PROJECT_MAINLINE then
|
||||
--loadConditionsFrame.CanShowTalentWarning()
|
||||
--loadConditionsFrame.CanShowPvPTalentWarning()
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--set the options table
|
||||
loadConditionsFrame.OptionsTable = optionsTable
|
||||
|
||||
--set the callback func
|
||||
loadConditionsFrame.CallbackFunc = callback
|
||||
loadConditionsFrame.OptionsTable = optionsTable
|
||||
|
||||
--set title
|
||||
loadConditionsFrame.EditingLabel:SetText(frameOptions.name)
|
||||
loadConditionsFrame.Title:SetText(frameOptions.title)
|
||||
|
||||
--show the panel to the user
|
||||
loadConditionsFrame:Show()
|
||||
|
||||
loadConditionsFrame:Refresh()
|
||||
end
|
||||
@@ -427,277 +427,6 @@ detailsFramework.ScriptHookMixin = {
|
||||
end,
|
||||
}
|
||||
|
||||
---mixin to use with DetailsFramework:Mixin(table, detailsFramework.SortFunctions)
|
||||
---add methods to be used on scrollframes
|
||||
---@class df_scrollboxmixin
|
||||
detailsFramework.ScrollBoxFunctions = {
|
||||
---refresh the scrollbox by resetting all lines created with :CreateLine(), then calling the refresh_func which was set at :CreateScrollBox()
|
||||
---@param self table
|
||||
---@return table
|
||||
Refresh = function(self)
|
||||
--hide all frames and tag as not in use
|
||||
self._LinesInUse = 0
|
||||
for index, frame in ipairs(self.Frames) do
|
||||
if (not self.DontHideChildrenOnPreRefresh) then
|
||||
frame:Hide()
|
||||
end
|
||||
frame._InUse = nil
|
||||
end
|
||||
|
||||
local offset = 0
|
||||
if (self.IsFauxScroll) then
|
||||
self:UpdateFaux(#self.data, self.LineAmount, self.LineHeight)
|
||||
offset = self:GetOffsetFaux()
|
||||
end
|
||||
|
||||
--call the refresh function
|
||||
detailsFramework:CoreDispatch((self:GetName() or "ScrollBox") .. ":Refresh()", self.refresh_func, self, self.data, offset, self.LineAmount)
|
||||
|
||||
--hide all frames that are not in use
|
||||
for index, frame in ipairs(self.Frames) do
|
||||
if (not frame._InUse) then
|
||||
frame:Hide()
|
||||
else
|
||||
frame:Show()
|
||||
end
|
||||
end
|
||||
|
||||
self:Show()
|
||||
|
||||
local frameName = self:GetName()
|
||||
if (frameName) then
|
||||
if (self.HideScrollBar) then
|
||||
local scrollBar = _G[frameName .. "ScrollBar"]
|
||||
if (scrollBar) then
|
||||
scrollBar:Hide()
|
||||
end
|
||||
else
|
||||
--[=[ --maybe in the future I visit this again
|
||||
local scrollBar = _G[frameName .. "ScrollBar"]
|
||||
local height = self:GetHeight()
|
||||
local totalLinesRequired = #self.data
|
||||
local linesShown = self._LinesInUse
|
||||
|
||||
local percent = linesShown / totalLinesRequired
|
||||
local thumbHeight = height * percent
|
||||
scrollBar.ThumbTexture:SetSize(12, thumbHeight)
|
||||
print("thumbHeight:", thumbHeight)
|
||||
--]=]
|
||||
end
|
||||
end
|
||||
return self.Frames
|
||||
end,
|
||||
|
||||
OnVerticalScroll = function(self, offset)
|
||||
self:OnVerticalScrollFaux(offset, self.LineHeight, self.Refresh)
|
||||
return true
|
||||
end,
|
||||
|
||||
---create a line within the scrollbox
|
||||
---@param self table is the scrollbox
|
||||
---@param func function|nil function to create the line object, this function will receive the line index as argument and return a table with the line object
|
||||
---@return table line object (table)
|
||||
CreateLine = function(self, func)
|
||||
if (not func) then
|
||||
func = self.CreateLineFunc
|
||||
end
|
||||
|
||||
local okay, newLine = pcall(func, self, #self.Frames+1)
|
||||
if (okay) then
|
||||
if (not newLine) then
|
||||
error("ScrollFrame:CreateLine() function did not returned a line, use: 'return line'")
|
||||
end
|
||||
tinsert(self.Frames, newLine)
|
||||
newLine.Index = #self.Frames
|
||||
return newLine
|
||||
else
|
||||
error("ScrollFrame:CreateLine() error on creating a line: " .. newLine)
|
||||
end
|
||||
end,
|
||||
|
||||
CreateLines = function(self, callback, lineAmount)
|
||||
for i = 1, lineAmount do
|
||||
self:CreateLine(callback)
|
||||
end
|
||||
end,
|
||||
|
||||
GetLine = function(self, lineIndex)
|
||||
local line = self.Frames[lineIndex]
|
||||
if (line) then
|
||||
line._InUse = true
|
||||
end
|
||||
|
||||
self._LinesInUse = self._LinesInUse + 1
|
||||
return line
|
||||
end,
|
||||
|
||||
SetData = function(self, data)
|
||||
self.data = data
|
||||
end,
|
||||
GetData = function(self)
|
||||
return self.data
|
||||
end,
|
||||
|
||||
GetFrames = function(self)
|
||||
return self.Frames
|
||||
end,
|
||||
GetLines = function(self) --alias of GetFrames
|
||||
return self.Frames
|
||||
end,
|
||||
|
||||
GetNumFramesCreated = function(self)
|
||||
return #self.Frames
|
||||
end,
|
||||
|
||||
GetNumFramesShown = function(self)
|
||||
return self.LineAmount
|
||||
end,
|
||||
|
||||
SetNumFramesShown = function(self, newAmount)
|
||||
--hide frames which won't be used
|
||||
if (newAmount < #self.Frames) then
|
||||
for i = newAmount+1, #self.Frames do
|
||||
self.Frames[i]:Hide()
|
||||
end
|
||||
end
|
||||
--set the new amount
|
||||
self.LineAmount = newAmount
|
||||
end,
|
||||
|
||||
SetFramesHeight = function(self, height)
|
||||
self.LineHeight = height
|
||||
self:OnSizeChanged()
|
||||
self:Refresh()
|
||||
end,
|
||||
|
||||
OnSizeChanged = function(self)
|
||||
if (self.ReajustNumFrames) then
|
||||
--how many lines the scroll can show
|
||||
local amountOfFramesToShow = floor(self:GetHeight() / self.LineHeight)
|
||||
|
||||
--how many lines the scroll already have
|
||||
local totalFramesCreated = self:GetNumFramesCreated()
|
||||
|
||||
--how many lines are current shown
|
||||
local totalFramesShown = self:GetNumFramesShown()
|
||||
|
||||
--the amount of frames increased
|
||||
if (amountOfFramesToShow > totalFramesShown) then
|
||||
for i = totalFramesShown+1, amountOfFramesToShow do
|
||||
--check if need to create a new line
|
||||
if (i > totalFramesCreated) then
|
||||
self:CreateLine(self.CreateLineFunc)
|
||||
end
|
||||
end
|
||||
|
||||
--the amount of frames decreased
|
||||
elseif (amountOfFramesToShow < totalFramesShown) then
|
||||
--hide all frames above the new amount to show
|
||||
for i = totalFramesCreated, amountOfFramesToShow, -1 do
|
||||
if (self.Frames[i]) then
|
||||
self.Frames[i]:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--set the new amount of frames
|
||||
self:SetNumFramesShown(amountOfFramesToShow)
|
||||
--refresh lines
|
||||
self:Refresh()
|
||||
end
|
||||
end,
|
||||
|
||||
--moved functions from blizzard faux scroll that are called from insecure code environment
|
||||
--this reduces the amount of taints while using the faux scroll frame
|
||||
GetOffsetFaux = function(self)
|
||||
return self.offset or 0
|
||||
end,
|
||||
OnVerticalScrollFaux = function(self, value, itemHeight, updateFunction)
|
||||
local scrollbar = self:GetChildFramesFaux();
|
||||
scrollbar:SetValue(value);
|
||||
self.offset = math.floor((value / itemHeight) + 0.5);
|
||||
if (updateFunction) then
|
||||
updateFunction(self)
|
||||
end
|
||||
end,
|
||||
GetChildFramesFaux = function(frame)
|
||||
local frameName = frame:GetName();
|
||||
if frameName then
|
||||
return _G[ frameName.."ScrollBar" ], _G[ frameName.."ScrollChildFrame" ], _G[ frameName.."ScrollBarScrollUpButton" ], _G[ frameName.."ScrollBarScrollDownButton" ];
|
||||
else
|
||||
return frame.ScrollBar, frame.ScrollChildFrame, frame.ScrollBar.ScrollUpButton, frame.ScrollBar.ScrollDownButton;
|
||||
end
|
||||
end,
|
||||
UpdateFaux = function(frame, numItems, numToDisplay, buttonHeight, button, smallWidth, bigWidth, highlightFrame, smallHighlightWidth, bigHighlightWidth, alwaysShowScrollBar)
|
||||
local scrollBar, scrollChildFrame, scrollUpButton, scrollDownButton = frame:GetChildFramesFaux();
|
||||
-- If more than one screen full of items then show the scrollbar
|
||||
local showScrollBar;
|
||||
if ( numItems > numToDisplay or alwaysShowScrollBar ) then
|
||||
frame:Show();
|
||||
showScrollBar = 1;
|
||||
else
|
||||
scrollBar:SetValue(0);
|
||||
frame:Hide();
|
||||
end
|
||||
if ( frame:IsShown() ) then
|
||||
local scrollFrameHeight = 0;
|
||||
local scrollChildHeight = 0;
|
||||
|
||||
if ( numItems > 0 ) then
|
||||
scrollFrameHeight = (numItems - numToDisplay) * buttonHeight;
|
||||
scrollChildHeight = numItems * buttonHeight;
|
||||
if ( scrollFrameHeight < 0 ) then
|
||||
scrollFrameHeight = 0;
|
||||
end
|
||||
scrollChildFrame:Show();
|
||||
else
|
||||
scrollChildFrame:Hide();
|
||||
end
|
||||
local maxRange = (numItems - numToDisplay) * buttonHeight;
|
||||
if (maxRange < 0) then
|
||||
maxRange = 0;
|
||||
end
|
||||
scrollBar:SetMinMaxValues(0, maxRange);
|
||||
scrollBar:SetValueStep(buttonHeight);
|
||||
scrollBar:SetStepsPerPage(numToDisplay-1);
|
||||
scrollChildFrame:SetHeight(scrollChildHeight);
|
||||
|
||||
-- Arrow button handling
|
||||
if ( scrollBar:GetValue() == 0 ) then
|
||||
scrollUpButton:Disable();
|
||||
else
|
||||
scrollUpButton:Enable();
|
||||
end
|
||||
if ((scrollBar:GetValue() - scrollFrameHeight) == 0) then
|
||||
scrollDownButton:Disable();
|
||||
else
|
||||
scrollDownButton:Enable();
|
||||
end
|
||||
|
||||
-- Shrink because scrollbar is shown
|
||||
if ( highlightFrame ) then
|
||||
highlightFrame:SetWidth(smallHighlightWidth);
|
||||
end
|
||||
if ( button ) then
|
||||
for i=1, numToDisplay do
|
||||
_G[button..i]:SetWidth(smallWidth);
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Widen because scrollbar is hidden
|
||||
if ( highlightFrame ) then
|
||||
highlightFrame:SetWidth(bigHighlightWidth);
|
||||
end
|
||||
if ( button ) then
|
||||
for i=1, numToDisplay do
|
||||
_G[button..i]:SetWidth(bigWidth);
|
||||
end
|
||||
end
|
||||
end
|
||||
return showScrollBar;
|
||||
end,
|
||||
}
|
||||
|
||||
--back compatibility, can be removed in the future (28/04/2023)
|
||||
---@class DetailsFramework.ScrollBoxFunctions : df_scrollboxmixin
|
||||
|
||||
|
||||
+235
-1401
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,7 @@ local CreateImageEditorFrame = function()
|
||||
background_frame:SetSize(790, 560)
|
||||
background_frame:SetClampedToScreen(true)
|
||||
|
||||
tinsert(UISpecialFrames, "DetailsFrameworkImageEditBackground")
|
||||
table.insert(UISpecialFrames, "DetailsFrameworkImageEditBackground")
|
||||
|
||||
background_frame:SetResizable(true)
|
||||
background_frame:SetMovable(true)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
--Details Framework Examples for the frame.lua file
|
||||
--create a frame with rounded corners
|
||||
|
||||
local detailsFramework = DetailsFramework
|
||||
local parent = UIParent
|
||||
|
||||
--example of how to create a frame with rounded corners
|
||||
--frame name for the example
|
||||
local name = "RoundedCornerFrameExample"
|
||||
|
||||
--default options
|
||||
local optionsTable = {
|
||||
use_titlebar = true, --default false | if true creates a title bar for the frame
|
||||
use_scalebar = true, --default false | if true creates a scale bar for the frame
|
||||
title = "Test", --default "" | title shown in the title bar
|
||||
scale = 1,
|
||||
width = 800, --default 200
|
||||
height = 600, --default 200
|
||||
roundness = 8, --default 0 | how rounded are the corner, 0 means very rounded, 15 means no rounded
|
||||
color = {.1, .1, .1, 1},
|
||||
border_color = {.2, .2, .2, .5},
|
||||
corner_texture = [[Interface\CHARACTERFRAME\TempPortraitAlphaMaskSmall]],
|
||||
}
|
||||
|
||||
--create the frame and set it's position
|
||||
---@type df_roundedpanel
|
||||
local frame = _G[name] or detailsFramework:CreateRoundedPanel(parent, name, optionsTable)
|
||||
frame:SetPoint("center", parent, "center", 0, 0)
|
||||
@@ -5,11 +5,15 @@ if (not detailsFramework or not DetailsFrameworkCanLoad) then
|
||||
return
|
||||
end
|
||||
|
||||
local unpack = unpack
|
||||
|
||||
local CreateFrame = CreateFrame
|
||||
local defaultRed, defaultGreen, defaultBlue = detailsFramework:GetDefaultBackdropColor()
|
||||
--local defaultColorTable = {defaultRed, defaultGreen, defaultBlue, 1}
|
||||
local defaultColorTable = {0.98, 0.98, 0.98, 1}
|
||||
local defaultBorderColorTable = {0.1, 0.1, 0.1, 1}
|
||||
local defaultColorTable = {.98, .98, .98, 1}
|
||||
local defaultBorderColorTable = {.2, .2, .2, .5}
|
||||
local titleBarColor = {.2, .2, .2, .5}
|
||||
|
||||
local PixelUtil = PixelUtil or DFPixelUtil
|
||||
|
||||
---@type edgenames[]
|
||||
local cornerNames = {"TopLeft", "TopRight", "BottomLeft", "BottomRight"}
|
||||
@@ -37,22 +41,23 @@ local cornerNames = {"TopLeft", "TopRight", "BottomLeft", "BottomRight"}
|
||||
---@field Left texture
|
||||
---@field Right texture
|
||||
|
||||
---@class df_roundedpanel_preset : table
|
||||
---@field border_color any
|
||||
---@field color any
|
||||
---@field roundness number
|
||||
|
||||
---@class df_roundedpanel_options : table
|
||||
---@field width number
|
||||
---@field height number
|
||||
---@field use_titlebar boolean
|
||||
---@field use_scalebar boolean
|
||||
---@field title string
|
||||
---@field scale number
|
||||
---@field roundness number
|
||||
---@field width number?
|
||||
---@field height number?
|
||||
---@field use_titlebar boolean?
|
||||
---@field use_scalebar boolean?
|
||||
---@field title string?
|
||||
---@field scale number?
|
||||
---@field roundness number?
|
||||
---@field color any
|
||||
---@field border_color any
|
||||
---@field corner_texture texturepath|textureid
|
||||
---@field corner_texture any
|
||||
---@field horizontal_border_size_offset number?
|
||||
|
||||
---@class df_roundedpanel_preset : table, df_roundedpanel_options
|
||||
---@field border_color any
|
||||
---@field color any
|
||||
---@field roundness number?
|
||||
|
||||
---@class df_roundedcornermixin : table
|
||||
---@field RoundedCornerConstructor fun(self:df_roundedpanel) --called from CreateRoundedPanel
|
||||
@@ -102,7 +107,7 @@ local cornerNames = {"TopLeft", "TopRight", "BottomLeft", "BottomRight"}
|
||||
---@param bIsBorder boolean|nil
|
||||
local setCornerPoints = function(self, textures, width, height, xOffset, yOffset, bIsBorder)
|
||||
for cornerName, thisTexture in pairs(textures) do
|
||||
thisTexture:SetSize(width or 16, height or 16)
|
||||
PixelUtil.SetSize(thisTexture, width or 16, height or 16)
|
||||
thisTexture:SetTexture(self.options.corner_texture)
|
||||
|
||||
--set the mask
|
||||
@@ -122,30 +127,30 @@ local setCornerPoints = function(self, textures, width, height, xOffset, yOffset
|
||||
|
||||
if (cornerName == "TopLeft") then
|
||||
thisTexture:SetTexCoord(0, 0.5, 0, 0.5)
|
||||
thisTexture:SetPoint(cornerName, self, cornerName, -xOffset, yOffset)
|
||||
PixelUtil.SetPoint(thisTexture, cornerName, self, cornerName, -xOffset, yOffset)
|
||||
if (thisTexture.MaskTexture) then
|
||||
thisTexture.MaskTexture:SetPoint(cornerName, self, cornerName, -18-xOffset, 16+yOffset)
|
||||
PixelUtil.SetPoint(thisTexture.MaskTexture, cornerName, self, cornerName, -18-xOffset, 16+yOffset)
|
||||
end
|
||||
|
||||
elseif (cornerName == "TopRight") then
|
||||
thisTexture:SetTexCoord(0.5, 1, 0, 0.5)
|
||||
thisTexture:SetPoint(cornerName, self, cornerName, xOffset, yOffset)
|
||||
PixelUtil.SetPoint(thisTexture, cornerName, self, cornerName, xOffset, yOffset)
|
||||
if (thisTexture.MaskTexture) then
|
||||
thisTexture.MaskTexture:SetPoint(cornerName, self, cornerName, -18+xOffset, 16+yOffset)
|
||||
PixelUtil.SetPoint(thisTexture.MaskTexture, cornerName, self, cornerName, -18+xOffset, 16+yOffset)
|
||||
end
|
||||
|
||||
elseif (cornerName == "BottomLeft") then
|
||||
thisTexture:SetTexCoord(0, 0.5, 0.5, 1)
|
||||
thisTexture:SetPoint(cornerName, self, cornerName, -xOffset, -yOffset)
|
||||
PixelUtil.SetPoint(thisTexture, cornerName, self, cornerName, -xOffset, -yOffset)
|
||||
if (thisTexture.MaskTexture) then
|
||||
thisTexture.MaskTexture:SetPoint(cornerName, self, cornerName, -18-xOffset, 16-yOffset)
|
||||
PixelUtil.SetPoint(thisTexture.MaskTexture, cornerName, self, cornerName, -18-xOffset, 16-yOffset)
|
||||
end
|
||||
|
||||
elseif (cornerName == "BottomRight") then
|
||||
thisTexture:SetTexCoord(0.5, 1, 0.5, 1)
|
||||
thisTexture:SetPoint(cornerName, self, cornerName, xOffset, -yOffset)
|
||||
PixelUtil.SetPoint(thisTexture, cornerName, self, cornerName, xOffset, -yOffset)
|
||||
if (thisTexture.MaskTexture) then
|
||||
thisTexture.MaskTexture:SetPoint(cornerName, self, cornerName, -18+xOffset, 16-yOffset)
|
||||
PixelUtil.SetPoint(thisTexture.MaskTexture, cornerName, self, cornerName, -18+xOffset, 16-yOffset)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -157,7 +162,6 @@ detailsFramework.RoundedCornerPanelMixin = {
|
||||
self.CenterTextures = {}
|
||||
self.BorderCornerTextures = {}
|
||||
self.BorderEdgeTextures = {}
|
||||
|
||||
self.cornerRoundness = 0
|
||||
|
||||
for i = 1, #cornerNames do
|
||||
@@ -170,28 +174,28 @@ detailsFramework.RoundedCornerPanelMixin = {
|
||||
--create the top texture which connects the top corners with a horizontal line
|
||||
---@type texture
|
||||
local topHorizontalEdge = self:CreateTexture(nil, "border", nil, 0)
|
||||
topHorizontalEdge:SetPoint("topleft", self.CornerTextures["TopLeft"], "topright", 0, 0)
|
||||
topHorizontalEdge:SetPoint("bottomleft", self.CornerTextures["TopLeft"], "bottomright", 0, 0)
|
||||
topHorizontalEdge:SetPoint("topright", self.CornerTextures["TopRight"], "topleft", 0, 0)
|
||||
topHorizontalEdge:SetPoint("bottomright", self.CornerTextures["TopRight"], "bottomleft", 0, 0)
|
||||
PixelUtil.SetPoint(topHorizontalEdge, "topleft", self.CornerTextures["TopLeft"], "topright", 0, 0)
|
||||
PixelUtil.SetPoint(topHorizontalEdge, "bottomleft", self.CornerTextures["TopLeft"], "bottomright", 0, 0)
|
||||
PixelUtil.SetPoint(topHorizontalEdge, "topright", self.CornerTextures["TopRight"], "topleft", 0, 0)
|
||||
PixelUtil.SetPoint(topHorizontalEdge, "bottomright", self.CornerTextures["TopRight"], "bottomleft", 0, 0)
|
||||
topHorizontalEdge:SetColorTexture(unpack(defaultColorTable))
|
||||
|
||||
--create the bottom texture which connects the bottom corners with a horizontal line
|
||||
---@type texture
|
||||
local bottomHorizontalEdge = self:CreateTexture(nil, "border", nil, 0)
|
||||
bottomHorizontalEdge:SetPoint("topleft", self.CornerTextures["BottomLeft"], "topright", 0, 0)
|
||||
bottomHorizontalEdge:SetPoint("bottomleft", self.CornerTextures["BottomLeft"], "bottomright", 0, 0)
|
||||
bottomHorizontalEdge:SetPoint("topright", self.CornerTextures["BottomRight"], "topleft", 0, 0)
|
||||
bottomHorizontalEdge:SetPoint("bottomright", self.CornerTextures["BottomRight"], "bottomleft", 0, 0)
|
||||
PixelUtil.SetPoint(bottomHorizontalEdge, "topleft", self.CornerTextures["BottomLeft"], "topright", 0, 0)
|
||||
PixelUtil.SetPoint(bottomHorizontalEdge, "bottomleft", self.CornerTextures["BottomLeft"], "bottomright", 0, 0)
|
||||
PixelUtil.SetPoint(bottomHorizontalEdge, "topright", self.CornerTextures["BottomRight"], "topleft", 0, 0)
|
||||
PixelUtil.SetPoint(bottomHorizontalEdge, "bottomright", self.CornerTextures["BottomRight"], "bottomleft", 0, 0)
|
||||
bottomHorizontalEdge:SetColorTexture(unpack(defaultColorTable))
|
||||
|
||||
--create the center block which connects the bottom left of the topleft corner with the top right of the bottom right corner
|
||||
---@type texture
|
||||
local centerBlock = self:CreateTexture(nil, "border", nil, 0)
|
||||
centerBlock:SetPoint("topleft", self.CornerTextures["TopLeft"], "bottomleft", 0, 0)
|
||||
centerBlock:SetPoint("bottomleft", self.CornerTextures["BottomLeft"], "topleft", 0, 0)
|
||||
centerBlock:SetPoint("topright", self.CornerTextures["BottomRight"], "topright", 0, 0)
|
||||
centerBlock:SetPoint("bottomright", self.CornerTextures["BottomRight"], "topright", 0, 0)
|
||||
PixelUtil.SetPoint(centerBlock, "topleft", self.CornerTextures["TopLeft"], "bottomleft", 0, 0)
|
||||
PixelUtil.SetPoint(centerBlock, "bottomleft", self.CornerTextures["BottomLeft"], "topleft", 0, 0)
|
||||
PixelUtil.SetPoint(centerBlock, "topright", self.CornerTextures["BottomRight"], "topright", 0, 0)
|
||||
PixelUtil.SetPoint(centerBlock, "bottomright", self.CornerTextures["BottomRight"], "topright", 0, 0)
|
||||
centerBlock:SetColorTexture(unpack(defaultColorTable))
|
||||
|
||||
self.CenterTextures[#self.CenterTextures+1] = topHorizontalEdge
|
||||
@@ -207,7 +211,7 @@ detailsFramework.RoundedCornerPanelMixin = {
|
||||
---@type height
|
||||
local height = self.options.height
|
||||
|
||||
self:SetSize(width, height)
|
||||
PixelUtil.SetSize(self, width, height)
|
||||
|
||||
--fill the corner and edge textures table
|
||||
setCornerPoints(self, self.CornerTextures)
|
||||
@@ -241,6 +245,7 @@ detailsFramework.RoundedCornerPanelMixin = {
|
||||
titleBar:SetPoint("top", self, "top", 0, -4)
|
||||
titleBar:SetRoundness(5)
|
||||
titleBar:SetFrameLevel(9500)
|
||||
titleBar:SetColor(unpack(titleBarColor))
|
||||
titleBar.bIsTitleBar = true
|
||||
self.TitleBar = titleBar
|
||||
self.bHasTitleBar = true
|
||||
@@ -293,13 +298,13 @@ detailsFramework.RoundedCornerPanelMixin = {
|
||||
|
||||
--set the new size of the corners on all corner textures
|
||||
for _, thisTexture in pairs(self.CornerTextures) do
|
||||
thisTexture:SetSize(newCornerSize-self.cornerRoundness, newCornerSize)
|
||||
PixelUtil.SetSize(thisTexture, newCornerSize - (self.cornerRoundness - 2), newCornerSize)
|
||||
end
|
||||
|
||||
--check if the frame has border and set the size of the border corners as well
|
||||
if (self.bHasBorder) then
|
||||
for _, thisTexture in pairs(self.BorderCornerTextures) do
|
||||
thisTexture:SetSize(newCornerSize, newCornerSize)
|
||||
PixelUtil.SetSize(thisTexture, newCornerSize-2, newCornerSize+2)
|
||||
end
|
||||
|
||||
--hide the left and right edges as the corner textures already is enough to fill the frame
|
||||
@@ -307,8 +312,8 @@ detailsFramework.RoundedCornerPanelMixin = {
|
||||
self.BorderEdgeTextures["Right"]:Hide()
|
||||
|
||||
local horizontalEdgesNewSize = self:CalculateBorderEdgeSize("horizontal")
|
||||
self.BorderEdgeTextures["Top"]:SetSize(horizontalEdgesNewSize, 1)
|
||||
self.BorderEdgeTextures["Bottom"]:SetSize(horizontalEdgesNewSize, 1)
|
||||
PixelUtil.SetSize(self.BorderEdgeTextures["Top"], horizontalEdgesNewSize + (self.options.horizontal_border_size_offset or 0), 1)
|
||||
PixelUtil.SetSize(self.BorderEdgeTextures["Bottom"], horizontalEdgesNewSize + (self.options.horizontal_border_size_offset or 0), 1)
|
||||
end
|
||||
|
||||
self.CenterBlock:Hide()
|
||||
@@ -324,22 +329,22 @@ detailsFramework.RoundedCornerPanelMixin = {
|
||||
self.CenterBlock:Show()
|
||||
|
||||
for _, thisTexture in pairs(self.CornerTextures) do
|
||||
thisTexture:SetSize(cornerWidth-self.cornerRoundness, cornerHeight-self.cornerRoundness)
|
||||
PixelUtil.SetSize(thisTexture, cornerWidth-self.cornerRoundness, cornerHeight-self.cornerRoundness)
|
||||
end
|
||||
|
||||
if (self.bHasBorder) then
|
||||
for _, thisTexture in pairs(self.BorderCornerTextures) do
|
||||
thisTexture:SetSize(cornerWidth-self.cornerRoundness, cornerHeight-self.cornerRoundness)
|
||||
PixelUtil.SetSize(thisTexture, cornerWidth-self.cornerRoundness, cornerHeight-self.cornerRoundness)
|
||||
thisTexture.MaskTexture:SetSize(74-(self.cornerRoundness*0.75), 64-self.cornerRoundness)
|
||||
end
|
||||
|
||||
local horizontalEdgesNewSize = self:CalculateBorderEdgeSize("horizontal")
|
||||
self.BorderEdgeTextures["Top"]:SetSize(horizontalEdgesNewSize, 1)
|
||||
self.BorderEdgeTextures["Bottom"]:SetSize(horizontalEdgesNewSize, 1)
|
||||
PixelUtil.SetSize(self.BorderEdgeTextures["Top"], horizontalEdgesNewSize, 1)
|
||||
PixelUtil.SetSize(self.BorderEdgeTextures["Bottom"], horizontalEdgesNewSize, 1)
|
||||
|
||||
local verticalEdgesNewSize = self:CalculateBorderEdgeSize("vertical")
|
||||
self.BorderEdgeTextures["Left"]:SetSize(1, verticalEdgesNewSize)
|
||||
self.BorderEdgeTextures["Right"]:SetSize(1, verticalEdgesNewSize)
|
||||
PixelUtil.SetSize(self.BorderEdgeTextures["Left"], 1, verticalEdgesNewSize)
|
||||
PixelUtil.SetSize(self.BorderEdgeTextures["Right"], 1, verticalEdgesNewSize)
|
||||
end
|
||||
end
|
||||
end,
|
||||
@@ -389,22 +394,22 @@ detailsFramework.RoundedCornerPanelMixin = {
|
||||
--create the top, left, bottom and right edges, the edge has 1pixel width and connects the corners
|
||||
---@type texture
|
||||
local topEdge = self:CreateTexture(nil, "background", nil, 0)
|
||||
topEdge:SetPoint("bottom", self, "top", 0, 0)
|
||||
PixelUtil.SetPoint(topEdge, "bottom", self, "top", 0, 0)
|
||||
self.BorderEdgeTextures["Top"] = topEdge
|
||||
|
||||
---@type texture
|
||||
local leftEdge = self:CreateTexture(nil, "background", nil, 0)
|
||||
leftEdge:SetPoint("right", self, "left", 0, 0)
|
||||
PixelUtil.SetPoint(leftEdge, "right", self, "left", 0, 0)
|
||||
self.BorderEdgeTextures["Left"] = leftEdge
|
||||
|
||||
---@type texture
|
||||
local bottomEdge = self:CreateTexture(nil, "background", nil, 0)
|
||||
bottomEdge:SetPoint("top", self, "bottom", 0, 0)
|
||||
PixelUtil.SetPoint(bottomEdge, "top", self, "bottom", 0, 0)
|
||||
self.BorderEdgeTextures["Bottom"] = bottomEdge
|
||||
|
||||
---@type texture
|
||||
local rightEdge = self:CreateTexture(nil, "background", nil, 0)
|
||||
rightEdge:SetPoint("left", self, "right", 0, 0)
|
||||
PixelUtil.SetPoint(rightEdge, "left", self, "right", 0, 0)
|
||||
self.BorderEdgeTextures["Right"] = rightEdge
|
||||
|
||||
---@type width
|
||||
@@ -413,10 +418,10 @@ detailsFramework.RoundedCornerPanelMixin = {
|
||||
local verticalEdgeSize = self:CalculateBorderEdgeSize("vertical")
|
||||
|
||||
--set the edges size
|
||||
topEdge:SetSize(horizontalEdgeSize, 1)
|
||||
leftEdge:SetSize(1, verticalEdgeSize)
|
||||
bottomEdge:SetSize(horizontalEdgeSize, 1)
|
||||
rightEdge:SetSize(1, verticalEdgeSize)
|
||||
PixelUtil.SetSize(topEdge, horizontalEdgeSize, 1)
|
||||
PixelUtil.SetSize(leftEdge, 1, verticalEdgeSize)
|
||||
PixelUtil.SetSize(bottomEdge, horizontalEdgeSize, 1)
|
||||
PixelUtil.SetSize(rightEdge, 1, verticalEdgeSize)
|
||||
|
||||
for edgeName, thisTexture in pairs(self.BorderEdgeTextures) do
|
||||
---@cast thisTexture texture
|
||||
@@ -482,7 +487,7 @@ detailsFramework.RoundedCornerPanelMixin = {
|
||||
end
|
||||
|
||||
if (self.bHasBorder) then
|
||||
if (alpha < 0.98) then
|
||||
if (alpha < 0.979) then
|
||||
--if using borders, the two border textures overlaps making the alpha be darker than it should
|
||||
for _, thisTexture in pairs(self.BorderCornerTextures) do
|
||||
thisTexture.MaskTexture:Show()
|
||||
@@ -504,14 +509,14 @@ local defaultOptions = {
|
||||
title = "",
|
||||
scale = 1,
|
||||
roundness = 0,
|
||||
color = defaultColorTable,
|
||||
border_color = defaultColorTable,
|
||||
color = {.1, .1, .1, 1},
|
||||
border_color = {.2, .2, .2, .5},
|
||||
corner_texture = [[Interface\CHARACTERFRAME\TempPortraitAlphaMaskSmall]],
|
||||
}
|
||||
|
||||
local defaultPreset = {
|
||||
border_color = {.1, .1, .1, 0.834},
|
||||
color = {defaultRed, defaultGreen, defaultBlue},
|
||||
color = {.1, .1, .1, 1},
|
||||
border_color = {.2, .2, .2, .5},
|
||||
roundness = 3,
|
||||
}
|
||||
|
||||
@@ -536,7 +541,11 @@ function detailsFramework:CreateRoundedPanel(parent, name, optionsTable)
|
||||
if (newRoundedPanel.options.use_titlebar) then
|
||||
---@type df_roundedpanel
|
||||
local titleBar = detailsFramework:CreateRoundedPanel(newRoundedPanel, "$parentTitleBar", {height = 26})
|
||||
titleBar:SetColor(unpack(titleBarColor))
|
||||
titleBar:SetPoint("top", newRoundedPanel, "top", 0, -7)
|
||||
|
||||
titleBar:SetBorderCornerColor(0, 0, 0, 0)
|
||||
|
||||
newRoundedPanel.TitleBar = titleBar
|
||||
titleBar:SetRoundness(5)
|
||||
newRoundedPanel.bHasTitleBar = true
|
||||
@@ -548,8 +557,8 @@ function detailsFramework:CreateRoundedPanel(parent, name, optionsTable)
|
||||
end
|
||||
|
||||
newRoundedPanel:SetRoundness(newRoundedPanel.options.roundness)
|
||||
newRoundedPanel:SetColor(newRoundedPanel.options.color)
|
||||
newRoundedPanel:SetBorderCornerColor(newRoundedPanel.options.border_color)
|
||||
newRoundedPanel:SetColor(newRoundedPanel.options.color)
|
||||
|
||||
return newRoundedPanel
|
||||
end
|
||||
@@ -613,49 +622,10 @@ function detailsFramework:AddRoundedCornersToFrame(frame, preset)
|
||||
|
||||
--handle preset
|
||||
if (preset and type(preset) == "table") then
|
||||
frame.options.horizontal_border_size_offset = preset.horizontal_border_size_offset
|
||||
applyPreset(frame, preset)
|
||||
else
|
||||
applyPreset(frame, defaultPreset)
|
||||
end
|
||||
end
|
||||
|
||||
---test case:
|
||||
C_Timer.After(1, function()
|
||||
|
||||
if true then return end
|
||||
|
||||
local DF = DetailsFramework
|
||||
|
||||
local parent = UIParent
|
||||
local name = "NewRoundedCornerFrame"
|
||||
local optionsTable = {
|
||||
use_titlebar = true,
|
||||
use_scalebar = true,
|
||||
title = "Test",
|
||||
scale = 1.0,
|
||||
}
|
||||
|
||||
---@type df_roundedpanel
|
||||
local frame = _G[name] or DF:CreateRoundedPanel(parent, name, optionsTable)
|
||||
frame:SetSize(800, 600)
|
||||
frame:SetPoint("center", parent, "center", 0, 0)
|
||||
|
||||
frame:SetColor(.1, .1, .1, 1)
|
||||
frame:SetTitleBarColor(.2, .2, .2, .5)
|
||||
frame:SetBorderCornerColor(.2, .2, .2, .5)
|
||||
frame:SetRoundness(0)
|
||||
|
||||
local radiusSlider = DF:CreateSlider(frame, 120, 14, 0, 15, 1, frame.cornerRoundness, false, "RadiusBar", nil, nil, DF:GetTemplate("slider", "OPTIONS_SLIDER_TEMPLATE"))
|
||||
radiusSlider:SetHook("OnValueChange", function(self, fixedValue, value)
|
||||
value = floor(value)
|
||||
if (frame.cornerRoundness == value) then
|
||||
return
|
||||
end
|
||||
frame:SetRoundness(value)
|
||||
end)
|
||||
|
||||
local radiusText = frame:CreateFontString(nil, "overlay", "GameFontNormal")
|
||||
radiusText:SetText("Radius:")
|
||||
radiusText:SetPoint("bottomleft", radiusSlider.widget, "topleft", 0, 0)
|
||||
radiusSlider:SetPoint(10, -100)
|
||||
end)
|
||||
@@ -1,5 +1,4 @@
|
||||
|
||||
--stopped doing the duplicate savedTable
|
||||
|
||||
local detailsFramework = _G ["DetailsFramework"]
|
||||
if (not detailsFramework or not DetailsFrameworkCanLoad) then
|
||||
|
||||
@@ -10,6 +10,11 @@ local unpack = table.unpack or _G.unpack
|
||||
--make a namespace for schedules
|
||||
DF.Schedules = DF.Schedules or {}
|
||||
|
||||
DF.Schedules.AfterCombatSchedules = {
|
||||
withId = {},
|
||||
withoutId = {},
|
||||
}
|
||||
|
||||
---@class df_schedule : table
|
||||
---@field NewTicker fun(time: number, callback: function, ...: any): timer
|
||||
---@field NewLooper fun(time: number, callback: function, loopAmount: number, loopEndCallback: function?, checkPointCallback: function?, ...: any): timer
|
||||
@@ -18,6 +23,24 @@ DF.Schedules = DF.Schedules or {}
|
||||
---@field After fun(time: number, callback: function)
|
||||
---@field SetName fun(object: timer, name: string)
|
||||
---@field RunNextTick fun(callback: function)
|
||||
---@field AfterCombat fun(callback:function, id:any, ...: any)
|
||||
|
||||
local eventFrame = CreateFrame("frame")
|
||||
eventFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
|
||||
eventFrame:SetScript("OnEvent", function(self, event)
|
||||
if (event == "PLAYER_REGEN_ENABLED") then
|
||||
for _, schedule in ipairs(DF.Schedules.AfterCombatSchedules.withoutId) do
|
||||
xpcall(schedule.callback, geterrorhandler(), unpack(schedule.payload))
|
||||
end
|
||||
|
||||
for _, schedule in pairs(DF.Schedules.AfterCombatSchedules.withId) do
|
||||
xpcall(schedule.callback, geterrorhandler(), unpack(schedule.payload))
|
||||
end
|
||||
|
||||
table.wipe(DF.Schedules.AfterCombatSchedules.withoutId)
|
||||
table.wipe(DF.Schedules.AfterCombatSchedules.withId)
|
||||
end
|
||||
end)
|
||||
|
||||
local triggerScheduledLoop = function(tickerObject)
|
||||
if (tickerObject:IsCancelled()) then
|
||||
@@ -128,6 +151,31 @@ function DF.Schedules.Cancel(tickerObject)
|
||||
end
|
||||
end
|
||||
|
||||
--schedule a task to be executed when the player leaves combat
|
||||
function DF.Schedules.AfterCombat(callback, id, ...)
|
||||
local bInCombatLockdown = UnitAffectingCombat("player") or InCombatLockdown()
|
||||
|
||||
if (not bInCombatLockdown) then
|
||||
xpcall(callback, geterrorhandler(), ...)
|
||||
return
|
||||
end
|
||||
|
||||
local payload = {...}
|
||||
|
||||
if (id) then
|
||||
DF.Schedules.AfterCombatSchedules.withId[id] = {
|
||||
callback = callback,
|
||||
payload = payload,
|
||||
id = id,
|
||||
}
|
||||
else
|
||||
table.insert(DF.Schedules.AfterCombatSchedules.withoutId, {
|
||||
callback = callback,
|
||||
payload = payload,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
--schedule a task with an interval of @time without payload
|
||||
function DF.Schedules.After(time, callback)
|
||||
C_Timer.After(time, callback)
|
||||
|
||||
+196
-195
@@ -1,233 +1,234 @@
|
||||
|
||||
--note: this scroll bar is using legacy code and shouldn't be used on creating new stuff
|
||||
|
||||
local DF = _G["DetailsFramework"]
|
||||
if (not DF or not DetailsFrameworkCanLoad) then
|
||||
local detailsFramework = _G["DetailsFramework"]
|
||||
if (not detailsFramework or not DetailsFrameworkCanLoad) then
|
||||
return
|
||||
end
|
||||
|
||||
function DF:CreateScrollBar(master, scrollContainer, x, y)
|
||||
return DF:NewScrollBar(master, scrollContainer, x, y)
|
||||
end
|
||||
--note: this scroll bar is using legacy code and shouldn't be used on creating new stuff
|
||||
do
|
||||
function detailsFramework:CreateScrollBar(master, scrollContainer, x, y)
|
||||
return detailsFramework:NewScrollBar(master, scrollContainer, x, y)
|
||||
end
|
||||
|
||||
function DF:NewScrollBar(parent, scrollContainer, x, y)
|
||||
local newSlider = CreateFrame("Slider", nil, parent, "BackdropTemplate")
|
||||
newSlider.scrollMax = 560
|
||||
function detailsFramework:NewScrollBar(parent, scrollContainer, x, y)
|
||||
local newSlider = CreateFrame("Slider", nil, parent, "BackdropTemplate")
|
||||
newSlider.scrollMax = 560
|
||||
|
||||
newSlider:SetPoint("TOPLEFT", parent, "TOPRIGHT", x, y)
|
||||
newSlider.ativo = true
|
||||
newSlider:SetPoint("TOPLEFT", parent, "TOPRIGHT", x, y)
|
||||
newSlider.ativo = true
|
||||
|
||||
newSlider.bg = newSlider:CreateTexture(nil, "BACKGROUND")
|
||||
newSlider.bg:SetAllPoints(true)
|
||||
newSlider.bg:SetTexture(0, 0, 0, 0)
|
||||
newSlider.bg = newSlider:CreateTexture(nil, "BACKGROUND")
|
||||
newSlider.bg:SetAllPoints(true)
|
||||
newSlider.bg:SetTexture(0, 0, 0, 0)
|
||||
|
||||
newSlider.thumb = newSlider:CreateTexture(nil, "OVERLAY")
|
||||
newSlider.thumb:SetTexture("Interface\\Buttons\\UI-ScrollBar-Knob")
|
||||
newSlider.thumb:SetSize(29, 30)
|
||||
newSlider:SetThumbTexture(newSlider.thumb)
|
||||
newSlider:SetOrientation("VERTICAL")
|
||||
newSlider:SetSize(16, 100)
|
||||
newSlider:SetMinMaxValues(0, newSlider.scrollMax)
|
||||
newSlider:SetValue(0)
|
||||
newSlider.ultimo = 0
|
||||
newSlider.thumb = newSlider:CreateTexture(nil, "OVERLAY")
|
||||
newSlider.thumb:SetTexture("Interface\\Buttons\\UI-ScrollBar-Knob")
|
||||
newSlider.thumb:SetSize(29, 30)
|
||||
newSlider:SetThumbTexture(newSlider.thumb)
|
||||
newSlider:SetOrientation("VERTICAL")
|
||||
newSlider:SetSize(16, 100)
|
||||
newSlider:SetMinMaxValues(0, newSlider.scrollMax)
|
||||
newSlider:SetValue(0)
|
||||
newSlider.ultimo = 0
|
||||
|
||||
local upButton = CreateFrame("Button", nil, parent,"BackdropTemplate")
|
||||
local upButton = CreateFrame("Button", nil, parent,"BackdropTemplate")
|
||||
|
||||
upButton:SetPoint("BOTTOM", newSlider, "TOP", 0, -12)
|
||||
upButton.x = 0
|
||||
upButton.y = -12
|
||||
upButton:SetPoint("BOTTOM", newSlider, "TOP", 0, -12)
|
||||
upButton.x = 0
|
||||
upButton.y = -12
|
||||
|
||||
upButton:SetWidth(29)
|
||||
upButton:SetHeight(32)
|
||||
upButton:SetNormalTexture("Interface\\BUTTONS\\UI-ScrollBar-ScrollUpButton-Up")
|
||||
upButton:SetPushedTexture("Interface\\BUTTONS\\UI-ScrollBar-ScrollUpButton-Down")
|
||||
upButton:SetDisabledTexture("Interface\\BUTTONS\\UI-ScrollBar-ScrollUpButton-Disabled")
|
||||
upButton:Show()
|
||||
upButton:Disable()
|
||||
upButton:SetWidth(29)
|
||||
upButton:SetHeight(32)
|
||||
upButton:SetNormalTexture("Interface\\BUTTONS\\UI-ScrollBar-ScrollUpButton-Up")
|
||||
upButton:SetPushedTexture("Interface\\BUTTONS\\UI-ScrollBar-ScrollUpButton-Down")
|
||||
upButton:SetDisabledTexture("Interface\\BUTTONS\\UI-ScrollBar-ScrollUpButton-Disabled")
|
||||
upButton:Show()
|
||||
upButton:Disable()
|
||||
|
||||
local downDutton = CreateFrame("Button", nil, parent,"BackdropTemplate")
|
||||
downDutton:SetPoint("TOP", newSlider, "BOTTOM", 0, 12)
|
||||
downDutton.x = 0
|
||||
downDutton.y = 12
|
||||
local downDutton = CreateFrame("Button", nil, parent,"BackdropTemplate")
|
||||
downDutton:SetPoint("TOP", newSlider, "BOTTOM", 0, 12)
|
||||
downDutton.x = 0
|
||||
downDutton.y = 12
|
||||
|
||||
downDutton:SetWidth(29)
|
||||
downDutton:SetHeight(32)
|
||||
downDutton:SetNormalTexture("Interface\\BUTTONS\\UI-ScrollBar-ScrollDownButton-Up")
|
||||
downDutton:SetPushedTexture("Interface\\BUTTONS\\UI-ScrollBar-ScrollDownButton-Down")
|
||||
downDutton:SetDisabledTexture("Interface\\BUTTONS\\UI-ScrollBar-ScrollDownButton-Disabled")
|
||||
downDutton:Show()
|
||||
downDutton:Disable()
|
||||
downDutton:SetWidth(29)
|
||||
downDutton:SetHeight(32)
|
||||
downDutton:SetNormalTexture("Interface\\BUTTONS\\UI-ScrollBar-ScrollDownButton-Up")
|
||||
downDutton:SetPushedTexture("Interface\\BUTTONS\\UI-ScrollBar-ScrollDownButton-Down")
|
||||
downDutton:SetDisabledTexture("Interface\\BUTTONS\\UI-ScrollBar-ScrollDownButton-Disabled")
|
||||
downDutton:Show()
|
||||
downDutton:Disable()
|
||||
|
||||
parent.baixo = downDutton
|
||||
parent.cima = upButton
|
||||
parent.slider = newSlider
|
||||
parent.baixo = downDutton
|
||||
parent.cima = upButton
|
||||
parent.slider = newSlider
|
||||
|
||||
downDutton:SetScript("OnMouseDown", function(self)
|
||||
if (not newSlider:IsEnabled()) then
|
||||
return
|
||||
end
|
||||
downDutton:SetScript("OnMouseDown", function(self)
|
||||
if (not newSlider:IsEnabled()) then
|
||||
return
|
||||
end
|
||||
|
||||
local current = newSlider:GetValue()
|
||||
local minValue, maxValue = newSlider:GetMinMaxValues()
|
||||
if (current + 5 < maxValue) then
|
||||
newSlider:SetValue(current + 5)
|
||||
else
|
||||
newSlider:SetValue(maxValue)
|
||||
end
|
||||
self.precionado = true
|
||||
self.last_up = -0.3
|
||||
self:SetScript("OnUpdate", function(self, elapsed)
|
||||
self.last_up = self.last_up + elapsed
|
||||
if (self.last_up > 0.03) then
|
||||
self.last_up = 0
|
||||
local current = newSlider:GetValue()
|
||||
local current = newSlider:GetValue()
|
||||
local minValue, maxValue = newSlider:GetMinMaxValues()
|
||||
if (current + 5 < maxValue) then
|
||||
newSlider:SetValue(current + 5)
|
||||
else
|
||||
newSlider:SetValue(maxValue)
|
||||
end
|
||||
self.precionado = true
|
||||
self.last_up = -0.3
|
||||
self:SetScript("OnUpdate", function(self, elapsed)
|
||||
self.last_up = self.last_up + elapsed
|
||||
if (self.last_up > 0.03) then
|
||||
self.last_up = 0
|
||||
local current = newSlider:GetValue()
|
||||
local minValue, maxValue = newSlider:GetMinMaxValues()
|
||||
if (current + 2 < maxValue) then
|
||||
newSlider:SetValue(current + 2)
|
||||
else
|
||||
newSlider:SetValue(maxValue)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
downDutton:SetScript("OnMouseUp", function(self)
|
||||
self.precionado = false
|
||||
self:SetScript("OnUpdate", nil)
|
||||
end)
|
||||
|
||||
upButton:SetScript("OnMouseDown", function(self)
|
||||
if (not newSlider:IsEnabled()) then
|
||||
return
|
||||
end
|
||||
|
||||
local current = newSlider:GetValue()
|
||||
if (current - 5 > 0) then
|
||||
newSlider:SetValue(current - 5)
|
||||
else
|
||||
newSlider:SetValue(0)
|
||||
end
|
||||
|
||||
self.precionado = true
|
||||
self.last_up = -0.3
|
||||
self:SetScript("OnUpdate", function(self, elapsed)
|
||||
self.last_up = self.last_up + elapsed
|
||||
if (self.last_up > 0.03) then
|
||||
self.last_up = 0
|
||||
local current = newSlider:GetValue()
|
||||
if (current - 2 > 0) then
|
||||
newSlider:SetValue(current - 2)
|
||||
else
|
||||
newSlider:SetValue(0)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
upButton:SetScript("OnMouseUp", function(self)
|
||||
self.precionado = false
|
||||
self:SetScript("OnUpdate", nil)
|
||||
end)
|
||||
|
||||
upButton:SetScript("OnEnable", function(self)
|
||||
local current = newSlider:GetValue()
|
||||
if (current == 0) then
|
||||
upButton:Disable()
|
||||
end
|
||||
end)
|
||||
|
||||
newSlider:SetScript("OnValueChanged", function(self)
|
||||
local current = self:GetValue()
|
||||
parent:SetVerticalScroll(current)
|
||||
|
||||
local minValue, maxValue = newSlider:GetMinMaxValues()
|
||||
|
||||
if (current == minValue) then
|
||||
upButton:Disable()
|
||||
elseif (not upButton:IsEnabled()) then
|
||||
upButton:Enable()
|
||||
end
|
||||
|
||||
if (current == maxValue) then
|
||||
downDutton:Disable()
|
||||
elseif (not downDutton:IsEnabled()) then
|
||||
downDutton:Enable()
|
||||
end
|
||||
end)
|
||||
|
||||
newSlider:SetScript("OnShow", function(self)
|
||||
upButton:Show()
|
||||
downDutton:Show()
|
||||
end)
|
||||
|
||||
newSlider:SetScript("OnDisable", function(self)
|
||||
upButton:Disable()
|
||||
downDutton:Disable()
|
||||
end)
|
||||
|
||||
newSlider:SetScript("OnEnable", function(self)
|
||||
upButton:Enable()
|
||||
downDutton:Enable()
|
||||
end)
|
||||
|
||||
parent:SetScript("OnMouseWheel", function(self, delta)
|
||||
if (not newSlider:IsEnabled()) then
|
||||
return
|
||||
end
|
||||
|
||||
local current = newSlider:GetValue()
|
||||
if (delta < 0) then
|
||||
local minValue, maxValue = newSlider:GetMinMaxValues()
|
||||
if (current + 2 < maxValue) then
|
||||
newSlider:SetValue(current + 2)
|
||||
if (current + (parent.wheel_jump or 20) < maxValue) then
|
||||
newSlider:SetValue(current + (parent.wheel_jump or 20))
|
||||
else
|
||||
newSlider:SetValue(maxValue)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
downDutton:SetScript("OnMouseUp", function(self)
|
||||
self.precionado = false
|
||||
self:SetScript("OnUpdate", nil)
|
||||
end)
|
||||
|
||||
upButton:SetScript("OnMouseDown", function(self)
|
||||
if (not newSlider:IsEnabled()) then
|
||||
return
|
||||
end
|
||||
|
||||
local current = newSlider:GetValue()
|
||||
if (current - 5 > 0) then
|
||||
newSlider:SetValue(current - 5)
|
||||
else
|
||||
newSlider:SetValue(0)
|
||||
end
|
||||
|
||||
self.precionado = true
|
||||
self.last_up = -0.3
|
||||
self:SetScript("OnUpdate", function(self, elapsed)
|
||||
self.last_up = self.last_up + elapsed
|
||||
if (self.last_up > 0.03) then
|
||||
self.last_up = 0
|
||||
local current = newSlider:GetValue()
|
||||
if (current - 2 > 0) then
|
||||
newSlider:SetValue(current - 2)
|
||||
elseif (delta > 0) then
|
||||
if (current + (parent.wheel_jump or 20) > 0) then
|
||||
newSlider:SetValue(current - (parent.wheel_jump or 20))
|
||||
else
|
||||
newSlider:SetValue(0)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
upButton:SetScript("OnMouseUp", function(self)
|
||||
self.precionado = false
|
||||
self:SetScript("OnUpdate", nil)
|
||||
end)
|
||||
|
||||
upButton:SetScript("OnEnable", function(self)
|
||||
local current = newSlider:GetValue()
|
||||
if (current == 0) then
|
||||
upButton:Disable()
|
||||
end
|
||||
end)
|
||||
|
||||
newSlider:SetScript("OnValueChanged", function(self)
|
||||
local current = self:GetValue()
|
||||
parent:SetVerticalScroll(current)
|
||||
|
||||
local minValue, maxValue = newSlider:GetMinMaxValues()
|
||||
|
||||
if (current == minValue) then
|
||||
upButton:Disable()
|
||||
elseif (not upButton:IsEnabled()) then
|
||||
upButton:Enable()
|
||||
function newSlider:Altura(height)
|
||||
self:SetHeight(height)
|
||||
end
|
||||
|
||||
if (current == maxValue) then
|
||||
downDutton:Disable()
|
||||
elseif (not downDutton:IsEnabled()) then
|
||||
downDutton:Enable()
|
||||
end
|
||||
end)
|
||||
|
||||
newSlider:SetScript("OnShow", function(self)
|
||||
upButton:Show()
|
||||
downDutton:Show()
|
||||
end)
|
||||
|
||||
newSlider:SetScript("OnDisable", function(self)
|
||||
upButton:Disable()
|
||||
downDutton:Disable()
|
||||
end)
|
||||
|
||||
newSlider:SetScript("OnEnable", function(self)
|
||||
upButton:Enable()
|
||||
downDutton:Enable()
|
||||
end)
|
||||
|
||||
parent:SetScript("OnMouseWheel", function(self, delta)
|
||||
if (not newSlider:IsEnabled()) then
|
||||
return
|
||||
end
|
||||
|
||||
local current = newSlider:GetValue()
|
||||
if (delta < 0) then
|
||||
local minValue, maxValue = newSlider:GetMinMaxValues()
|
||||
if (current + (parent.wheel_jump or 20) < maxValue) then
|
||||
newSlider:SetValue(current + (parent.wheel_jump or 20))
|
||||
else
|
||||
newSlider:SetValue(maxValue)
|
||||
end
|
||||
elseif (delta > 0) then
|
||||
if (current + (parent.wheel_jump or 20) > 0) then
|
||||
newSlider:SetValue(current - (parent.wheel_jump or 20))
|
||||
else
|
||||
function newSlider:Update(desativar)
|
||||
if (desativar) then
|
||||
newSlider:Disable()
|
||||
newSlider:SetValue(0)
|
||||
newSlider.ativo = false
|
||||
parent:EnableMouseWheel(false)
|
||||
return
|
||||
end
|
||||
|
||||
self.scrollMax = scrollContainer:GetHeight() - parent:GetHeight()
|
||||
if (self.scrollMax > 0) then
|
||||
newSlider:SetMinMaxValues(0, self.scrollMax)
|
||||
if (not newSlider.ativo) then
|
||||
newSlider:Enable()
|
||||
newSlider.ativo = true
|
||||
parent:EnableMouseWheel(true)
|
||||
end
|
||||
else
|
||||
newSlider:Disable()
|
||||
newSlider:SetValue(0)
|
||||
newSlider.ativo = false
|
||||
parent:EnableMouseWheel(false)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
function newSlider:Altura(height)
|
||||
self:SetHeight(height)
|
||||
end
|
||||
|
||||
function newSlider:Update(desativar)
|
||||
if (desativar) then
|
||||
newSlider:Disable()
|
||||
newSlider:SetValue(0)
|
||||
newSlider.ativo = false
|
||||
parent:EnableMouseWheel(false)
|
||||
return
|
||||
function newSlider:cimaPoint(x, y)
|
||||
upButton:SetPoint("BOTTOM", newSlider, "TOP", x, y - 12)
|
||||
end
|
||||
|
||||
self.scrollMax = scrollContainer:GetHeight() - parent:GetHeight()
|
||||
if (self.scrollMax > 0) then
|
||||
newSlider:SetMinMaxValues(0, self.scrollMax)
|
||||
if (not newSlider.ativo) then
|
||||
newSlider:Enable()
|
||||
newSlider.ativo = true
|
||||
parent:EnableMouseWheel(true)
|
||||
end
|
||||
else
|
||||
newSlider:Disable()
|
||||
newSlider:SetValue(0)
|
||||
newSlider.ativo = false
|
||||
parent:EnableMouseWheel(false)
|
||||
function newSlider:baixoPoint(x, y)
|
||||
downDutton:SetPoint("TOP", newSlider, "BOTTOM", x, y + 12)
|
||||
end
|
||||
end
|
||||
|
||||
function newSlider:cimaPoint(x, y)
|
||||
upButton:SetPoint("BOTTOM", newSlider, "TOP", x, y - 12)
|
||||
return newSlider
|
||||
end
|
||||
|
||||
function newSlider:baixoPoint(x, y)
|
||||
downDutton:SetPoint("TOP", newSlider, "BOTTOM", x, y + 12)
|
||||
end
|
||||
|
||||
return newSlider
|
||||
end
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
|
||||
--documentation for scrollbox.lua
|
||||
|
||||
--a scrollbox is a frame with a scrollbar and lines, these lines can be used to show data or show more frames in the case of a grid frame
|
||||
--a grid of frames if a frame with lines and columns, each line can have multiple columns, a column is a frame
|
||||
|
||||
--------Start of the Grid Scroll Box Example--------
|
||||
|
||||
local parent = UIParent
|
||||
local name = "GridScrollBoxExample"
|
||||
|
||||
--declare a function which receives a frame and the data which will be used to refresh it
|
||||
local refreshOptionFunc = function(optionButton, data)
|
||||
optionButton.text:SetText(data.text)
|
||||
optionButton:SetScript("OnClick", function(self) print("clicked option " .. data.text) end)
|
||||
optionButton:Show()
|
||||
end
|
||||
|
||||
--declare a function to create a column within a scroll line
|
||||
--this function will receive the line, the line index within the scrollbox and the column index within the line
|
||||
local createOptionFrameFunc = function(line, lineIndex, columnIndex)
|
||||
local optionButton = CreateFrame("button", "$parentOptionFrame" .. lineIndex .. columnIndex, line)
|
||||
optionButton:SetSize(100, 20)
|
||||
optionButton.text = optionButton:CreateFontString(nil, "overlay", "GameFontNormal")
|
||||
optionButton.text:SetPoint("center", optionButton, "center", 0, 0)
|
||||
optionButton.text:SetText("Option " .. lineIndex .. columnIndex)
|
||||
|
||||
local highlightTexture = optionButton:CreateTexture(nil, "highlight")
|
||||
highlightTexture:SetAllPoints()
|
||||
highlightTexture:SetColorTexture(1, 1, 1, 0.2)
|
||||
|
||||
DetailsFramework:ApplyStandardBackdrop(optionButton)
|
||||
|
||||
return optionButton
|
||||
end
|
||||
|
||||
--when creatin a grid scrollbox, some of the settings for the grid is clared into a table to be passed as an argument
|
||||
local options = {
|
||||
width = 600,
|
||||
height = 400,
|
||||
--amount of horizontal lines
|
||||
line_amount = 12,
|
||||
--amount of columns per line
|
||||
columns_per_line = 4,
|
||||
--height of each line
|
||||
line_height = 30,
|
||||
auto_amount = false,
|
||||
no_scroll = false,
|
||||
no_backdrop = false,
|
||||
}
|
||||
|
||||
--grid scrollbox data, can also be set with gridScrollBox:SetData(data) if the data is only available later on
|
||||
--the data table is passed within the optionFrame when calling the refresh function
|
||||
local data = {
|
||||
{text = "1"}, {text = "2"}, {text = "3"}, {text = "4"}, {text = "5"}, {text = "6"}, {text = "7"}, {text = "8"}, {text = "9"}, {text = "10"},
|
||||
{text = "11"}, {text = "12"}, {text = "13"}, {text = "14"}, {text = "15"}, {text = "16"}, {text = "17"}, {text = "18"}, {text = "19"}, {text = "20"},
|
||||
{text = "21"}, {text = "22"}, {text = "23"}, {text = "24"}, {text = "25"}, {text = "26"}, {text = "27"}, {text = "28"}, {text = "29"}, {text = "30"},
|
||||
{text = "31"}, {text = "32"}, {text = "33"}, {text = "34"}, {text = "35"}, {text = "36"}, {text = "37"}, {text = "38"}, {text = "39"}, {text = "40"},
|
||||
{text = "41"}, {text = "42"}, {text = "43"}, {text = "44"}, {text = "45"}, {text = "46"}, {text = "47"}, {text = "48"}, {text = "49"}, {text = "50"},
|
||||
{text = "51"}, {text = "52"}, {text = "53"}, {text = "54"}, {text = "55"}, {text = "56"}, {text = "57"}, {text = "58"}, {text = "59"}, {text = "60"},
|
||||
{text = "61"}, {text = "62"}, {text = "63"}, {text = "64"}, {text = "65"}, {text = "66"}, {text = "67"}, {text = "68"}, {text = "69"}, {text = "70"},
|
||||
{text = "71"}, {text = "72"}, {text = "73"}, {text = "74"}, {text = "75"}, {text = "76"}, {text = "77"}, {text = "78"}, {text = "79"}, {text = "80"},
|
||||
{text = "81"}, {text = "82"}, {text = "83"}, {text = "84"}, {text = "85"}, {text = "86"}, {text = "87"}, {text = "88"}, {text = "89"}, {text = "90"},
|
||||
{text = "91"}, {text = "92"}, {text = "93"}, {text = "94"}, {text = "95"}, {text = "96"}, {text = "97"}, {text = "98"}, {text = "99"}, {text = "100"},
|
||||
}
|
||||
|
||||
--create the grid scrollbox
|
||||
local gridScrollBox = DetailsFramework:CreateGridScrollBox(parent, name, refreshOptionFunc, data, createOptionFrameFunc, options)
|
||||
gridScrollBox:SetPoint("center", parent, "center", 0, 0)
|
||||
gridScrollBox:Refresh()
|
||||
|
||||
--------End of the Grid Scroll Box Example--------
|
||||
@@ -0,0 +1,622 @@
|
||||
|
||||
---@type detailsframework
|
||||
local detailsFramework = _G["DetailsFramework"]
|
||||
if (not detailsFramework or not DetailsFrameworkCanLoad) then
|
||||
return
|
||||
end
|
||||
|
||||
local CreateFrame = CreateFrame
|
||||
local GetSpellInfo = GetSpellInfo
|
||||
local GameTooltip = GameTooltip
|
||||
local unpack = unpack
|
||||
|
||||
---mixin to use with DetailsFramework:Mixin(table, detailsFramework.SortFunctions)
|
||||
---add methods to be used on scrollframes
|
||||
---@class df_scrollboxmixin
|
||||
detailsFramework.ScrollBoxFunctions = {
|
||||
--set a function to run right before the refresh function (scroll:Refresh())
|
||||
--this function receives the same parameters as the refresh function
|
||||
SetPreRefreshFunction = function(self, func)
|
||||
self.pre_refresh_func = func
|
||||
end,
|
||||
|
||||
---refresh the scrollbox by resetting all lines created with :CreateLine(), then calling the refresh_func which was set at :CreateScrollBox()
|
||||
---@param self table
|
||||
---@return table
|
||||
Refresh = function(self)
|
||||
--hide all frames and tag as not in use
|
||||
self._LinesInUse = 0
|
||||
for index, frame in ipairs(self.Frames) do
|
||||
if (not self.DontHideChildrenOnPreRefresh) then
|
||||
frame:Hide()
|
||||
end
|
||||
frame._InUse = nil
|
||||
end
|
||||
|
||||
local offset = 0
|
||||
if (self.IsFauxScroll) then
|
||||
self:UpdateFaux(#self.data, self.LineAmount, self.LineHeight)
|
||||
offset = self:GetOffsetFaux()
|
||||
end
|
||||
|
||||
if (self.pre_refresh_func) then
|
||||
detailsFramework:Dispatch(self.pre_refresh_func, self, self.data, offset, self.LineAmount)
|
||||
end
|
||||
|
||||
--call the refresh function
|
||||
detailsFramework:Dispatch(self.refresh_func, self, self.data, offset, self.LineAmount)
|
||||
|
||||
--hide all frames that are not in use
|
||||
for index, frame in ipairs(self.Frames) do
|
||||
if (not frame._InUse) then
|
||||
frame:Hide()
|
||||
else
|
||||
frame:Show()
|
||||
end
|
||||
end
|
||||
|
||||
self:Show()
|
||||
|
||||
local frameName = self:GetName()
|
||||
if (frameName) then
|
||||
if (self.HideScrollBar) then
|
||||
local scrollBar = _G[frameName .. "ScrollBar"]
|
||||
if (scrollBar) then
|
||||
scrollBar:Hide()
|
||||
end
|
||||
else
|
||||
--[=[ --maybe in the future I visit this again
|
||||
local scrollBar = _G[frameName .. "ScrollBar"]
|
||||
local height = self:GetHeight()
|
||||
local totalLinesRequired = #self.data
|
||||
local linesShown = self._LinesInUse
|
||||
|
||||
local percent = linesShown / totalLinesRequired
|
||||
local thumbHeight = height * percent
|
||||
scrollBar.ThumbTexture:SetSize(12, thumbHeight)
|
||||
print("thumbHeight:", thumbHeight)
|
||||
--]=]
|
||||
end
|
||||
end
|
||||
return self.Frames
|
||||
end,
|
||||
|
||||
OnVerticalScroll = function(self, offset)
|
||||
self:OnVerticalScrollFaux(offset, self.LineHeight, self.Refresh)
|
||||
return true
|
||||
end,
|
||||
|
||||
---create a line within the scrollbox
|
||||
---@param self table is the scrollbox
|
||||
---@param func function|nil function to create the line object, this function will receive the line index as argument and return a table with the line object
|
||||
---@return table line object (table)
|
||||
CreateLine = function(self, func)
|
||||
if (not func) then
|
||||
func = self.CreateLineFunc
|
||||
end
|
||||
|
||||
local okay, newLine = pcall(func, self, #self.Frames+1)
|
||||
if (okay) then
|
||||
if (not newLine) then
|
||||
error("ScrollFrame:CreateLine() function did not returned a line, use: 'return line'")
|
||||
end
|
||||
table.insert(self.Frames, newLine)
|
||||
newLine.Index = #self.Frames
|
||||
return newLine
|
||||
else
|
||||
error("ScrollFrame:CreateLine() error on creating a line: " .. newLine)
|
||||
end
|
||||
end,
|
||||
|
||||
CreateLines = function(self, callback, lineAmount)
|
||||
for i = 1, lineAmount do
|
||||
self:CreateLine(callback)
|
||||
end
|
||||
end,
|
||||
|
||||
GetLine = function(self, lineIndex)
|
||||
local line = self.Frames[lineIndex]
|
||||
if (line) then
|
||||
line._InUse = true
|
||||
end
|
||||
|
||||
self._LinesInUse = self._LinesInUse + 1
|
||||
return line
|
||||
end,
|
||||
|
||||
SetData = function(self, data)
|
||||
self.data = data
|
||||
if (self.OnSetData) then
|
||||
detailsFramework:CoreDispatch((self:GetName() or "ScrollBox") .. ":OnSetData()", self.OnSetData, self, self.data)
|
||||
end
|
||||
end,
|
||||
|
||||
GetData = function(self)
|
||||
return self.data
|
||||
end,
|
||||
|
||||
GetFrames = function(self)
|
||||
return self.Frames
|
||||
end,
|
||||
|
||||
GetLines = function(self) --alias of GetFrames
|
||||
return self.Frames
|
||||
end,
|
||||
|
||||
GetNumFramesCreated = function(self)
|
||||
return #self.Frames
|
||||
end,
|
||||
|
||||
GetNumFramesShown = function(self)
|
||||
return self.LineAmount
|
||||
end,
|
||||
|
||||
SetNumFramesShown = function(self, newAmount)
|
||||
--hide frames which won't be used
|
||||
if (newAmount < #self.Frames) then
|
||||
for i = newAmount+1, #self.Frames do
|
||||
self.Frames[i]:Hide()
|
||||
end
|
||||
end
|
||||
--set the new amount
|
||||
self.LineAmount = newAmount
|
||||
end,
|
||||
|
||||
SetFramesHeight = function(self, height)
|
||||
self.LineHeight = height
|
||||
self:OnSizeChanged()
|
||||
self:Refresh()
|
||||
end,
|
||||
|
||||
OnSizeChanged = function(self)
|
||||
if (self.ReajustNumFrames) then
|
||||
--how many lines the scroll can show
|
||||
local amountOfFramesToShow = math.floor(self:GetHeight() / self.LineHeight)
|
||||
|
||||
--how many lines the scroll already have
|
||||
local totalFramesCreated = self:GetNumFramesCreated()
|
||||
|
||||
--how many lines are current shown
|
||||
local totalFramesShown = self:GetNumFramesShown()
|
||||
|
||||
--the amount of frames increased
|
||||
if (amountOfFramesToShow > totalFramesShown) then
|
||||
for i = totalFramesShown+1, amountOfFramesToShow do
|
||||
--check if need to create a new line
|
||||
if (i > totalFramesCreated) then
|
||||
self:CreateLine(self.CreateLineFunc)
|
||||
end
|
||||
end
|
||||
|
||||
--the amount of frames decreased
|
||||
elseif (amountOfFramesToShow < totalFramesShown) then
|
||||
--hide all frames above the new amount to show
|
||||
for i = totalFramesCreated, amountOfFramesToShow, -1 do
|
||||
if (self.Frames[i]) then
|
||||
self.Frames[i]:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--set the new amount of frames
|
||||
self:SetNumFramesShown(amountOfFramesToShow)
|
||||
--refresh lines
|
||||
self:Refresh()
|
||||
end
|
||||
end,
|
||||
|
||||
--moved functions from blizzard faux scroll that are called from insecure code environment
|
||||
--this reduces the amount of taints while using the faux scroll frame
|
||||
GetOffsetFaux = function(self)
|
||||
return self.offset or 0
|
||||
end,
|
||||
|
||||
OnVerticalScrollFaux = function(self, value, lineHeight, updateFunction)
|
||||
local scrollbar = self:GetChildFramesFaux()
|
||||
scrollbar:SetValue(value)
|
||||
self.offset = math.floor((value / lineHeight) + 0.5)
|
||||
|
||||
if (updateFunction) then
|
||||
updateFunction(self)
|
||||
end
|
||||
end,
|
||||
|
||||
GetChildFramesFaux = function(frame)
|
||||
local frameName = frame:GetName();
|
||||
if frameName then
|
||||
return _G[ frameName.."ScrollBar" ], _G[ frameName.."ScrollChildFrame" ], _G[ frameName.."ScrollBarScrollUpButton" ], _G[ frameName.."ScrollBarScrollDownButton" ];
|
||||
else
|
||||
return frame.ScrollBar, frame.ScrollChildFrame, frame.ScrollBar.ScrollUpButton, frame.ScrollBar.ScrollDownButton;
|
||||
end
|
||||
end,
|
||||
|
||||
UpdateFaux = function(frame, numItems, numToDisplay, buttonHeight, button, smallWidth, bigWidth, highlightFrame, smallHighlightWidth, bigHighlightWidth, alwaysShowScrollBar)
|
||||
local scrollBar, scrollChildFrame, scrollUpButton, scrollDownButton = frame:GetChildFramesFaux();
|
||||
-- If more than one screen full of items then show the scrollbar
|
||||
local showScrollBar;
|
||||
if ( numItems > numToDisplay or alwaysShowScrollBar ) then
|
||||
frame:Show();
|
||||
showScrollBar = 1;
|
||||
else
|
||||
scrollBar:SetValue(0);
|
||||
frame:Hide();
|
||||
end
|
||||
if ( frame:IsShown() ) then
|
||||
local scrollFrameHeight = 0;
|
||||
local scrollChildHeight = 0;
|
||||
|
||||
if ( numItems > 0 ) then
|
||||
scrollFrameHeight = (numItems - numToDisplay) * buttonHeight;
|
||||
scrollChildHeight = numItems * buttonHeight;
|
||||
if ( scrollFrameHeight < 0 ) then
|
||||
scrollFrameHeight = 0;
|
||||
end
|
||||
scrollChildFrame:Show();
|
||||
else
|
||||
scrollChildFrame:Hide();
|
||||
end
|
||||
local maxRange = (numItems - numToDisplay) * buttonHeight;
|
||||
if (maxRange < 0) then
|
||||
maxRange = 0;
|
||||
end
|
||||
scrollBar:SetMinMaxValues(0, maxRange);
|
||||
scrollBar:SetValueStep(buttonHeight);
|
||||
scrollBar:SetStepsPerPage(numToDisplay-1);
|
||||
scrollChildFrame:SetHeight(scrollChildHeight);
|
||||
|
||||
-- Arrow button handling
|
||||
if ( scrollBar:GetValue() == 0 ) then
|
||||
scrollUpButton:Disable();
|
||||
else
|
||||
scrollUpButton:Enable();
|
||||
end
|
||||
if ((scrollBar:GetValue() - scrollFrameHeight) == 0) then
|
||||
scrollDownButton:Disable();
|
||||
else
|
||||
scrollDownButton:Enable();
|
||||
end
|
||||
|
||||
-- Shrink because scrollbar is shown
|
||||
if ( highlightFrame ) then
|
||||
highlightFrame:SetWidth(smallHighlightWidth);
|
||||
end
|
||||
if ( button ) then
|
||||
for i=1, numToDisplay do
|
||||
_G[button..i]:SetWidth(smallWidth);
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Widen because scrollbar is hidden
|
||||
if ( highlightFrame ) then
|
||||
highlightFrame:SetWidth(bigHighlightWidth);
|
||||
end
|
||||
if ( button ) then
|
||||
for i=1, numToDisplay do
|
||||
_G[button..i]:SetWidth(bigWidth);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return showScrollBar;
|
||||
end,
|
||||
}
|
||||
|
||||
|
||||
---@class df_gridscrollbox_options : table
|
||||
---@field width number?
|
||||
---@field height number?
|
||||
---@field line_amount number?
|
||||
---@field line_height number?
|
||||
---@field columns_per_line number?
|
||||
---@field auto_amount boolean?
|
||||
---@field no_scroll boolean?
|
||||
---@field vertical_padding number?
|
||||
---@field no_backdrop boolean?
|
||||
|
||||
---@type df_gridscrollbox_options
|
||||
local grid_scrollbox_options = {
|
||||
width = 600,
|
||||
height = 400,
|
||||
line_amount = 10,
|
||||
line_height = 30,
|
||||
columns_per_line = 4,
|
||||
no_scroll = false,
|
||||
vertical_padding = 1,
|
||||
no_backdrop = false,
|
||||
}
|
||||
|
||||
---@class df_gridscrollbox : df_scrollbox
|
||||
|
||||
---create a scrollbox with a grid layout
|
||||
---@param parent frame
|
||||
---@param name string
|
||||
---@param refreshFunc function
|
||||
---@param data table
|
||||
---@param createColumnFrameFunc function
|
||||
---@param options df_gridscrollbox_options?
|
||||
---@return unknown
|
||||
function detailsFramework:CreateGridScrollBox(parent, name, refreshFunc, data, createColumnFrameFunc, options)
|
||||
options = options or {}
|
||||
|
||||
local width = options.width or grid_scrollbox_options.width
|
||||
local height = options.height or grid_scrollbox_options.height
|
||||
local lineAmount = options.line_amount or grid_scrollbox_options.line_amount
|
||||
local lineHeight = options.line_height or grid_scrollbox_options.line_height
|
||||
local columnsPerLine = options.columns_per_line or grid_scrollbox_options.columns_per_line
|
||||
local autoAmount = options.auto_amount
|
||||
local noScroll = options.no_scroll
|
||||
local noBackdrop = options.no_backdrop
|
||||
local verticalPadding = options.vertical_padding or grid_scrollbox_options.vertical_padding
|
||||
|
||||
local createLineFunc = function(scrollBox, lineIndex)
|
||||
local line = CreateFrame("frame", "$parentLine" .. lineIndex, scrollBox)
|
||||
line:SetSize(width, lineHeight)
|
||||
line:SetPoint("top", scrollBox, "top", 0, -((lineIndex-1) * (lineHeight + verticalPadding)))
|
||||
line.optionFrames = {}
|
||||
|
||||
for columnIndex = 1, columnsPerLine do
|
||||
--dispatch payload: line, lineIndex, columnIndex
|
||||
local optionFrame = createColumnFrameFunc(line, lineIndex, columnIndex)
|
||||
line.optionFrames[columnIndex] = optionFrame
|
||||
optionFrame:SetPoint("left", line, "left", (columnIndex-1) * (width/columnsPerLine), 0)
|
||||
end
|
||||
|
||||
return line
|
||||
end
|
||||
|
||||
local onSetData = function(self, data)
|
||||
local newData = {}
|
||||
|
||||
for i = 1, #data, columnsPerLine do
|
||||
local thisColumnData = {}
|
||||
|
||||
for o = 1, columnsPerLine do
|
||||
local index = i + (o-1)
|
||||
local thisData = data[index]
|
||||
if (thisData) then
|
||||
thisColumnData[#thisColumnData+1] = thisData
|
||||
end
|
||||
end
|
||||
newData[#newData+1] = thisColumnData
|
||||
end
|
||||
|
||||
self.data = newData
|
||||
end
|
||||
|
||||
local refreshGrid = function(scrollBox, thisData, offset, totalLines)
|
||||
for i = 1, totalLines do
|
||||
local index = i + offset
|
||||
local lineData = thisData[index]
|
||||
|
||||
if (lineData) then
|
||||
local line = scrollBox:GetLine(i)
|
||||
for o = 1, columnsPerLine do
|
||||
local optionFrame = line.optionFrames[o]
|
||||
local data = lineData[o]
|
||||
if (data) then
|
||||
detailsFramework:Dispatch(refreshFunc, optionFrame, data)
|
||||
optionFrame:Show()
|
||||
line:Show()
|
||||
else
|
||||
optionFrame:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local scrollBox = detailsFramework:CreateScrollBox(parent, name, refreshGrid, data, width, height, lineAmount, lineHeight, createLineFunc, autoAmount, noScroll, noBackdrop)
|
||||
scrollBox:CreateLines(createLineFunc, lineAmount)
|
||||
detailsFramework:ReskinSlider(scrollBox)
|
||||
scrollBox.OnSetData = onSetData
|
||||
onSetData(scrollBox, data)
|
||||
|
||||
return scrollBox
|
||||
end
|
||||
|
||||
|
||||
|
||||
--aura scroll box
|
||||
--default settings
|
||||
local auraScrollDefaultSettings = {
|
||||
line_height = 18,
|
||||
line_amount = 18,
|
||||
width = 300,
|
||||
height = 500,
|
||||
vertical_padding = 1,
|
||||
show_spell_tooltip = false,
|
||||
remove_icon_border = true,
|
||||
no_scroll = false,
|
||||
no_backdrop = false,
|
||||
backdrop_onenter = {.8, .8, .8, 0.2},
|
||||
backdrop_onleave = {.8, .8, .8, 0.4},
|
||||
font_size = 12,
|
||||
}
|
||||
|
||||
function detailsFramework:CreateAuraScrollBox(parent, name, refreshFunc, data, onAuraRemoveCallback, options)
|
||||
--hack the construction of the options table here, as the scrollbox is created much later
|
||||
local scrollOptions = {}
|
||||
detailsFramework.OptionsFunctions.BuildOptionsTable(scrollOptions, auraScrollDefaultSettings, options)
|
||||
options = scrollOptions.options
|
||||
|
||||
local refreshAuraLines = function(self, data, offset, totalLines)
|
||||
for i = 1, totalLines do
|
||||
local index = i + offset
|
||||
local auraTable = data[index]
|
||||
if (auraTable) then
|
||||
local line = self:GetLine(i)
|
||||
local spellId, spellName, spellIcon, lowerSpellName, flag = unpack(auraTable)
|
||||
|
||||
line.SpellID = spellId
|
||||
line.SpellName = spellName
|
||||
line.SpellNameLower = lowerSpellName
|
||||
line.SpellIcon = spellIcon
|
||||
line.Flag = flag
|
||||
|
||||
if (flag) then
|
||||
line.name:SetText(spellName)
|
||||
else
|
||||
line.name:SetText(spellName .. "(" .. spellId .. ")")
|
||||
end
|
||||
|
||||
line.icon:SetTexture(spellIcon)
|
||||
if (options.remove_icon_border) then
|
||||
line.icon:SetTexCoord(.1, .9, .1, .9)
|
||||
else
|
||||
line.icon:SetTexCoord(0, 1, 0, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local onLeaveAuraLine = function(self)
|
||||
self:SetBackdropColor(unpack(options.backdrop_onleave))
|
||||
GameTooltip:Hide()
|
||||
end
|
||||
|
||||
local onEnterAuraLine = function(line, capsule, value)
|
||||
if (options.show_spell_tooltip and line.SpellID and GetSpellInfo(line.SpellID)) then
|
||||
GameTooltip:SetOwner(line, "ANCHOR_CURSOR")
|
||||
GameTooltip:SetSpellByID(line.SpellID)
|
||||
GameTooltip:AddLine(" ")
|
||||
GameTooltip:Show()
|
||||
end
|
||||
line:SetBackdropColor(unpack(options.backdrop_onenter))
|
||||
|
||||
local bAddedBySpellName = line.Flag
|
||||
value = value or line.SpellID
|
||||
|
||||
if (not bAddedBySpellName) then
|
||||
GameCooltip:Preset(2)
|
||||
GameCooltip:SetOwner(line, "left", "right", 2, 0)
|
||||
GameCooltip:SetOption("TextSize", 10)
|
||||
|
||||
local spellName, _, spellIcon = GetSpellInfo(value)
|
||||
if (spellName) then
|
||||
GameCooltip:AddLine(spellName .. " (" .. value .. ")")
|
||||
GameCooltip:AddIcon(spellIcon, 1, 1, 14, 14, .1, .9, .1, .9)
|
||||
end
|
||||
GameCooltip:Show()
|
||||
|
||||
else
|
||||
local spellName = GetSpellInfo(value)
|
||||
if (spellName) then
|
||||
local spellsWithSameName = db.aura_cache_by_name[string.lower(spellName)]
|
||||
if (not spellsWithSameName) then
|
||||
same_name_spells_add(value)
|
||||
spellsWithSameName = db.aura_cache_by_name[string.lower(spellName)]
|
||||
end
|
||||
|
||||
if (spellsWithSameName) then
|
||||
GameCooltip:Preset(2)
|
||||
GameCooltip:SetOwner(line, "left", "right", 2, 0)
|
||||
GameCooltip:SetOption("TextSize", 10)
|
||||
|
||||
for i, spellId in ipairs(spellsWithSameName) do
|
||||
local spellName, _, spellIcon = GetSpellInfo(spellId)
|
||||
if (spellName) then
|
||||
GameCooltip:AddLine(spellName .. "(" .. spellId .. ")")
|
||||
GameCooltip:AddIcon(spellIcon, 1, 1, 14, 14, .1, .9, .1, .9)
|
||||
end
|
||||
end
|
||||
|
||||
GameCooltip:Show()
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
local onClickAuraRemoveButton = function(self)
|
||||
local spellId = self:GetParent().SpellID
|
||||
if (spellId and type(spellId) == "number") then
|
||||
data[spellId] = nil
|
||||
data["" .. (spellId or "")] = nil -- cleanup...
|
||||
|
||||
--button > line > scrollbox
|
||||
self:GetParent():GetParent():DoRefresh()
|
||||
|
||||
if (onAuraRemoveCallback) then --upvalue
|
||||
detailsFramework:QuickDispatch(onAuraRemoveCallback, spellId)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local createLineFunc = function(self, index)
|
||||
local line = CreateFrame("button", "$parentLine" .. index, self, "BackdropTemplate")
|
||||
local scrollBoxWidth = options.width
|
||||
local lineHeight = options.line_height
|
||||
local verticalPadding = options.vertical_padding
|
||||
|
||||
line:SetPoint("topleft", self, "topleft", 1, -((index-1) * (lineHeight + verticalPadding)) - 1)
|
||||
line:SetSize(scrollBoxWidth - 2, lineHeight)
|
||||
line:SetScript("OnEnter", onEnterAuraLine)
|
||||
line:SetScript("OnLeave", onLeaveAuraLine)
|
||||
|
||||
line:SetBackdrop({bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
|
||||
line:SetBackdropColor(options.backdrop_onleave)
|
||||
|
||||
local iconTexture = line:CreateTexture("$parentIcon", "overlay")
|
||||
iconTexture:SetSize(lineHeight - 2, lineHeight - 2)
|
||||
|
||||
local spellNameFontString = line:CreateFontString("$parentName", "overlay", "GameFontNormal")
|
||||
detailsFramework:SetFontSize(spellNameFontString, options.font_size)
|
||||
|
||||
local removeButton = CreateFrame("button", "$parentRemoveButton", line, "UIPanelCloseButton")
|
||||
removeButton:SetSize(16, 16)
|
||||
removeButton:SetScript("OnClick", onClickAuraRemoveButton)
|
||||
removeButton:SetPoint("topright", line, "topright", 0, 0)
|
||||
removeButton:GetNormalTexture():SetDesaturated(true)
|
||||
|
||||
iconTexture:SetPoint("left", line, "left", 2, 0)
|
||||
spellNameFontString:SetPoint("left", iconTexture, "right", 3, 0)
|
||||
|
||||
line.icon = iconTexture
|
||||
line.name = spellNameFontString
|
||||
line.removebutton = removeButton
|
||||
|
||||
return line
|
||||
end
|
||||
|
||||
---@class df_aurascrollbox : df_scrollbox
|
||||
---@field RefreshMe fun(self:df_aurascrollbox)
|
||||
---@field TransformAuraData fun(self:df_aurascrollbox)
|
||||
---@field data_original table
|
||||
|
||||
data = data or {}
|
||||
|
||||
local auraScrollBox = detailsFramework:CreateScrollBox(parent, name, refreshAuraLines, data, options.width, options.height, options.line_amount, options.line_height)
|
||||
detailsFramework:ReskinSlider(auraScrollBox)
|
||||
---@cast auraScrollBox df_aurascrollbox
|
||||
|
||||
function auraScrollBox:TransformAuraData()
|
||||
local newData = {}
|
||||
local added = {}
|
||||
|
||||
for spellId, bAddedBySpellName in pairs(self.data) do
|
||||
local spellName, _, spellIcon = GetSpellInfo(spellId)
|
||||
if (spellName and not added[tonumber(spellId) or 0]) then
|
||||
local lowerSpellName = spellName:lower()
|
||||
table.insert(newData, {spellId, spellName, spellIcon, lowerSpellName, bAddedBySpellName})
|
||||
added[tonumber(spellId) or 0] = true
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(newData, function(t1, t2) return t1[4] < t2[4] end)
|
||||
self.data = newData
|
||||
end
|
||||
|
||||
auraScrollBox.data_original = data
|
||||
|
||||
auraScrollBox.SetData = function(self, data)
|
||||
self.data_original = data
|
||||
self.data = data
|
||||
auraScrollBox:TransformAuraData()
|
||||
end
|
||||
|
||||
auraScrollBox.GetData = function(self)
|
||||
return self.data_original
|
||||
end
|
||||
|
||||
auraScrollBox:SetData(data)
|
||||
end
|
||||
@@ -223,6 +223,10 @@ DF:Mixin(DFSliderMetaFunctions, DF.ScriptHookMixin)
|
||||
rawset(self, "FixedValue", value)
|
||||
end
|
||||
|
||||
function DFSliderMetaFunctions:GetFixedParameter()
|
||||
return rawget(self, "FixedValue")
|
||||
end
|
||||
|
||||
--set value
|
||||
function DFSliderMetaFunctions:SetValue(value)
|
||||
return self(value)
|
||||
@@ -799,6 +803,10 @@ local switch_set_fixparameter = function(self, value)
|
||||
rawset(self, "FixedValue", value)
|
||||
end
|
||||
|
||||
local switch_get_fixparameter = function(self)
|
||||
return rawget(self, "FixedValue")
|
||||
end
|
||||
|
||||
local switch_disable = function(self)
|
||||
if (self.is_checkbox) then
|
||||
self.checked_texture:Hide()
|
||||
@@ -841,6 +849,10 @@ local set_switch_func = function(self, newFunction)
|
||||
self.OnSwitch = newFunction
|
||||
end
|
||||
|
||||
local get_switch_func = function(self)
|
||||
return self.OnSwitch
|
||||
end
|
||||
|
||||
local set_as_checkbok = function(self)
|
||||
if self.is_checkbox and self.checked_texture then return end
|
||||
local checked = self:CreateTexture(self:GetName() .. "CheckTexture", "overlay")
|
||||
@@ -871,11 +883,29 @@ local set_as_checkbok = function(self)
|
||||
end
|
||||
end
|
||||
|
||||
---@class df_checkbox : df_button
|
||||
---@field OnSwitch fun(self:df_checkbox, fixedValue:any, value:boolean)
|
||||
---@field SetValue fun(self:df_button, value:boolean)
|
||||
---@field GetValue fun(self:df_button):boolean
|
||||
---@field SetFixedParameter fun(self:df_button, value:any)
|
||||
---@field GetFixedParameter fun(self:df_button):any
|
||||
---@field Disable fun(self:df_button)
|
||||
---@field Enable fun(self:df_button)
|
||||
---@field SetAsCheckBox fun(self:df_button)
|
||||
---@field SetTemplate fun(self:df_button, template: table)
|
||||
---@field GetSwitchFunction fun(self:df_button):function
|
||||
---@field SetSwitchFunction fun(self:df_button, newOnSwitchFunction: function)
|
||||
---@field GetCapsule fun(self:df_button):df_button capsule only exists in the actual frame of the encapsulated widget
|
||||
|
||||
|
||||
function DF:CreateSwitch(parent, onSwitch, defaultValue, width, height, leftText, rightText, member, name, colorInverted, switchFunc, returnFunc, withLabel, switch_template, label_template)
|
||||
local switch, label = DF:NewSwitch(parent, parent, name, member, width or 60, height or 20, leftText, rightText, defaultValue, colorInverted, switchFunc, returnFunc, withLabel, switch_template, label_template)
|
||||
if (onSwitch) then
|
||||
switch.OnSwitch = onSwitch
|
||||
end
|
||||
|
||||
---@cast switch df_checkbox
|
||||
---@cast label df_label
|
||||
return switch, label
|
||||
end
|
||||
|
||||
@@ -909,11 +939,13 @@ function DF:NewSwitch(parent, container, name, member, width, height, leftText,
|
||||
slider.SetValue = switch_set_value
|
||||
slider.GetValue = switch_get_value
|
||||
slider.SetFixedParameter = switch_set_fixparameter
|
||||
slider.GetFixedParameter = switch_get_fixparameter
|
||||
slider.Disable = switch_disable
|
||||
slider.Enable = switch_enable
|
||||
slider.SetAsCheckBox = set_as_checkbok
|
||||
slider.SetTemplate = DFSliderMetaFunctions.SetTemplate
|
||||
slider.SetSwitchFunction = set_switch_func
|
||||
slider.GetSwitchFunction = get_switch_func
|
||||
|
||||
if (member) then
|
||||
parent[member] = slider
|
||||
|
||||
+4
-3
@@ -957,6 +957,7 @@ DF.CrowdControlSpells = {
|
||||
[15487] = "PRIEST", --Silence
|
||||
|
||||
[2094] = "ROGUE", --Blind
|
||||
[427773] = "ROGUE", --Blind (AoE)
|
||||
[1833] = "ROGUE", --Cheap Shot
|
||||
[408] = "ROGUE", --Kidney Shot
|
||||
[1766] = "ROGUE", --Kick
|
||||
@@ -1448,15 +1449,15 @@ function DF:GetSpellsForEncounterFromJournal (instanceEJID, encounterEJID)
|
||||
|
||||
if (sectionInfo) then
|
||||
if (sectionInfo.spellID and type(sectionInfo.spellID) == "number" and sectionInfo.spellID ~= 0) then
|
||||
tinsert(spellIDs, sectionInfo.spellID)
|
||||
table.insert(spellIDs, sectionInfo.spellID)
|
||||
end
|
||||
|
||||
local nextChild, nextSibling = sectionInfo.firstChildSectionID, sectionInfo.siblingSectionID
|
||||
if (nextSibling) then
|
||||
tinsert(nextID, nextSibling)
|
||||
table.insert(nextID, nextSibling)
|
||||
end
|
||||
if (nextChild) then
|
||||
tinsert(nextID, nextChild)
|
||||
table.insert(nextID, nextChild)
|
||||
end
|
||||
else
|
||||
break
|
||||
|
||||
+53
-6
@@ -245,8 +245,8 @@ detailsFramework.TextEntryCounter = detailsFramework.TextEntryCounter or 1
|
||||
|
||||
self.editbox:Disable()
|
||||
|
||||
self.editbox:SetBackdropBorderColor(.5, .5, .5, .5)
|
||||
self.editbox:SetBackdropColor(.5, .5, .5, .5)
|
||||
self.editbox:SetBackdropBorderColor(0, 0, 0, 1)
|
||||
self.editbox:SetBackdropColor(.1, .1, .1, .834)
|
||||
self.editbox:SetTextColor(.5, .5, .5, .5)
|
||||
|
||||
if (self.editbox.borderframe) then
|
||||
@@ -531,8 +531,30 @@ end
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
--object constructor
|
||||
|
||||
---@class df_textentry : table, frame
|
||||
---@class df_textentry : editbox
|
||||
---@field widget editbox
|
||||
---@field tooltip any
|
||||
---@field show any
|
||||
---@field hide any
|
||||
---@field width any
|
||||
---@field height any
|
||||
---@field text any
|
||||
---@field multiline any
|
||||
---@field align any
|
||||
---@field SetTemplate fun(self:df_textentry, template:table)
|
||||
---@field Disable fun(self:df_textentry)
|
||||
---@field Enable fun(self:df_textentry)
|
||||
---@field SetCommitFunction fun(self:df_textentry, func:function)
|
||||
---@field SetNext fun(self:df_textentry, next:df_textentry)
|
||||
---@field SetLabelText fun(self:df_textentry, text:string)
|
||||
---@field SelectAll fun(self:df_textentry)
|
||||
---@field SetAutoSelectTextOnFocus fun(self:df_textentry, value:boolean)
|
||||
---@field Blink fun(self:df_textentry)
|
||||
---@field SetText fun(self:df_textentry, text:string)
|
||||
---@field GetText fun(self:df_textentry)
|
||||
---@field SetEnterFunction fun(self:df_textentry, func:function, param1:any, param2:any)
|
||||
---@field SetHook fun(self:df_textentry, hookName:string, func:function)
|
||||
---@field SetAsSearchBox fun(self:df_textentry)
|
||||
|
||||
---@param parent frame
|
||||
---@param textChangedCallback function
|
||||
@@ -955,9 +977,34 @@ local set_speciallua_editor_font_size = function(borderFrame, newSize)
|
||||
borderFrame.editboxlines:SetFont(file, newSize, flags)
|
||||
end
|
||||
|
||||
---@class df_luaeditor : frame
|
||||
---@field scroll scrollframe
|
||||
---@field editbox editbox
|
||||
---@field scrollnumberlines number
|
||||
---@field editboxlines editbox
|
||||
---@field SetTemplate fun(self:df_luaeditor, template:table)
|
||||
---@field Disable fun(self:df_luaeditor)
|
||||
---@field Enable fun(self:df_luaeditor)
|
||||
---@field SetText fun(self:df_luaeditor, text:string)
|
||||
---@field GetText fun(self:df_luaeditor):string
|
||||
---@field SetTextSize fun(self:df_luaeditor, size:number)
|
||||
---@field ClearFocus fun(self:df_luaeditor)
|
||||
---@field SetFocus fun(self:df_luaeditor)
|
||||
|
||||
---create a text box to edit lua code
|
||||
---if 'nointent' is true, the lua code will not be indented / highlighted / colored
|
||||
---@param parent frame
|
||||
---@param width number
|
||||
---@param height number
|
||||
---@param member string?
|
||||
---@param name string?
|
||||
---@param nointent boolean?
|
||||
---@param showLineNumbers boolean?
|
||||
---@param bNoName boolean?
|
||||
---@return df_luaeditor
|
||||
function detailsFramework:NewSpecialLuaEditorEntry(parent, width, height, member, name, nointent, showLineNumbers, bNoName)
|
||||
if (not bNoName) then
|
||||
if (name:find("$parent")) then
|
||||
if (name and name:find("$parent")) then
|
||||
local parentName = detailsFramework.GetParentName(parent)
|
||||
name = name:gsub("$parent", parentName)
|
||||
end
|
||||
@@ -1061,13 +1108,13 @@ function detailsFramework:NewSpecialLuaEditorEntry(parent, width, height, member
|
||||
--set the line text into a fontstring to get its width
|
||||
local thisText = textInArray[i]
|
||||
stringLengthFontString:SetText(thisText)
|
||||
local lineTextLength = ceil(stringLengthFontString:GetStringWidth())
|
||||
local lineTextLength = math.ceil(stringLengthFontString:GetStringWidth())
|
||||
|
||||
if (lineTextLength < maxStringWidth) then
|
||||
resultText = resultText .. i .. "\n"
|
||||
else
|
||||
--if the text width is bigger than the editbox width, add a blank line into the line counter
|
||||
local linesToOccupy = floor(lineTextLength / maxStringWidth)
|
||||
local linesToOccupy = math.floor(lineTextLength / maxStringWidth)
|
||||
local fillingText = i .. ""
|
||||
for o = 1, linesToOccupy do
|
||||
fillingText = fillingText .. "\n"
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
--guadians: represents a npc, the server has the possess of the controller, don't accept commands like pets, helps attacking the enemies of the npc or player.
|
||||
--role: is a string that represents the role of a unit, such as tank, healer, or damage dealer. only players can have a role.
|
||||
|
||||
---@alias auratype
|
||||
---| "BUFF"
|
||||
---| "DEBUFF"
|
||||
|
||||
---@alias role
|
||||
---| "TANK"
|
||||
@@ -305,7 +308,7 @@
|
||||
---@field GetScale fun(self: uiobject) : scale|number
|
||||
---@field GetAlpha fun(self: uiobject) : alpha|number
|
||||
---@field GetSize fun(self: uiobject) : width|number, height|number
|
||||
---@field GetParent fun(self: uiobject) : frame
|
||||
---@field GetParent fun(self: uiobject) : any
|
||||
---@field GetPoint fun(self: uiobject, index: number): string, frame, string, number, number
|
||||
---@field GetCenter fun(self: uiobject): number, number
|
||||
---@field SetPoint fun(self: uiobject, point: anchorpoint, relativeFrame: uiobject, relativePoint: anchorpoint, xOffset: number, yOffset: number)
|
||||
@@ -363,6 +366,7 @@
|
||||
---@field SetThickness fun(self: line, thickness: number)
|
||||
|
||||
---@class frame : uiobject
|
||||
---@field __background texture
|
||||
---@field CreateLine fun(self: frame, name: string?, drawLayer: drawlayer, templateName: string?, subLevel: number?) : line
|
||||
---@field SetID fun(self: frame, id: number) set an ID for the frame
|
||||
---@field SetAttribute fun(self: frame, name: string, value: any)
|
||||
@@ -544,6 +548,7 @@
|
||||
|
||||
---@class texture : region
|
||||
---@field SetDrawLayer fun(self: texture, layer: drawlayer, subLayer: number?)
|
||||
---@field GetTexture fun(self: texture) : any
|
||||
---@field SetTexture fun(self: texture, path: textureid|texturepath, horizontalWrap: texturewrap?, verticalWrap: texturewrap?, filter: texturefilter?)
|
||||
---@field SetAtlas fun(self: texture, atlas: string)
|
||||
---@field SetColorTexture fun(self: texture, r: red|number, g: green|number, b: blue|number, a: alpha|number?)
|
||||
@@ -583,3 +588,22 @@
|
||||
---@field GetBlendMode fun(self: texture) : string
|
||||
---@field GetVertexColor fun(self: texture) : number, number, number, number
|
||||
|
||||
---@class editbox : frame
|
||||
---@field SetText fun(self: editbox, text: string)
|
||||
---@field GetText fun(self: editbox) : string
|
||||
---@field SetCursorPosition fun(self: editbox, position: number)
|
||||
---@field GetCursorPosition fun(self: editbox) : number
|
||||
---@field SetMaxLetters fun(self: editbox, maxLetters: number)
|
||||
---@field GetMaxLetters fun(self: editbox) : number
|
||||
---@field SetNumeric fun(self: editbox, numeric: boolean)
|
||||
---@field GetNumeric fun(self: editbox) : boolean
|
||||
---@field SetMultiLine fun(self: editbox, multiLine: boolean)
|
||||
---@field GetMultiLine fun(self: editbox) : boolean
|
||||
---@field SetAutoFocus fun(self: editbox, autoFocus: boolean)
|
||||
---@field GetAutoFocus fun(self: editbox) : boolean
|
||||
---@field SetFont fun(self: editbox, font: string, size: number, flags: string)
|
||||
---@field SetFontObject fun(self: editbox, fontString: fontstring)
|
||||
---@field GetFont fun(self: editbox) : string, number, string
|
||||
---@field SetTextColor fun(self: editbox, r: red|number, g: green|number, b: blue|number, a: alpha|number?)
|
||||
---@field SetJustifyH fun(self:editbox, alignment:string)
|
||||
---@field SetTextInsets fun(self:editbox, left:number, right:number, top:number, bottom:number)
|
||||
|
||||
@@ -367,7 +367,7 @@ do
|
||||
[216331] = {cooldown = 120, duration = 20, specs = {65}, talent = false, charges = 1, class = "PALADIN", type = 1}, --Avenging Crusader
|
||||
[31884] = {cooldown = 120, duration = 20, specs = {65, 66, 70}, talent = false, charges = 1, class = "PALADIN", type = 1}, --Avenging Wrath
|
||||
[1044] = {cooldown = 25, duration = 8, specs = {65, 66, 70}, talent = false, charges = 1, class = "PALADIN", type = 5}, --Blessing of Freedom
|
||||
[1022] = {cooldown = 300, duration = 10, specs = {65, 66, 70}, talent = false, charges = 1, class = "PALADIN", type = 3, shareid = 204018}, --Blessing of Protection
|
||||
[1022] = {cooldown = 300, duration = 10, specs = {65, 66, 70}, talent = false, charges = 1, class = "PALADIN", type = 3, shareid = 1022}, --Blessing of Protection
|
||||
[6940] = {cooldown = 120, duration = 12, specs = {65, 66, 70}, talent = false, charges = 1, class = "PALADIN", type = 3}, --Blessing of Sacrifice
|
||||
[204018] = {cooldown = 180, duration = 10, specs = {66}, talent = false, charges = 1, class = "PALADIN", type = 3, shareid = 1022}, --Blessing of Spellwarding
|
||||
[115750] = {cooldown = 90, duration = 6, specs = {65, 66, 70}, talent = false, charges = 1, class = "PALADIN", type = 8}, --Blinding Light
|
||||
@@ -984,4 +984,4 @@ do
|
||||
end
|
||||
end)
|
||||
loadLibDatabase()
|
||||
end
|
||||
end
|
||||
|
||||
+12
-9
@@ -1200,17 +1200,20 @@
|
||||
local is_friendly_fire = false
|
||||
|
||||
if (_is_in_instance) then
|
||||
if (bitfield_swap_cache [sourceSerial] or ownerActor and bitfield_swap_cache [ownerActor.serial]) then
|
||||
if (targetActor.grupo or targetOwner and targetOwner.grupo) then
|
||||
is_friendly_fire = true
|
||||
end
|
||||
else
|
||||
if (bitfield_swap_cache [targetSerial] or targetOwner and bitfield_swap_cache [targetOwner.serial]) then
|
||||
else
|
||||
--Astral Nova explosion from Astral Bomb (Spectral Invoker - Algeth'ar Academy) should get friend zone here
|
||||
if ((targetActor.grupo or targetOwner and targetOwner.grupo) and (sourceActor.grupo or ownerActor and ownerActor.grupo)) then
|
||||
local npcId = npcid_cache[targetSerial]
|
||||
if (npcId ~= 207341) then
|
||||
if (bitfield_swap_cache [sourceSerial] or ownerActor and bitfield_swap_cache [ownerActor.serial]) then
|
||||
if (targetActor.grupo or targetOwner and targetOwner.grupo) then
|
||||
is_friendly_fire = true
|
||||
end
|
||||
else
|
||||
if (bitfield_swap_cache [targetSerial] or targetOwner and bitfield_swap_cache [targetOwner.serial]) then
|
||||
else
|
||||
--Astral Nova explosion from Astral Bomb (Spectral Invoker - Algeth'ar Academy) should get friend zone here
|
||||
if ((targetActor.grupo or targetOwner and targetOwner.grupo) and (sourceActor.grupo or ownerActor and ownerActor.grupo)) then
|
||||
is_friendly_fire = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user