diff --git a/.idea/DJBags.iml b/.idea/DJBags.iml new file mode 100644 index 0000000..d6ebd48 --- /dev/null +++ b/.idea/DJBags.iml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="JAVA_MODULE" version="4"> + <component name="NewModuleRootManager" inherit-compiler-output="true"> + <exclude-output /> + <content url="file://$MODULE_DIR$" /> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> +</module> \ No newline at end of file diff --git a/src/lua/base/djclass.lua b/src/lua/base/djclass.lua deleted file mode 100644 index 157a374..0000000 --- a/src/lua/base/djclass.lua +++ /dev/null @@ -1,69 +0,0 @@ --- local NAME, ADDON = ... - -function class(...) - local arg1 = ... - local base - if type(arg1) == 'table' and arg1.__djclass then - base = arg1 - end - - local c = {} - c.__index = c - c.__djclass = true - c.type = select(base and 2 or 1, ...) or base and base.type - c.inherits = select(base and 3 or 2, ...) or base and base.inherits - - if base then - for k, v in pairs(base) do - c[k] = v - end - end - - setmetatable(c, { - __call = function(table, ...) - local name - if table.type then - name = ... - assert(name and type(name) == 'string', 'DJClass needs a name (first argument) when creating an object for WoWs frame content') - end - local obj - if name then - obj = {} -- CreateFrame(name, table.type, UIParent, table.inherits) - else - obj = {} - end - - for k, v in pairs(table) do - obj[k] = v - end - - if obj.init and type(obj.init) == 'function' then - obj:init(select(name and 2 or 1, ...)) - end - - return obj - end - }) - - return c -end - -local A = class('FRAME') -function A:init(string) - self.name = string -end - -local B = class(A) -function B:init(name, text) - A.init(self, name) - self.text = text -end - -function B:print() - print(self.name, self.text) -end - -print("\nstart\n\n") - -local b = B('Namerize', 'Text', 'Face') -b:print() \ No newline at end of file diff --git a/src/lua/cache/cache.lua b/src/lua/cache/cache.lua new file mode 100644 index 0000000..a967be3 --- /dev/null +++ b/src/lua/cache/cache.lua @@ -0,0 +1,19 @@ +local NAME, ADDON = ... + +ADDON.cache = {} +ADDON.cache.__index = ADDON.cache + +local cache = ADDON.cache +cache.items = {} +cache.bagContainers = {} + +function cache:GetItem(bag, slot) + self.items[bag] = self.items[bag] or {} + self.items[bag][slot] = self.items[bag][slot] or ADDON.item(bag, slot) + return self.items[bag][slot] +end + +function cache:GetBagItemContainer(name) + self.bagContainers[name] = self.bagContainers[name] or ADDON.itemContainer(name, name ~= ADDON.utils.EMPTY_BAG_NAME, nil, name == ADDON.utils.EMPTY_BAG_NAME) + return self.bagContainers[name] +end \ No newline at end of file diff --git a/src/lua/controllers/bag.lua b/src/lua/controllers/bag.lua new file mode 100644 index 0000000..aa9510b --- /dev/null +++ b/src/lua/controllers/bag.lua @@ -0,0 +1,123 @@ +local NAME, ADDON = ... + +ADDON.bag = {} +ADDON.bag.__index = ADDON.bag + +local bag = ADDON.bag + +function bag:Init() + self.frame = ADDON.categoryContainer('DJBagsBagCategoryContainer', UIParent) + self.frame:SetPoint('BOTTOMRIGHT', -200, 200) + self.frame:SetUserPlaced(true) + self.frame:Hide() + self.frame.mainBar = ADDON.mainBar(self.frame) + self.frame.mainBar:SetPoint('TOPRIGHT', self.frame, 'BOTTOMRIGHT', 0, -2) + self.frame.mainBar:Show() +end + +function bag:Open() + self:Register() + self:UpdateAllItems() + self.frame.mainBar:Update() + self.frame:Show() +end + +function bag:Close() + self:UnRegister() + self.frame:Hide() +end + +function bag:Toggle() + if self.frame:IsVisible() then + self:Close() + else + self:Open() + end +end + +local function UpdateItemsForBag(self, bag, arrangeList) + for slot = 1, GetContainerNumSlots(bag) do + local item = ADDON.cache:GetItem(bag, slot) + local previousContainer + if item:GetParent() and item:GetParent().__class == ADDON.itemContainer.__class then + previousContainer = item:GetParent() + end + + item:Update() + + local newContainer = ADDON.cache:GetBagItemContainer(ADDON.utils:GetItemContainerName(bag, slot)) + self.frame:AddContainer(newContainer) + + if previousContainer ~= newContainer then + if previousContainer then + previousContainer:RemoveItem(item) + arrangeList[previousContainer] = true + end + newContainer:AddItem(item) + arrangeList[newContainer] = true + end + end +end + +function bag:UpdateAllItems() + local arrangeList = {} + for bag = 0, NUM_BAG_SLOTS do + UpdateItemsForBag(self, bag, arrangeList) + end + for container, _ in pairs(arrangeList) do + container:Arrange() + end + self.frame:Arrange() +end + +function bag:UpdateAllItemsForBag(bag) + local arrangeList = {} + UpdateItemsForBag(self, bag, arrangeList) + for container, _ in pairs(arrangeList) do + container:Arrange() + end + self.frame:Arrange() +end + +function bag:Register() + ADDON.eventManager:AddEvent(self, 'INVENTORY_SEARCH_UPDATE') + ADDON.eventManager:AddEvent(self, 'BAG_UPDATE') + ADDON.eventManager:AddEvent(self, 'BAG_UPDATE_COOLDOWN') + ADDON.eventManager:AddEvent(self, 'ITEM_LOCK_CHANGED') +end + +function bag:UnRegister() + ADDON.eventManager:RemoveEvent(self, 'INVENTORY_SEARCH_UPDATE') + ADDON.eventManager:RemoveEvent(self, 'BAG_UPDATE') + ADDON.eventManager:RemoveEvent(self, 'BAG_UPDATE_COOLDOWN') + ADDON.eventManager:RemoveEvent(self, 'ITEM_LOCK_CHANGED') +end + +function bag:BAG_UPDATE(bag) + if bag >= 0 and bag <= NUM_BAG_SLOTS then + self:UpdateAllItemsForBag(bag) + end +end + +function bag:INVENTORY_SEARCH_UPDATE() + for bag = 0, NUM_BAG_SLOTS do + for _, item in pairs(ADDON.cache:GetItemsForBag(bag)) do + item:UpdateSearch() + end + end +end + +function bag:BAG_UPDATE_COOLDOWN() + for bag = 0, NUM_BAG_SLOTS do + for slot = 1, GetContainerNumSlots(bag) do + local item = ADDON.cache:GetItem(bag, slot) + item:UpdateCooldown() + end + end +end + +function bag:ITEM_LOCK_CHANGED(bag, slot) + if bag >= 0 and bag <= NUM_BAG_SLOTS then + ADDON.cache:GetItem(bag, slot):UpdateLock() + end +end \ No newline at end of file diff --git a/src/lua/core.lua b/src/lua/core.lua index 4f05f6d..c4887fa 100644 --- a/src/lua/core.lua +++ b/src/lua/core.lua @@ -1 +1,35 @@ -local NAME, ADDON = ... \ No newline at end of file +local NAME, ADDON = ... + +ADDON.core = {} +ADDON.core.__index = ADDON.core +local core = ADDON.core + +--region Events + +function core:ADDON_LOADED(name) + if name ~= NAME then return end + + ADDON.settingsController:Init() + + ADDON.bag:Init() + + ADDON.eventManager:RemoveEvent(self, 'ADDON_LOADED') +end + +ADDON.eventManager:AddEvent(core, 'ADDON_LOADED') + +--region Slash Commands + +SLASH_DJBAGS1, SLASH_DJBAGS2 = '/db', '/djbags'; -- 3. +function SlashCmdList.DJBAGS(msg, editbox) -- 4. +-- ADDON.bag:Open() +ADDON.categoryDialog(12) +ADDON.eventManager:AddEvent('MyRandonEvent') +end + +SLASH_RELOAD1 = '/rl' +function SlashCmdList.RELOAD(msg, editbox) -- 4. +ReloadUI() +end + +--endregion \ No newline at end of file diff --git a/src/lua/elements/bagBar.lua b/src/lua/elements/bagBar.lua new file mode 100644 index 0000000..3d92cfb --- /dev/null +++ b/src/lua/elements/bagBar.lua @@ -0,0 +1,6 @@ +-- +-- User: Brandon James Talbot +-- Date: 2016/06/29 +-- Time: 6:04 PM +-- + diff --git a/src/lua/elements/categoryContainer.lua b/src/lua/elements/categoryContainer.lua new file mode 100644 index 0000000..d35d461 --- /dev/null +++ b/src/lua/elements/categoryContainer.lua @@ -0,0 +1,77 @@ +local NAME, ADDON = ... + +ADDON.categoryContainer = {} +ADDON.categoryContainer.__index = ADDON.categoryContainer + +local container = ADDON.categoryContainer +container.containers = {} +setmetatable(container, { + __call = function(tbl, name, parent) + local frame = ADDON.container(name, parent) + + for k, v in pairs(tbl) do + frame[k] = v + end + + frame:Init() + frame:Setup() + + return frame + end +}) + +function container:Init() + table.insert(UISpecialFrames, self:GetName()) + self:SetMovable(true) + self:EnableMouse(true) + self:RegisterForDrag("LeftButton") + self:SetScript("OnDragStart", self.StartMoving) + self:SetScript("OnDragStop", self.StopMovingOrSizing) +end + +function container:Setup() + ADDON.container.Setup(self) + + local settings = ADDON.settings.categoryContainer + + self.padding = settings.padding + self.spacing = settings.spacing + self.sortFunction = ADDON.sorters.containers[settings.sortFunction] + self.maxHeight = settings.maxHeight +end + +function container:AddContainer(container) + self.containers[container] = true +end + +function container:Arrange() + local list = self.containers + + local x = -self.padding + local y = self.padding + local width = 0 + local height = 0 + + for item in ADDON.utils:PairsByKey(list, self.sortFunction) do + item:ClearAllPoints() + item:SetParent(self) + + if item:IsEmpty() then + item:Hide() + else + item:Show() + if (y + item:GetHeight() + self.spacing) > self.maxHeight then + y = self.padding + x = x - item:GetWidth() - self.spacing + end + + item:SetPoint('BOTTOMRIGHT', x, y) + + height = math.max(height, y + item:GetHeight() + self.padding) + width = math.max(width, -x + self.padding + item:GetWidth()) + y = y + self.spacing + item:GetHeight() + end + end + + self:SetSize(width, height) +end \ No newline at end of file diff --git a/src/lua/elements/categorydialog.lua b/src/lua/elements/categorydialog.lua new file mode 100644 index 0000000..7f6e1bb --- /dev/null +++ b/src/lua/elements/categorydialog.lua @@ -0,0 +1,177 @@ +local NAME, ADDON = ... + +ADDON.categoryDialog = {} +ADDON.categoryDialog.__index = ADDON.categoryDialog + +local dialog = ADDON.categoryDialog +setmetatable(dialog, { + __call = function(self, id) + self:Show(id) + end +}) + +function dialog:Show(id) + if not id then return end + + local frame = self:GetFrame(id) + self.id = id + frame:Show() +end + +function dialog:GetFrame(id) + if not self.frame then + self:CreateFrame() + end + + self.frame:Setup() + + self:Init(id) + return self.frame +end + +function OnDropDownClick(self) + UIDropDownMenu_SetSelectedID(dialog.dropDown, self:GetID()) + dialog:SetText(self.value) +end + +function InitDropDown(self, level) + local unique = {} + for _, v in pairs(ADDON.settings.categories.userDefined) do + unique[v] = true + end + + if next(unique) ~= nil then + local info + for k, _ in pairs(unique) do + info = UIDropDownMenu_CreateInfo() + info.text = k + info.value = k + info.func = OnDropDownClick + UIDropDownMenu_AddButton(info, level) + end + end +end + +function dialog:Init(id) + -- local name, link, quality, iLevel, reqLevel, class, subclass, maxStack, equipSlot, texture, vendorPrice = GetItemInfo(id) + + self.title:SetText(string.format('Change %s\'s category?', 'Test Name')) + -- TODO add texture + + UIDropDownMenu_Initialize(self.dropDown, InitDropDown) + self.errorText:Hide() + local text = ADDON.settings.categories.userDefined[id] or '' + self:SetText(text) +end + +function dialog:SetText(text) + self.editBox:SetText(text) +end + +function dialog:CreateFrame() + self.frame = ADDON.container('DJBagsCategoryDialog') + self.frame:SetPoint('CENTER') + table.insert(UISpecialFrames, self.frame:GetName()) + + self.title = self.frame:CreateFontString('DJBagsCategoryDialogTitle', 'OVERLAY') + self.title:SetFont('Fonts\\FRIZQT__.TTF', 18, 'OUTLINE') + self.title:SetTextColor(1, 1, 1, 1) + self.title:SetPoint("TOPLEFT", 5, -5) + self.title:SetPoint("TOPRIGHT", -5, -5) + + self.editBox = CreateFrame('EDITBOX', 'DJBagsCategoryDialogEdit', self.frame) + self.editBox:SetHeight(20) + self.editBox:SetFontObject("GameFontHighlight") + self.editBox:SetPoint('TOPLEFT', self.title, 'BOTTOMLEFT', 0, -15) + self.editBox:SetPoint('TOPRIGHT', self.frame, 'RIGHT', -140, 0) + self.editBox:SetBackdrop({ + bgFile = "Interface\\ChatFrame\\ChatFrameBackground", + edgeFile = "Interface\\Buttons\\WHITE8x8", + tile = true, + tileSize = 16, + edgeSize = 1, + }) + self.editBox:SetBackdropBorderColor(0.3, 0.3, 0.3, 1) + self.editBox:SetBackdropColor(0, 0, 0, 0) + + self.errorText = self.frame:CreateFontString('DJBagsCategoryDialogTitle', 'OVERLAY') + self.errorText:SetFont('Fonts\\FRIZQT__.TTF', 18, 'OUTLINE') + self.errorText:SetTextColor(1, 0, 0, 1) + self.errorText:SetPoint("TOPRIGHT", self.editBox, 'TOPLEFT', -5, 0) + self.errorText:SetText('A Category name needs to be entered!') + self.errorText:Hide() + + self.dropDown = CreateFrame("Button", "DJBagsCategoryDialogDropDown", self.frame, "UIDropDownMenuTemplate") + self.dropDown:SetPoint('LEFT', self.editBox, 'RIGHT') + UIDropDownMenu_SetWidth(self.dropDown, 100); + UIDropDownMenu_SetButtonWidth(self.dropDown, 124) + UIDropDownMenu_JustifyText(self.dropDown, "LEFT") + + self.resetBtn = CreateFrame('BUTTON', 'DJBagsCategoryDialogResetButton', self.frame) + self.resetBtn:SetNormalFontObject("GameFontHighlight") + self.resetBtn:SetSize(75, 20) + self.resetBtn:SetText("Clear") + self.resetBtn:SetBackdrop({ + bgFile = "Interface\\ChatFrame\\ChatFrameBackground", + edgeFile = "Interface\\Buttons\\WHITE8x8", + tile = true, + tileSize = 16, + edgeSize = 1, + }) + self.resetBtn:SetBackdropBorderColor(0.3, 0.3, 0.3, 1) + self.resetBtn:SetBackdropColor(0, 0, 0, 0) + self.resetBtn:SetPoint('BOTTOMLEFT', self.frame, 'BOTTOMLEFT', 5, 5) + self.resetBtn:SetScript('OnClick', function() + ADDON.settings.categories.userDefined[dialog.id] = nil + ADDON.eventManager:FireEvent('SETTINGS_UPDATE') + dialog.frame:Hide() + end) + + self.okBtn = CreateFrame('BUTTON', 'DJBagsCategoryDialogOkButton', self.frame) + self.okBtn:SetNormalFontObject("GameFontHighlight") + self.okBtn:SetSize(75, 20) + self.okBtn:SetText("OK") + self.okBtn:SetBackdrop({ + bgFile = "Interface\\ChatFrame\\ChatFrameBackground", + edgeFile = "Interface\\Buttons\\WHITE8x8", + tile = true, + tileSize = 16, + edgeSize = 1, + }) + self.okBtn:SetBackdropBorderColor(0.3, 0.3, 0.3, 1) + self.okBtn:SetBackdropColor(0, 0, 0, 0) + self.okBtn:SetPoint('BOTTOMRIGHT', self.frame, 'BOTTOMRIGHT', -5, 5) + self.okBtn:SetScript('OnClick', function() + local text = dialog.editBox:GetText() + dialog.errorText:Hide() + if not text or text ~= '' then + ADDON.settings.categories.userDefined[dialog.id] = text + ADDON.eventManager:FireEvent('SETTINGS_UPDATE') + dialog.frame:Hide() + else + dialog.errorText:Show() + end + end) + + self.cancelBtn = CreateFrame('BUTTON', 'DJBagsCategoryDialogCancelButton', self.frame) + self.cancelBtn:SetNormalFontObject("GameFontHighlight") + self.cancelBtn:SetSize(75, 20) + self.cancelBtn:SetText("Cancel") + self.cancelBtn:SetBackdrop({ + bgFile = "Interface\\ChatFrame\\ChatFrameBackground", + edgeFile = "Interface\\Buttons\\WHITE8x8", + tile = true, + tileSize = 16, + edgeSize = 1, + }) + self.cancelBtn:SetBackdropBorderColor(0.3, 0.3, 0.3, 1) + self.cancelBtn:SetBackdropColor(0, 0, 0, 0) + self.cancelBtn:SetPoint('TOPRIGHT', self.okBtn, 'TOPLEFT', -5, 0) + self.cancelBtn:SetScript('OnClick', function() + dialog.frame:Hide() + end) + + self.frame:SetWidth(350) + self.frame:SetHeight(90) +end + diff --git a/src/lua/elements/container.lua b/src/lua/elements/container.lua new file mode 100644 index 0000000..8bbf102 --- /dev/null +++ b/src/lua/elements/container.lua @@ -0,0 +1,35 @@ +local NAME, ADDON = ... + +ADDON.container = {} +ADDON.container.__index = ADDON.container + +local container = ADDON.container +setmetatable(container, { + __call = function(tbl, name, parent) + local frame = CreateFrame('FRAME', 'DJBagContainer_' .. (name or ADDON.uuid()), parent or UIParent) + frame.name = name + + for key, value in pairs(tbl) do + frame[key] = value + end + + frame:Setup() + + return frame + end +}) + +function container:Setup() + local settings = ADDON.settings.container + + self:SetBackdrop({ + -- TODO remove all hardcoded shit + bgFile = "Interface\\ChatFrame\\ChatFrameBackground", + edgeFile = "Interface\\Buttons\\WHITE8x8", + tile = true, + tileSize = 16, + edgeSize = settings.borderWidth, + }) + self:SetBackdropColor(unpack(settings.backgroundColor)) + self:SetBackdropBorderColor(unpack(settings.borderColor)) +end \ No newline at end of file diff --git a/src/lua/elements/item.lua b/src/lua/elements/item.lua new file mode 100644 index 0000000..19f980a --- /dev/null +++ b/src/lua/elements/item.lua @@ -0,0 +1,186 @@ +local NAME, ADDON = ... + +ADDON.item = {} +ADDON.item.__index = ADDON.item + +local item = ADDON.item +setmetatable(item, { + __call = function(tbl, bag, slot) + local parent = CreateFrame('FRAME', string.format('DJBagsItemParent%d_%d', bag, slot)) + parent.button = CreateFrame('BUTTON', string.format('DJBagsItem%d_%d', bag, slot), parent, 'ContainerFrameItemButtonTemplate') + + parent:SetID(bag) + parent.button:SetID(slot) + + for key, value in pairs(tbl) do + parent[key] = value + end + + parent:Init() + parent:Setup() + + return parent + end +}) + +function item:Init() + self.button:ClearAllPoints() + self.button:SetAllPoints() + + self.button.IconBorder:ClearAllPoints() + self.button.IconBorder:SetAllPoints() + + self.button:SetNormalTexture([[Interface\Common\WhiteIconFrame]]) + self.button:GetNormalTexture():ClearAllPoints() + self.button:GetNormalTexture():SetAllPoints() + + self.button.NewItemTexture:ClearAllPoints() + self.button.NewItemTexture:SetAllPoints() + + self.button.flash:ClearAllPoints() + self.button.flash:SetAllPoints() + + self.button.quest = _G[self.button:GetName() .. "IconQuestTexture"] + self.button.quest:ClearAllPoints() + self.button.quest:SetAllPoints() + + self.button.cooldown = _G[self.button:GetName() .. "Cooldown"] + + self.button:Show() +end + +function item:Setup() + local settings = ADDON.settings.item + self:SetSize(settings.size, settings.size) + local name, _, outline = self.button.Count:GetFont() + self.button.Count:SetFont(name, math.min(settings.size / 4, 13), outline) +end + +--region Update Events + +local function UpdateQuest(self, isQuestItem, questId, isActive) + if (questId and not isActive) then + self.button.quest:SetTexture(TEXTURE_ITEM_QUEST_BANG) + self.button.quest:Show() + elseif (questId or isQuestItem) then + self.button.quest:SetTexture(TEXTURE_ITEM_QUEST_BORDER) + self.button.quest:Show() + else + self.button.quest:Hide() + end +end + +local function UpdateNewItemAnimations(self, isNewItem, isBattlePayItem, quality) + if (isNewItem) then + if (isBattlePayItem) then + self.button.NewItemTexture:Hide() + self.button.BattlepayItemTexture:Show() + else + if (quality and NEW_ITEM_ATLAS_BY_QUALITY[quality]) then + self.button.NewItemTexture:SetAtlas(NEW_ITEM_ATLAS_BY_QUALITY[quality]); + else + self.button.NewItemTexture:SetAtlas("bags-glow-white"); + end + self.button.BattlepayItemTexture:Hide(); + self.button.NewItemTexture:Show(); + end + if (not self.button.flashAnim:IsPlaying() and not self.button.newitemglowAnim:IsPlaying()) then + self.button.flashAnim:Play(); + self.button.newitemglowAnim:Play(); + end + else + self.button.BattlepayItemTexture:Hide(); + self.button.NewItemTexture:Hide(); + if (self.button.flashAnim:IsPlaying() or self.button.newitemglowAnim:IsPlaying()) then + self.button.flashAnim:Stop(); + self.button.newitemglowAnim:Stop(); + end + end +end + +local function UpdateFiltered(self, filtered, shouldDoRelicChecks, itemID) + if (filtered) then + self.button.searchOverlay:Show(); + else + self.button.searchOverlay:Hide(); + if shouldDoRelicChecks then + ContainerFrame_ConsiderItemButtonForRelicTutorial(self.button, itemID); + end + end +end + +local function UpdateCountcolour(self, equipable, quality) + if (equipable) then + self.button.Count:SetVertexColor(BAG_ITEM_QUALITY_COLORS[quality].r, BAG_ITEM_QUALITY_COLORS[quality].g, BAG_ITEM_QUALITY_COLORS[quality].b) + else + self.button.Count:SetVertexColor(1, 1, 1) + end +end + +local function UpdateCooldown(self) + if not GetContainerItemID(self:GetID(), self.button:GetID()) then + self.button.cooldown:Hide() + return + end + + local start, duration, enable = GetContainerItemCooldown(self:GetID(), self.button:GetID()); + CooldownFrame_Set(self.button.cooldown, start, duration, enable); + if (duration > 0 and enable == 0) then + SetItemButtonTextureVertexColor(self.button, 0.4, 0.4, 0.4); + else + SetItemButtonTextureVertexColor(self.button, 1, 1, 1); + end +end + +function item:Update() + local texture, count, locked, quality, _, _, _, filtered, _, id = GetContainerItemInfo(self:GetID(), self.button:GetID()) + local isQuestItem, questId, isActive = GetContainerItemQuestInfo(self:GetID(), self.button:GetID()) + local isNewItem = C_NewItems.IsNewItem(self:GetID(), self.button:GetID()) + local isBattlePayItem = IsBattlePayItem(self:GetID(), self.button:GetID()) + local shouldDoRelicChecks = not BagHelpBox:IsShown() and not GetCVarBitfield("closedInfoFrames", LE_FRAME_TUTORIAL_ARTIFACT_RELIC_MATCH) + local equipable = IsEquippableItem(id) + + if (equipable) then + count = count > 1 and count or select(4, GetItemInfo(id)) + end + + self.id = id + self.name = id and select(1, GetItemInfo(id)) or '' + self.quality = quality or 0 + self.ilevel = id and select(4, GetItemInfo(id)) or 0 + + SetItemButtonTexture(self.button, texture) + SetItemButtonQuality(self.button, quality, id) + SetItemButtonCount(self.button, count) + SetItemButtonDesaturated(self.button, locked) + UpdateQuest(self, isQuestItem, questId, isActive) + UpdateNewItemAnimations(self, isNewItem, isBattlePayItem, quality) + UpdateFiltered(self, filtered, shouldDoRelicChecks, id) + UpdateCountcolour(self, equipable, quality) + UpdateCooldown(self) +end + +function item:UpdateCooldown() + UpdateCooldown(self) +end + +function item:UpdateSearch() + local _, _, _, _, _, _, _, filtered, _, id = GetContainerItemInfo(self:GetID(), self.button:GetID()) + local shouldDoRelicChecks = not BagHelpBox:IsShown() and not GetCVarBitfield("closedInfoFrames", LE_FRAME_TUTORIAL_ARTIFACT_RELIC_MATCH) + UpdateFiltered(self, filtered, shouldDoRelicChecks, id) +end + +function item:UpdateLock() + local locked = select(3, GetContainerItemInfo(self:GetID(), self.button:GetID())) + SetItemButtonDesaturated(self.button, locked); +end + +function item:OnClick() + if self.id then + if IsAltKeyDown() and IsControlKeyDown() then + -- ADDON.categoryInput(self, self.id) + end + end +end + +--endregion \ No newline at end of file diff --git a/src/lua/elements/itemContainer.lua b/src/lua/elements/itemContainer.lua new file mode 100644 index 0000000..efef94a --- /dev/null +++ b/src/lua/elements/itemContainer.lua @@ -0,0 +1,102 @@ +local NAME, ADDON = ... + +ADDON.itemContainer = {} +ADDON.itemContainer.__index = ADDON.itemContainer +ADDON.itemContainer.__class = 'ItemContainer' + +local container = ADDON.itemContainer +setmetatable(container, { + __call = function(tbl, name, hasTitle, parent, max) + local frame = ADDON.container(name, parent) + frame.max = max + + for k, v in pairs(tbl) do + frame[k] = v + end + + frame:Init(hasTitle) + frame:Setup() + + return frame + end +}) + +function container:Init(hasTitle) + self.items = {} + if hasTitle == nil or hasTitle then + self.title = self:CreateFontString(self:GetName() .. 'Title', 'OVERLAY') + end +end + +function container:Setup() + ADDON.container.Setup(self) + + local settings = ADDON.settings.itemContainer + + self.padding = settings.padding + self.spacing = settings.spacing + self.cols = settings.cols + self.sortFunction = ADDON.sorters.items[settings.sortFunction] + + if self.title then + self.title:SetFont(settings.font, settings.fontSize, '') + self.title:SetText(self.name) + self.title:SetTextColor(unpack(settings.fontColor)) + self.title:ClearAllPoints() + self.title:SetPoint('TOPLEFT', self.padding, -self.padding) + self.title:SetPoint('TOPRIGHT', -self.padding, -self.padding) + self.title.margin = settings.titleMargin + end +end + +function container:AddItem(item) + if item:GetParent() ~= self then + self.items[item] = true + end +end + +function container:RemoveItem(item) + self.items[item] = nil +end + +function container:Arrange() + local list = self.items + + local x = self.padding + local y = -self.padding - (self.title and (self.title:GetStringHeight() + self.title.margin) or 0) + local width + local height = 0 + + local cnt = 0 + + for item, _ in ADDON.utils:PairsByKey(list, self.sortFunction) do + item:ClearAllPoints() + item:SetParent(self) + + if self.max and cnt >= self.cols then + item:Hide() + else + item:SetPoint('TOPLEFT', x, y) + item:Show() + + width = width or self.cols * (self.spacing + item:GetWidth()) - self.spacing + self.padding * 2 + height = math.max(height, -y + item:GetHeight() + self.padding) + + cnt = cnt + 1 + + if cnt % self.cols == 0 then + y = y - self.spacing - item:GetHeight() + x = self.padding + else + x = x + self.spacing + item:GetWidth() + end + end + end + if width then + self:SetSize(width, height) + end +end + +function container:IsEmpty() + return next(self.items) == nil +end \ No newline at end of file diff --git a/src/lua/elements/mainBar.lua b/src/lua/elements/mainBar.lua new file mode 100644 index 0000000..5645dc0 --- /dev/null +++ b/src/lua/elements/mainBar.lua @@ -0,0 +1,91 @@ +local NAME, ADDON = ... + +ADDON.mainBar = {} +ADDON.mainBar.__index = ADDON.mainBar + +local bar = ADDON.mainBar +setmetatable(bar, { + __call = function(tbl, parent) + local container = ADDON.container('DJBagsMoneyBar', parent) + + for k, v in pairs(tbl) do + container[k] = v + end + + container:Init() + container:Setup() + + return container + end +}) + +function bar:Init() + self:SetMovable(true) + self:EnableMouse(true) + self:RegisterForDrag("LeftButton") + self:SetScript("OnDragStart", function(self, ...) + if self:GetParent() then + self:GetParent():StartMoving(...) + end + end) + self:SetScript("OnDragStop", function(self, ...) + if self:GetParent() then + self:GetParent():StopMovingOrSizing(...) + end + end) + + self.currencyBox = CreateFrame('FRAME', 'DJBagsMainBarCurrencyBox', self) + self.currency = self.currencyBox:CreateFontString('DJBagMainBarCurrencyText', 'OVERLAY') + self.currency:SetAllPoints() + self.currencyBox:SetPoint('TOPLEFT', 5, -5) + self.currencyBox:SetPoint('BOTTOMLEFT', 5, 5) + self.searchBox = CreateFrame('EDITBOX', 'DJBagsMainBarSearch', self, 'BagSearchBoxTemplate') + self.searchBox:SetPoint('TOPLEFT', self.currencyBox, 'TOPRIGHT', 10, 0) + self.searchBox:SetPoint('BOTTOMLEFT', self.currencyBox, 'BOTTOMRIGHT', 10, 0) + self.searchBox:SetWidth(125) + self.slots = self:CreateFontString('DJBagMainBarSlotsText', 'OVERLAY') + self.slots:SetPoint('TOPLEFT', self.searchBox, 'TOPRIGHT', 5, 0) + self.slots:SetPoint('BOTTOMLEFT', self.searchBox, 'BOTTOMRIGHT', 5, 0) + + self.currencyBox:SetScript('OnEnter', function() + local cnt = GetCurrencyListSize() + GameTooltip:SetOwner(self.currencyBox, "ANCHOR_NONE") + GameTooltip:SetPoint("BOTTOMLEFT", self.currencyBox, "TOPLEFT") + GameTooltip:SetText("Currency") + for index = 1, cnt do + local name, _, _, _, _, count, texture, _, _, _, _ = GetCurrencyListInfo(index) + if count ~= 0 and texture ~= nil then + GameTooltip:AddDoubleLine(name, count .. " |T" .. texture .. ":16|t", 1, 1, 1, 1, 1, 1) + end + end + GameTooltip:Show() + end) + + self.currencyBox:SetScript('OnLeave', function() + GameTooltip:Hide() + end) +end + +function bar:Setup() + ADDON.container.Setup(self) + + local settings = ADDON.settings.moneyBar + self.currency:SetFont(settings.currencyFont, settings.currencyFontSize, '') + self.currency:SetTextColor(unpack(settings.currencyFontColor)) + self.slots:SetFont(settings.slotsFont, settings.slotsFontSize, '') + self.slots:SetTextColor(unpack(settings.slotsFontColor)) +end + +function bar:Update() + self.currency:SetText(GetCoinTextureString(GetMoney())) + + local total, free = 0, 0 + for bag = 0, NUM_BAG_SLOTS do + total = total + GetContainerNumSlots(bag) + free = free + GetContainerNumFreeSlots(bag) + end + self.slots:SetText(string.format("%d/%d", total - free, total)) + + self.currencyBox:SetWidth(self.currency:GetStringWidth()) + self:SetSize(self.currency:GetStringWidth() + self.slots:GetStringWidth() + 165, self.currency:GetStringHeight() + 12) +end diff --git a/src/lua/event/eventManager.lua b/src/lua/event/eventManager.lua new file mode 100644 index 0000000..7540ae4 --- /dev/null +++ b/src/lua/event/eventManager.lua @@ -0,0 +1,41 @@ +local NAME, ADDON = ... + +local eventFrame = CreateFrame("FRAME", "DJBagsEventsFrame", nil) +eventFrame:Hide() + +eventFrame.types = {} + +function eventFrame:FireEvent(event, ...) + if not self.types[event] then return end + + for k, _ in pairs(self.types[event]) do + if k[event] then + k[event](k, ...) + end + end +end + +eventFrame:SetScript("OnEvent", eventFrame.AddEvent) + +function eventFrame:AddEvent(obj, event) + if not obj[event] then return end + + if not self.types[event] then + self.types[event] = {} + self:RegisterEvent(event) + end + + self.types[event][obj] = true +end + +function eventFrame:RemoveEvent(obj, event) + if not self.types[event] and not self.types[event][obj] then return end + + self.types[event][obj] = nil + + if #self.types[event] <= 0 then + self:UnregisterEvent(event) + end +end + +ADDON.eventManager = eventFrame \ No newline at end of file diff --git a/src/lua/settings/defaults/category.lua b/src/lua/settings/defaults/category.lua new file mode 100644 index 0000000..2455a8c --- /dev/null +++ b/src/lua/settings/defaults/category.lua @@ -0,0 +1,26 @@ +local NAME, ADDON = ... + +ADDON.settings = ADDON.settings or {} + +ADDON.settings.categories = { + subClass = { + [LE_ITEM_CLASS_CONSUMABLE] = true, + [LE_ITEM_CLASS_CONTAINER] = false, + [LE_ITEM_CLASS_WEAPON] = false, + [LE_ITEM_CLASS_GEM] = false, + [LE_ITEM_CLASS_ARMOR] = false, + [LE_ITEM_CLASS_TRADEGOODS] = true, + [LE_ITEM_CLASS_ITEM_ENHANCEMENT] = false, + [LE_ITEM_CLASS_RECIPE] = false, + [LE_ITEM_CLASS_QUESTITEM] = false, + [LE_ITEM_CLASS_MISCELLANEOUS] = true, + [LE_ITEM_CLASS_GLYPH] = false, + [LE_ITEM_CLASS_BATTLEPET] = false, + }, + userDefined = { + [12] = 'Testerize', + [154] = 'ASD', + [124] = 'ZXC', + } +} + diff --git a/src/lua/settings/defaults/categoryContainer.lua b/src/lua/settings/defaults/categoryContainer.lua new file mode 100644 index 0000000..cd59d76 --- /dev/null +++ b/src/lua/settings/defaults/categoryContainer.lua @@ -0,0 +1,11 @@ +local NAME, ADDON = ... + +ADDON.settings = ADDON.settings or {} + +ADDON.settings.categoryContainer = { + padding = 5, + spacing = 3, + maxHeight = 450, + sortFunction = 'default', +} + diff --git a/src/lua/settings/defaults/container.lua b/src/lua/settings/defaults/container.lua new file mode 100644 index 0000000..8b57935 --- /dev/null +++ b/src/lua/settings/defaults/container.lua @@ -0,0 +1,9 @@ +local NAME, ADDON = ... + +ADDON.settings = ADDON.settings or {} + +ADDON.settings.container = { + borderColor = { 0.3, 0.3, 0.3, 0.9 }, + borderWidth = 1, + backgroundColor = { 0, 0, 0, 0.6 }, +} \ No newline at end of file diff --git a/src/lua/settings/defaults/item.lua b/src/lua/settings/defaults/item.lua new file mode 100644 index 0000000..29c84f9 --- /dev/null +++ b/src/lua/settings/defaults/item.lua @@ -0,0 +1,8 @@ +local NAME, ADDON = ... + +ADDON.settings = ADDON.settings or {} + +ADDON.settings.item = { + size = 32, +} + diff --git a/src/lua/settings/defaults/itemContainer.lua b/src/lua/settings/defaults/itemContainer.lua new file mode 100644 index 0000000..3fd258e --- /dev/null +++ b/src/lua/settings/defaults/itemContainer.lua @@ -0,0 +1,14 @@ +local NAME, ADDON = ... + +ADDON.settings = ADDON.settings or {} + +ADDON.settings.itemContainer = { + spacing = 3, + padding = 5, + cols = 5, + font = 'Fonts\\FRIZQT__.TTF', + fontSize = 13, + fontColor = { 0.5, 1, 0.5, 1 }, + titleMargin = 5, + sortFunction = 'default', +} \ No newline at end of file diff --git a/src/lua/settings/defaults/mainBar.lua b/src/lua/settings/defaults/mainBar.lua new file mode 100644 index 0000000..ac9eeb7 --- /dev/null +++ b/src/lua/settings/defaults/mainBar.lua @@ -0,0 +1,12 @@ +local NAME, ADDON = ... + +ADDON.settings = ADDON.settings or {} + +ADDON.settings.moneyBar = { + currencyFontSize = 12, + currencyFontColor = { 1, 1, 1, 1 }, + currencyFont = 'Fonts\\FRIZQT__.TTF', + slotsFontSize = 12, + slotsFontColor = { 1, 1, 1, 1 }, + slotsFont = 'Fonts\\FRIZQT__.TTF', +} \ No newline at end of file diff --git a/src/lua/settings/settings.lua b/src/lua/settings/settings.lua new file mode 100644 index 0000000..52a6385 --- /dev/null +++ b/src/lua/settings/settings.lua @@ -0,0 +1,20 @@ +local NAME, ADDON = ... + +ADDON.settingsController = {} +local settings = ADDON.settingsController +settings.__index = settings + +--region Events + +function settings:Init() + self:GetCharacterSettings() +end + +function settings:GetCharacterSettings() + local realm = GetRealmName() + local player = UnitName("player") + + if DJBagsConfig and DJBagsConfig[realm] and DJBagsConfig[realm][player] then + -- ADDON.settings = DJBagsConfig[realm][player] + end +end \ No newline at end of file diff --git a/src/lua/sorters/containers.lua b/src/lua/sorters/containers.lua new file mode 100644 index 0000000..fac5109 --- /dev/null +++ b/src/lua/sorters/containers.lua @@ -0,0 +1,15 @@ +local NAME, ADDON = ... + +ADDON.sorters = ADDON.sorters or {} + +ADDON.sorters.containers = { + ['default'] = function(A, B) + if A.name == ADDON.utils.EMPTY_BAG_NAME then + return true + elseif B.name == ADDON.utils.EMPTY_BAG_NAME then + return false + else + return A.name > B.name + end + end, +} \ No newline at end of file diff --git a/src/lua/sorters/items.lua b/src/lua/sorters/items.lua new file mode 100644 index 0000000..be0e56e --- /dev/null +++ b/src/lua/sorters/items.lua @@ -0,0 +1,15 @@ +local NAME, ADDON = ... + +ADDON.sorters = ADDON.sorters or {} + +ADDON.sorters.items = { + ['default'] = function(A, B) + if A.quality == B.quality then + if A.ilevel == B.ilevel then + return A.name < B.name + end + return A.ilevel > B.ilevel + end + return A.quality > B.quality + end, +} \ No newline at end of file diff --git a/src/lua/utils/utils.lua b/src/lua/utils/utils.lua new file mode 100644 index 0000000..921092b --- /dev/null +++ b/src/lua/utils/utils.lua @@ -0,0 +1,59 @@ +local NAME, ADDON = ... + +local random = math.random +ADDON.uuid = function() + local template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' + return string.gsub(template, '[xy]', function(c) + local v = (c == 'x') and random(0, 0xf) or random(8, 0xb) + return string.format('%x', v) + end) +end + +ADDON.utils = {} +ADDON.utils.__index = ADDON.utils +ADDON.utils.EMPTY_BAG_NAME = 'SUPER_RANDOM_EMPTY_BAG_NAME_123123' + +local utils = ADDON.utils + +function utils:PairsByKey(tbl, sortFunction) + local keys = {} + for k in pairs(tbl) do + tinsert(keys, k) + end + table.sort(keys, sortFunction) + local index = 0 + return function() + index = index + 1 + return keys[index], tbl[keys[index]] + end +end + +function utils:GetItemContainerName(bag, slot) + local id = GetContainerItemID(bag, slot) + + if id then + local name, link, quality, iLevel, reqLevel, className, subClassName, maxStack, equipSlot, texture, vendorPrice, cId, sCId = GetItemInfo(id) + local isInSet, setName = GetContainerItemEquipmentSetInfo(bag, slot) + + if quality == LE_ITEM_QUALITY_POOR then + return subClassName + end + + if isInSet then + return setName + end + + local userDefinedList = ADDON.settings.categories.userDefined + if userDefinedList[id] then + return userDefinedList[id] + end + + local subClassSplitList = ADDON.settings.categories.subClass + if subClassSplitList[cId] then + return className .. ' ' .. subClassName + end + + return className + end + return self.EMPTY_BAG_NAME +end \ No newline at end of file diff --git a/src/manifest.xml b/src/manifest.xml index 5e4e862..b1ce275 100644 --- a/src/manifest.xml +++ b/src/manifest.xml @@ -1,32 +1,39 @@ <Ui xsi:schemaLocation="http://www.blizzard.com/wow/ui/ http://wowprogramming.com/FrameXML/UI.xsd"> + <!-- Class --> + <Script file="src/lua/base/djclass.lua"/> + <!-- Utils --> - <!--<Script file="src/lua/util/uuid.lua"/>--> - <!--<Script file="src/lua/util/util.lua"/>--> + <Script file="src/lua/utils/utils.lua"/> <!-- Cache --> - <!--<Script file="src/lua/cache/cache.lua"/>--> + <Script file="src/lua/cache/cache.lua"/> <!-- Settings --> - <!--<Script file="src/lua/settings/defaults/item.lua"/>--> - <!--<Script file="src/lua/settings/defaults/container.lua"/>--> - <!--<Script file="src/lua/settings/defaults/itemContainer.lua"/>--> - <!--<Script file="src/lua/settings/defaults/category.lua"/>--> - <!--<Script file="src/lua/settings/defaults/categoryContainer.lua"/>--> - <!--<Script file="src/lua/settings/defaults/moneyBar.lua"/>--> - <!--<Script file="src/lua/settings/settings.lua"/>--> + <Script file="src/lua/settings/defaults/item.lua"/> + <Script file="src/lua/settings/defaults/container.lua"/> + <Script file="src/lua/settings/defaults/itemContainer.lua"/> + <Script file="src/lua/settings/defaults/category.lua"/> + <Script file="src/lua/settings/defaults/categoryContainer.lua"/> + <Script file="src/lua/settings/defaults/mainBar.lua"/> + <Script file="src/lua/settings/settings.lua"/> + + <!-- sorters --> + <Script file="src/lua/sorters/items.lua"/> + <Script file="src/lua/sorters/containers.lua"/> <!-- Tools --> - <!--<Script file="src/lua/event/eventManager.lua"/>--> + <Script file="src/lua/event/eventManager.lua"/> <!-- elements --> - <!--<Script file="src/lua/element/item.lua"/>--> - <!--<Script file="src/lua/element/container.lua"/>--> - <!--<Script file="src/lua/element/itemContainer.lua"/>--> - <!--<Script file="src/lua/element/categoryContainer.lua"/>--> - <!--<Script file="src/lua/element/moneyBar.lua"/>--> + <Script file="src/lua/elements/item.lua"/> + <Script file="src/lua/elements/container.lua"/> + <Script file="src/lua/elements/itemContainer.lua"/> + <Script file="src/lua/elements/categoryContainer.lua"/> + <Script file="src/lua/elements/mainBar.lua"/> + <Script file="src/lua/elements/categoryDialog.lua"/> <!-- Controller --> - <!--<Script file="src/lua/controller/bag.lua"/>--> + <Script file="src/lua/controllers/bag.lua"/> <!-- Core (Load last) --> <Script file="src/lua/core.lua"/>