diff --git a/Clique.lua b/Clique.lua new file mode 100644 index 0000000..57f66d7 --- /dev/null +++ b/Clique.lua @@ -0,0 +1,329 @@ +--[[--------------------------------------------------------------------------------- + Clique by Cladhaire <cladhaire@gmail.com> +----------------------------------------------------------------------------------]] + +Clique = {Locals = {}} + +DongleStub("Dongle"):New(Clique, "Clique") + +local L = Clique.Locals +-- Create a frame for event registration +local eventFrame = CreateFrame("Frame") +local elapsed = 0 +eventFrame:SetScript("OnUpdate", function() + elapsed = elapsed + arg1 + if elapsed >= 2.0 then + elapsed = 0 + Clique:ClearQueue() + end +end) +eventFrame:Hide() + +if not InCombatLockdown then + function InCombatLockdown() + return UnitAffectingCombat("player") + end +end + +function Clique:Enable() + -- Grab the localisation header + L = Clique.Locals + + self.defaults = { + profile = { + [L.CLICKSET_DEFAULT] = {}, + [L.CLICKSET_HARMFUL] = {}, + [L.CLICKSET_HELPFUL] = {}, + [L.CLICKSET_OOC] = {}, + } + } + + self.db = self:InitializeDB("CliqueDB", self.defaults) + self.profile = self.db.profile + + self.editSet = self.profile[L.CLICKSET_DEFAULT] + + local newindex = function(t,k,v) + Clique:RegisterFrame(k) + rawset(t,k,v) + end + + ClickCastFrames = ClickCastFrames or {} + setmetatable(ClickCastFrames, {__newindex=newindex}) + + -- Register all frames that snuck in before we did =) + for frame in pairs(ClickCastFrames) do + self:RegisterFrame(frame) + end + + Clique:OptionsOnLoad() + Clique:EnableFrames() + + -- Run the OOC script if we need to + Clique:CombatUnlock() + + -- Securehook the RaidFrame_LoadUI + local raidFunc = function(type, name, parent, template) + if template == "RaidPulloutButtonTemplate" then + ClickCastFrames[getglobal(name.."ClearButton")] = true + end + end + + hooksecurefunc("CreateFrame", raidFunc) +end + +function Clique:EnableFrames() + local tbl = { + PlayerFrame, + PetFrame, + PartyMemberFrame1, + PartyMemberFrame2, + PartyMemberFrame3, + PartyMemberFrame4, + PartyMemberFrame1PetFrame, + PartyMemberFrame2PetFrame, + PartyMemberFrame3PetFrame, + PartyMemberFrame4PetFrame, + TargetFrame, + TargetofTargetFrame, + } + + for i,frame in pairs(tbl) do + ClickCastFrames[frame] = true + end +end + +function Clique:SpellBookButtonPressed() + local id = SpellBook_GetSpellID(this:GetParent():GetID()); + local texture = GetSpellTexture(id, SpellBookFrame.bookType) + local name, rank = GetSpellName(id, SpellBookFrame.bookType) + + if rank == L.RACIAL_PASSIVE or rank == L.PASSIVE then + StaticPopup_Show("CLIQUE_PASSIVE_SKILL") + return + else + rank = select(3, string.find(rank, L.RANK_PATTERN)) + if rank then rank = tonumber(rank) end + end + + local type = "spell" + local button + + if self.editSet == self.profile[L.CLICKSET_HARMFUL] then + button = string.format("%s%d", "harmbutton", self:GetButtonNumber()) + elseif self.editSet == self.profile[L.CLICKSET_HELPFUL] then + button = string.format("%s%d", "helpbutton", self:GetButtonNumber()) + else + button = self:GetButtonNumber() + end + + -- Build the SVN/live structure + local t = { + ["button"] = button, + ["modifier"] = self:GetModifierText(), + ["texture"] = GetSpellTexture(id, SpellBookFrame.bookType), + ["type"] = type, + ["arg1"] = name, + ["arg2"] = rank, + } + + local key = t.modifier .. t.button + + if self:CheckBinding(key) then + StaticPopup_Show("CLIQUE_BINDING_PROBLEM") + return + end + + self.editSet[key] = t + + self:SetAction(t) + self:ListScrollUpdate() +end + +function Clique:CombatLockdown() + self:Debug(1, "Going into combat mode") + -- Remove all OOC clicks + for k,v in pairs(self.profile[L.CLICKSET_OOC]) do + self:DeleteAction(v) + self:Debug(1, "Removing %s, %s", v.type, tostring(v.arg1)) + end + + -- Just bluntly force our clicks back onto the frames + for frame in pairs(ClickCastFrames) do + self:RegisterFrame(frame) + end +end + +function Clique:CombatUnlock() + self:Debug(1, "Setting any out of combat clicks") + for frame in pairs(ClickCastFrames) do + for k,v in pairs(self.profile[L.CLICKSET_OOC]) do + self:SetAttribute(v,frame) + end + end +end + +local queue = {} + +function Clique:CombatDelay(tbl) + if InCombatLockdown() then + if #queue == 0 then + self:Print("Cannot make changes in combat. These changes will be delayed until you exit combat.") + end + table.insert(queue, tbl) + eventFrame:Show() + return true + end +end + +function Clique:ClearQueue() + if InCombatLockdown() then return end + + eventFrame:Hide() + self:Print("Out of combat. Applying all queued changes.") + for k,v in ipairs(queue) do + if v.GetAttribute then + self:RegisterFrame(v) + else + if v.delete then + self:DeleteAction(v) + else + self:SetAction(v) + end + end + end + queue = {} +end + +function Clique:RegisterFrame(frame) + if self:CombatDelay(frame) then return end + -- Ensure we have all the buttons registered + frame:RegisterForClicks("LeftButtonUp", "MiddleButtonUp", "RightButtonUp", "Button4Up", "Button5Up") + + for name,set in pairs(self.profile) do + if name ~= L.CLICKSET_OOC then + for modifier,entry in pairs(set) do + self:SetAttribute(entry, frame) + end + end + end +end + +function Clique:ProfileChanged(new) + + for name,set in pairs(self.profile) do + for modifier,entry in pairs(set) do + self:DeleteAction(entry) + end + end + + self.profile = self.db.profile + self.editSet = self.profile[L.CLICKSET_DEFAULT] + self.profileKey = new + + -- refresh the dropdown if its active + CliqueDropDownProfile:Hide() + CliqueDropDownProfile:Show() + + self:Print("Profile changed to '%s'", new) + + for frame in pairs(ClickCastFrames) do + self:RegisterFrame(frame) + end +end + +function Clique:SetAttribute(entry, frame) + -- Set up any special attributes + local type,button,value + + if not tonumber(entry.button) then + type,button = select(3, string.find(entry.button, "(%a+)button(%d+)")) + frame:SetAttribute(entry.modifier..entry.button, type..button) + button = string.format("-%s%s", type, button) + end + + button = button or entry.button + + if entry.type == "actionbar" then + frame:SetAttribute(entry.modifier.."type"..button, entry.type) + frame:SetAttribute(entry.modifier.."action"..button, entry.arg1) + elseif entry.type == "action" then + frame:SetAttribute(entry.modifier.."type"..button, entry.type) + frame:SetAttribute(entry.modifier.."action"..button, entry.arg1) + frame:SetAttribute(entry.modifier.."unit"..button, entry.arg2) + elseif entry.type == "pet" then + frame:SetAttribute(entry.modifier.."type"..button, entry.type) + frame:SetAttribute(entry.modifier.."action"..button, entry.arg1) + frame:SetAttribute(entry.modifier.."unit"..button, entry.arg2) + elseif entry.type == "spell" then + local rank = tonumber(entry.arg2) + local cast = string.format(rank and L.CAST_FORMAT or "%s", entry.arg1, rank) + frame:SetAttribute(entry.modifier.."type"..button, entry.type) + frame:SetAttribute(entry.modifier.."spell"..button, cast) + + frame:SetAttribute(entry.modifier.."bag"..button, entry.arg2) + frame:SetAttribute(entry.modifier.."slot"..button, entry.arg3) + frame:SetAttribute(entry.modifier.."item"..button, entry.arg4) + frame:SetAttribute(entry.modifier.."unit"..button, entry.arg5) + elseif entry.type == "item" then + frame:SetAttribute(entry.modifier.."type"..button, entry.type) + frame:SetAttribute(entry.modifier.."bag"..button, entry.arg1) + frame:SetAttribute(entry.modifier.."slot"..button, entry.arg2) + frame:SetAttribute(entry.modifier.."item"..button, entry.arg3) + frame:SetAttribute(entry.modifier.."unit"..button, entry.arg4) + elseif entry.type == "macro" then + frame:SetAttribute(entry.modifier.."type"..button, entry.type) + frame:SetAttribute(entry.modifier.."macro"..button, entry.arg1) + elseif entry.type == "stop" then + frame:SetAttribute(entry.modifier.."type"..button, entry.type) + elseif entry.type == "target" then + frame:SetAttribute(entry.modifier.."type"..button, entry.type) + frame:SetAttribute(entry.modifier.."unit"..button, entry.arg1) + elseif entry.type == "focus" then + frame:SetAttribute(entry.modifier.."type"..button, entry.type) + frame:SetAttribute(entry.modifier.."unit"..button, entry.arg1) + elseif entry.type == "assist" then + frame:SetAttribute(entry.modifier.."type"..button, entry.type) + frame:SetAttribute(entry.modifier.."unit"..button, entry.arg1) + elseif entry.type == "click" then + frame:SetAttribute(entry.modifier.."type"..button, entry.type) + frame:SetAttribute(entry.modifier.."delegate"..button, getglobal(entry.arg1)) + end +end + +function Clique:SetAction(entry) + if self:CombatDelay(entry) then return end + for frame in pairs(ClickCastFrames) do + self:SetAttribute(entry, frame) + end +end + +function Clique:DeleteAction(entry) + local type,button,value + + if not tonumber(entry.button) then + type,button = select(3, string.find(entry.button, "(%a+)button(%d+)")) + for frame in pairs(ClickCastFrames) do + frame:SetAttribute(entry.modifier..entry.button, nil) + end + button = string.format("-%s%s", type, button) + end + + button = button or entry.button + + entry.delete = true + + if self:CombatDelay(entry) then return end + for frame in pairs(ClickCastFrames) do + frame:SetAttribute(entry.modifier.."type"..button, nil) + frame:SetAttribute(entry.modifier..entry.type..button, nil) + end +end + +function Clique:Print(msg, ...) + if string.find(msg, "%%") then + -- This is a string format, so lets format + msg = string.format(msg, ...) + end + ChatFrame1:AddMessage("|cFF33FF99Clique|r: " .. tostring(msg)) +end diff --git a/Clique.toc b/Clique.toc new file mode 100644 index 0000000..437e21e --- /dev/null +++ b/Clique.toc @@ -0,0 +1,16 @@ +## Interface: 20000 +## Title: Clique +## Author: Cladhaire +## Notes: Simply powerful click-casting interface +## SavedVariables: CliqueDB +## OptionalDeps: Dongle + +Clique.lua +Clique.xml +Localization.en.lua +Localization.fr.lua +Localization.de.lua +Localization.zh.lua +Localization.kr.lua +CliqueOptions.lua +CliqueUtils.lua diff --git a/Clique.xml b/Clique.xml new file mode 100644 index 0000000..e386fa8 --- /dev/null +++ b/Clique.xml @@ -0,0 +1,43 @@ +<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ +..\FrameXML\UI.xsd"> + <CheckButton name="CliqueIconTemplate" virtual="true"> + <Size> + <AbsDimension x="36" y="36"/> + </Size> + <Layers> + <Layer level="BACKGROUND"> + <Texture file="Interface\Buttons\UI-EmptySlot-Disabled"> + <Size> + <AbsDimension x="64" y="64"/> + </Size> + <Anchors> + <Anchor point="CENTER"> + <Offset> + <AbsDimension x="0" y="-1"/> + </Offset> + </Anchor> + </Anchors> + </Texture> + </Layer> + </Layers> + <NormalTexture name="$parentIcon"> + <Size> + <AbsDimension x="36" y="36"/> + </Size> + <Anchors> + <Anchor point="CENTER"> + <Offset> + <AbsDimension x="0" y="-1"/> + </Offset> + </Anchor> + </Anchors> + </NormalTexture> + <HighlightTexture alphaMode="ADD" file="Interface\Buttons\ButtonHilight-Square"/> + <CheckedTexture alphaMode="ADD" file="Interface\Buttons\CheckButtonHilight"/> + <Scripts> + <OnClick> + Clique:SetSpellIcon() + </OnClick> + </Scripts> + </CheckButton> +</Ui> diff --git a/CliqueOptions.lua b/CliqueOptions.lua new file mode 100644 index 0000000..2a1eee7 --- /dev/null +++ b/CliqueOptions.lua @@ -0,0 +1,1279 @@ +local L = Clique.Locals + +local NUM_ENTRIES = 10 +local ENTRY_SIZE = 35 +local work = {} + +function Clique:OptionsOnLoad() + -- Create a set of buttons to hook the SpellbookFrame + self.spellbuttons = {} + local onclick = function() Clique:SpellBookButtonPressed() end + local onleave = function() + this.updateTooltip = nil + GameTooltip:Hide() + end + + for i=1,12 do + local parent = getglobal("SpellButton"..i) + local button = CreateFrame("Button", nil, parent) + button:SetID(parent:GetID()) + button:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square") + button:RegisterForClicks("LeftButtonUp","RightButtonUp", "MiddleButtonUp", "Button4Up", "Button5Up") + button:SetAllPoints(parent) + button:SetScript("OnClick", onclick) + button:SetScript("OnEnter", SpellButton_OnEnter) + button:SetScript("OnLeave", onleave) + button:Hide() + self.spellbuttons[i] = button + end + + CreateFrame("CheckButton", "CliquePulloutTab", SpellBookFrame, "SpellBookSkillLineTabTemplate") + CliquePulloutTab:SetNormalTexture("Interface\\AddOns\\Clique\\Images\\CliqueIcon") + CliquePulloutTab:SetScript("OnClick", function() Clique:Toggle() end) + CliquePulloutTab:SetScript("OnEnter", function() local i = 1 end) + CliquePulloutTab:SetScript("OnShow", function() + Clique.inuse = nil + for k,v in pairs(self.profile) do + if next(v) then + Clique.inuse = true + end + end + if not Clique.inuse then + CliqueFlashFrame.texture:Show() + UIFrameFlash(CliqueFlashFrame, 0.5, 0.5, 30, nil) + end + end) + + local frame = CreateFrame("Frame", "CliqueFlashFrame", CliquePulloutTab) + frame:SetWidth(10) frame:SetHeight(10) + frame:SetPoint("CENTER", 0, 0) + + local texture = frame:CreateTexture(nil, "OVERLAY") + texture:SetTexture("Interface\\Buttons\\CheckButtonGlow") + texture:SetHeight(64) texture:SetWidth(64) + texture:SetPoint("CENTER", 0, 0) + texture:Hide() + CliqueFlashFrame.texture = texture + + CliquePulloutTab:Show() + + local num = GetNumSpellTabs() + CliquePulloutTab:ClearAllPoints() + CliquePulloutTab:SetPoint("TOPLEFT","SpellBookSkillLineTab"..(num),"BOTTOMLEFT",0,-17) + + -- Hook the container buttons + local containerFunc = function(button) + if IsShiftKeyDown() and CliqueCustomArg1 then + if CliqueCustomArg1:HasFocus() then + CliqueCustomArg1:Insert(GetContainerItemLink(this:GetParent():GetID(), this:GetID())) + elseif CliqueCustomArg2:HasFocus() then + CliqueCustomArg2:Insert(GetContainerItemLink(this:GetParent():GetID(), this:GetID())) + elseif CliqueCustomArg3:HasFocus() then + CliqueCustomArg3:Insert(GetContainerItemLink(this:GetParent():GetID(), this:GetID())) + elseif CliqueCustomArg4:HasFocus() then + CliqueCustomArg4:Insert(GetContainerItemLink(this:GetParent():GetID(), this:GetID())) + elseif CliqueCustomArg5:HasFocus() then + CliqueCustomArg5:Insert(GetContainerItemLink(this:GetParent():GetID(), this:GetID())) + end + end + end + + hooksecurefunc("ContainerFrameItemButton_OnModifiedClick", containerFunc) + + -- Hook the bank buttons + local bankFunc = function(button) + if IsShiftKeyDown() and CliqueCustomArg1 then + if CliqueCustomArg1:HasFocus() then + CliqueCustomArg1:Insert(GetContainerItemLink(BANK_CONTAINER, this:GetID())) + elseif CliqueCustomArg2:HasFocus() then + CliqueCustomArg2:Insert(GetContainerItemLink(BANK_CONTAINER, this:GetID())) + elseif CliqueCustomArg3:HasFocus() then + CliqueCustomArg3:Insert(GetContainerItemLink(BANK_CONTAINER, this:GetID())) + elseif CliqueCustomArg4:HasFocus() then + CliqueCustomArg4:Insert(GetContainerItemLink(BANK_CONTAINER, this:GetID())) + elseif CliqueCustomArg5:HasFocus() then + CliqueCustomArg5:Insert(GetContainerItemLink(BANK_CONTAINER, this:GetID())) + end + end + end + + hooksecurefunc("BankFrameItemButtonGeneric_OnModifiedClick", bankFunc) + + -- Hook the paper doll frame buttons + local dollFunc = function(button) + if IsShiftKeyDown() and CliqueCustomArg1 then + if CliqueCustomArg1:HasFocus() then + CliqueCustomArg1:Insert(GetInventoryItemLink("player", this:GetID())) + elseif CliqueCustomArg2:HasFocus() then + CliqueCustomArg2:Insert(GetInventoryItemLink("player", this:GetID())) + elseif CliqueCustomArg3:HasFocus() then + CliqueCustomArg3:Insert(GetInventoryItemLink("player", this:GetID())) + elseif CliqueCustomArg4:HasFocus() then + CliqueCustomArg4:Insert(GetInventoryItemLink("player", this:GetID())) + elseif CliqueCustomArg5:HasFocus() then + CliqueCustomArg5:Insert(GetInventoryItemLink("player", this:GetID())) + end + end + end + hooksecurefunc("PaperDollItemSlotButton_OnModifiedClick", dollFunc) +end + +function Clique:ToggleSpellBookButtons() + local method = CliqueFrame:IsVisible() and "Show" or "Hide" + local buttons = self.spellbuttons + for i=1,12 do + buttons[i][method](buttons[i]) + end +end + +function Clique:Toggle() + if not CliqueFrame then + Clique:CreateOptionsFrame() + CliqueFrame:Hide() + CliqueFrame:Show() + else + if CliqueFrame:IsVisible() then + CliqueFrame:Hide() + CliquePulloutTab:SetChecked(nil) + else + CliqueFrame:Show() + CliquePulloutTab:SetChecked(true) + end + end + + Clique:ToggleSpellBookButtons() + self:ListScrollUpdate() +end + +-- This code is contributed with permission from Beladona +local ondragstart = function() + this:GetParent():StartMoving() +end + +local ondragstop = function() + this:GetParent():StopMovingOrSizing() + this:GetParent():SetUserPlaced() +end + +function Clique:SkinFrame(frame) + frame:SetBackdrop({ + bgFile = "Interface\\AddOns\\Clique\\images\\backdrop.tga", + edgeFile = "Interface\\AddOns\\Clique\\images\\borders.tga", tile = true, + tileSize = 32, edgeSize = 16, + insets = {left = 16, right = 16, top = 16, bottom = 16} + }); + + frame:EnableMouse() + + frame.titleBar = CreateFrame("Button", nil, frame) + frame.titleBar:SetHeight(32) + frame.titleBar:SetPoint("TOPLEFT", frame, "TOPLEFT", 2, -2) + frame.titleBar:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -2, -2) + frame:SetMovable(true) + frame:SetFrameStrata("MEDIUM") + frame.titleBar:RegisterForDrag("LeftButton") + frame.titleBar:SetScript("OnDragStart", ondragstart) + frame.titleBar:SetScript("OnDragStop", ondragstop) + + frame.headerLeft = frame.titleBar:CreateTexture(nil, "ARTWORK"); + frame.headerLeft:SetTexture("Interface\\AddOns\\Clique\\images\\headCorner.tga"); + frame.headerLeft:SetWidth(32); frame.headerLeft:SetHeight(32); + frame.headerLeft:SetPoint("TOPLEFT", 0, 0); + + frame.headerRight = frame.titleBar:CreateTexture(nil, "ARTWORK"); + frame.headerRight:SetTexture("Interface\\AddOns\\Clique\\images\\headCorner.tga"); + frame.headerRight:SetTexCoord(1,0,0,1); + frame.headerRight:SetWidth(32); frame.headerRight:SetHeight(32); + frame.headerRight:SetPoint("TOPRIGHT", 0, 0); + + frame.header = frame.titleBar:CreateTexture(nil, "ARTWORK"); + frame.header:SetTexture("Interface\\AddOns\\Clique\\images\\header.tga"); + frame.header:SetPoint("TOPLEFT", frame.headerLeft, "TOPRIGHT"); + frame.header:SetPoint("BOTTOMRIGHT", frame.headerRight, "BOTTOMLEFT"); + + frame.title = frame.titleBar:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall"); + frame.title:SetWidth(200); frame.title:SetHeight(16); + frame.title:SetPoint("TOP", 0, -2); + + frame.footerLeft = frame:CreateTexture(nil, "ARTWORK"); + frame.footerLeft:SetTexture("Interface\\AddOns\\Clique\\images\\footCorner.tga"); + frame.footerLeft:SetWidth(48); frame.footerLeft:SetHeight(48); + frame.footerLeft:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 2, 2); + + frame.footerRight = frame:CreateTexture(nil, "ARTWORK"); + frame.footerRight:SetTexture("Interface\\AddOns\\Clique\\images\\footCorner.tga"); + frame.footerRight:SetTexCoord(1,0,0,1); + frame.footerRight:SetWidth(48); frame.footerRight:SetHeight(48); + frame.footerRight:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -2, 2); + + frame.footer = frame:CreateTexture(nil, "ARTWORK"); + frame.footer:SetTexture("Interface\\AddOns\\Clique\\images\\footer.tga"); + frame.footer:SetPoint("TOPLEFT", frame.footerLeft, "TOPRIGHT"); + frame.footer:SetPoint("BOTTOMRIGHT", frame.footerRight, "BOTTOMLEFT"); +end + +function Clique:CreateOptionsFrame() + local frames = {} + self.frames = frames + + local frame = CreateFrame("Frame", "CliqueFrame", SpellBookFrame) + frame:SetHeight(415) + frame:SetWidth(400) + frame:SetPoint("LEFT", SpellBookFrame, "RIGHT", 15, 30) + self:SkinFrame(frame) + frame.title:SetText("Clique (BC) v0.1"); + frame:SetScript("OnShow", function() + if Clique.inuse then + CliqueHelpText:Hide() + else + CliqueHelpText:Show() + end + end) + + local frame = CreateFrame("Frame", "CliqueListFrame", CliqueFrame) + frame:SetAllPoints() + + local onclick = function() + local offset = FauxScrollFrame_GetOffset(CliqueListScroll) + self.listSelected = offset + this.id + Clique:ListScrollUpdate() + end + + local onenter = function() this:SetBackdropBorderColor(1, 1, 1) end + local onleave = function() + local selected = FauxScrollFrame_GetOffset(CliqueListScroll) + this.id + if selected == self.listSelected then + this:SetBackdropBorderColor(1, 1, 0) + else + this:SetBackdropBorderColor(0.3, 0.3, 0.3) + end + end + + for i=1,NUM_ENTRIES do + local entry = CreateFrame("Button", "CliqueList"..i, frame) + entry.id = i + entry:SetHeight(ENTRY_SIZE) + entry:SetWidth(390) + entry:SetBackdrop({ + bgFile="Interface\\Tooltips\\UI-Tooltip-Background", + edgeFile = "Interface/Tooltips/UI-Tooltip-Border", + tile = true, tileSize = 8, edgeSize = 16, + insets = {left = 2, right = 2, top = 2, bottom = 2}}) + + entry:SetBackdropBorderColor(0.3, 0.3, 0.3) + entry:SetBackdropColor(0.1, 0.1, 0.1, 0.3) + entry:SetScript("OnClick", onclick) + entry:SetScript("OnEnter", onenter) + entry:SetScript("OnLeave", onleave) + + entry.icon = entry:CreateTexture(nil, "ARTWORK") + entry.icon:SetHeight(24) + entry.icon:SetWidth(24) + entry.icon:SetPoint("LEFT", 5, 0) + + entry.name = entry:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall") + entry.name:SetPoint("LEFT", entry.icon, "RIGHT", 5, 0) + + entry.binding = entry:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall") + entry.binding:SetPoint("RIGHT", entry, "RIGHT", -5, 0) + frames[i] = entry + end + + frames[1]:SetPoint("TOPLEFT", 5, -55) + for i=2,NUM_ENTRIES do + frames[i]:SetPoint("TOP", frames[i-1], "BOTTOM", 0, 2) + end + + local endButton = getglobal("CliqueList"..NUM_ENTRIES) + CreateFrame("ScrollFrame", "CliqueListScroll", CliqueListFrame, "FauxScrollFrameTemplate") + CliqueListScroll:SetPoint("TOPLEFT", CliqueList1, "TOPLEFT", 0, 0) + CliqueListScroll:SetPoint("BOTTOMRIGHT", endButton, "BOTTOMRIGHT", 0, 0) + + local texture = CliqueListScroll:CreateTexture(nil, "BACKGROUND") + texture:SetTexture("Interface\\ChatFrame\\ChatFrameBackground") + texture:SetPoint("TOPLEFT", CliqueListScroll, "TOPRIGHT", 14, 0) + texture:SetPoint("BOTTOMRIGHT", CliqueListScroll, "BOTTOMRIGHT", 23, 0) + texture:SetGradientAlpha("HORIZONTAL", 0.5, 0.25, 0.05, 0, 0.15, 0.15, 0.15, 1) + + local texture = CliqueListScroll:CreateTexture(nil, "BACKGROUND") + texture:SetTexture("Interface\\ChatFrame\\ChatFrameBackground") + texture:SetPoint("TOPLEFT", CliqueListScroll, "TOPRIGHT", 4, 0) + texture:SetPoint("BOTTOMRIGHT", CliqueListScroll, "BOTTOMRIGHT", 14, 0) + texture:SetGradientAlpha("HORIZONTAL", 0.15, 0.15, 0.15, 0.15, 1, 0.5, 0.25, 0.05, 0) + + local update = function() Clique:ListScrollUpdate() end + + CliqueListScroll:SetScript("OnVerticalScroll", function() FauxScrollFrame_OnVerticalScroll(ENTRY_SIZE, update) end) + CliqueListScroll:SetScript("OnShow", update) + + -- Dropdown Frame + CreateFrame("Frame", "CliqueDropDown", CliqueFrame, "UIDropDownMenuTemplate") + CliqueDropDown:SetID(1) + CliqueDropDown:SetPoint("TOPRIGHT", -115, -25) + CliqueDropDown:SetScript("OnShow", function() Clique:DropDown_OnShow() end) + + local font = CliqueDropDown:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall") + font:SetText("Click Set:") + font:SetPoint("RIGHT", CliqueDropDown, "LEFT", 5, 3) + + -- Profile Dropdown Frame + CreateFrame("Frame", "CliqueDropDownProfile", CliqueFrame, "UIDropDownMenuTemplate") + CliqueDropDownProfile:SetID(1) + CliqueDropDownProfile:SetPoint("RIGHT", CliqueDropDown, "LEFT", -210, 0) + CliqueDropDownProfile:SetScript("OnShow", function() Clique:DropDownProfile_OnShow() end) + + -- Button Creations + local buttonFunc = function() Clique:ButtonOnClick() end + + local button = CreateFrame("Button", "CliqueButtonClose", CliqueFrame.titleBar, "UIPanelCloseButton") + button:SetHeight(25) + button:SetWidth(25) + button:SetPoint("TOPRIGHT", -5, 3) + button:SetScript("OnClick", buttonFunc) + + local button = CreateFrame("Button", "CliqueButtonDelete", CliqueFrame, "UIPanelButtonGrayTemplate") + button:SetHeight(24) + button:SetWidth(70) + button:SetText("Delete") + button:SetPoint("BOTTOM", -38, 4) + button:SetScript("OnClick", buttonFunc) + + local button = CreateFrame("Button", "CliqueButtonEdit", CliqueFrame, "UIPanelButtonGrayTemplate") + button:SetHeight(24) + button:SetWidth(70) + button:SetText("Edit") + button:SetPoint("BOTTOM", 38, 4) + button:SetScript("OnClick", buttonFunc) + + local button = CreateFrame("Button", "CliqueButtonMax", CliqueFrame, "UIPanelButtonGrayTemplate") + button:SetHeight(24) + button:SetWidth(70) + button:SetText("Max Rank") + button:SetPoint("LEFT", CliqueButtonEdit, "RIGHT", 6, 0) + button:SetScript("OnClick", buttonFunc) + + -- Create the custom edit screen + local button = CreateFrame("Button", "CliqueButtonCustom", CliqueFrame, "UIPanelButtonGrayTemplate") + button:SetHeight(24) + button:SetWidth(70) + button:SetText("Custom") + button:SetPoint("RIGHT", CliqueButtonDelete, "LEFT", -6, 0) + button:SetScript("OnClick", buttonFunc) + self.customEntry = {} + + local frame = CreateFrame("Frame", "CliqueCustomFrame", CliqueFrame) + frame:SetHeight(375) + frame:SetWidth(450) + frame:SetPoint("CENTER", 70, -50) + self:SkinFrame(frame) + frame.title:SetText("Clique Custom Editor"); + frame:SetFrameStrata("HIGH") + frame:Hide() + + -- Help text for Custom screen + + local font = frame:CreateFontString("CliqueCustomHelpText", "OVERLAY", "GameFontHighlight") + font:SetWidth(260) font:SetHeight(100) + font:SetPoint("TOPRIGHT", -10, -25) + font:SetText(L.CUSTOM_HELP) + + local checkFunc = function() Clique:CustomRadio() end + self.radio = {} + + local buttons = { + {type = "actionbar", name = "Change ActionBar"}, + {type = "action", name = "Action Button"}, + {type = "pet", name = "Pet Action Button"}, + {type = "spell", name = "Cast Spell"}, + {type = "item", name = "Use Item"}, + {type = "macro", name = "Run Custom Macro"}, + {type = "stop", name = "Stop Casting"}, + {type = "target", name = "Target Unit"}, + {type = "focus", name = "Set Focus"}, + {type = "assist", name = "Assist Unit"}, + {type = "click", name = "Click Button"}, + } + + local entry = buttons[1] + local name = "CliqueRadioButton"..entry.type + local button = CreateFrame("CheckButton", name, CliqueCustomFrame, "UIRadioButtonTemplate") + button.type = entry.type + getglobal(name.."Text"):SetText(entry.name) + button:SetPoint("TOPLEFT", 5, -30) + button:SetScript("OnClick", checkFunc) + self.radio[button] = true + + local prev = button + + for i=2,#buttons do + local entry = buttons[i] + local name = "CliqueRadioButton"..entry.type + local button = CreateFrame("CheckButton", name, CliqueCustomFrame, "UIRadioButtonTemplate") + button.type = entry.type + getglobal(name.."Text"):SetText(entry.name) + button:SetPoint("TOPLEFT", prev, "BOTTOMLEFT", 0, 0) + button:SetScript("OnClick", checkFunc) + self.radio[button] = true + prev = button + end + + -- Disable the click button + CliqueRadioButtonclick:Disable() + + -- Button to set the binding + + local button = CreateFrame("Button", "CliqueCustomButtonBinding", CliqueCustomFrame, "UIPanelButtonGrayTemplate") + button:SetHeight(30) + button:SetWidth(175) + button:SetText("Set Click Binding") + button:SetPoint("TOP", CliqueCustomHelpText, "BOTTOM", 40, -10) + button:SetScript("OnClick", function() Clique:CustomBinding_OnClick() end ) + button:RegisterForClicks("LeftButtonUp", "RightButtonUp", "MiddleButtonUp", "Button4Up", "Button5Up") + + -- Button for icon selection + + local button = CreateFrame("Button", "CliqueCustomButtonIcon", CliqueCustomFrame) + button.icon = button:CreateTexture(nil, "BORDER") + button.icon:SetAllPoints() + button.icon:SetTexture("Interface\\Icons\\Ability_Rogue_Sprint") + button:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square") + button:GetHighlightTexture():SetBlendMode("ADD") + button:SetHeight(30) + button:SetWidth(30) + button:SetPoint("RIGHT", CliqueCustomButtonBinding, "LEFT", -15, 0) + + local func = function() + GameTooltip:SetOwner(button, "ANCHOR_TOPLEFT") + GameTooltip:SetText("Click here to set icon") + GameTooltip:Show() + end + + button:SetScript("OnEnter", func) + button:SetScript("OnLeave", function() GameTooltip:Hide() end) + button:SetScript("OnClick", function() CliqueIconSelectFrame:Show() end) + + -- Create the editboxes for action arguments + + local edit = CreateFrame("EditBox", "CliqueCustomArg1", CliqueCustomFrame, "InputBoxTemplate") + edit:SetHeight(30) + edit:SetWidth(200) + edit:SetPoint("TOPRIGHT", CliqueCustomFrame, "TOPRIGHT", -10, -190) + edit:SetAutoFocus(nil) + edit:SetScript("OnTabPressed", function() + if CliqueCustomArg2:IsVisible() then + CliqueCustomArg2:SetFocus() + end + end) + + edit.label = edit:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + edit.label:SetText("Spell Name:") + edit.label:SetPoint("RIGHT", edit, "LEFT", -10, 0) + edit.label:SetJustifyH("RIGHT") + edit:Hide() + + -- Argument 2 + + local edit = CreateFrame("EditBox", "CliqueCustomArg2", CliqueCustomFrame, "InputBoxTemplate") + edit:SetHeight(30) + edit:SetWidth(200) + edit:SetPoint("TOPRIGHT", CliqueCustomArg1, "BOTTOMRIGHT", 0, 0) + edit:SetAutoFocus(nil) + edit:SetScript("OnTabPressed", function() + if CliqueCustomArg3:IsVisible() then + CliqueCustomArg3:SetFocus() + end + end) + + edit.label = edit:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + edit.label:SetText("Spell Name:") + edit.label:SetPoint("RIGHT", edit, "LEFT", -10, 0) + edit.label:SetJustifyH("RIGHT") + edit:Hide() + + -- Argument 3 + + local edit = CreateFrame("EditBox", "CliqueCustomArg3", CliqueCustomFrame, "InputBoxTemplate") + edit:SetHeight(30) + edit:SetWidth(200) + edit:SetPoint("TOPRIGHT", CliqueCustomArg2, "BOTTOMRIGHT", 0, 0) + edit:SetAutoFocus(nil) + edit:SetScript("OnTabPressed", function() + if CliqueCustomArg4:IsVisible() then + CliqueCustomArg4:SetFocus() + end + end) + + edit.label = edit:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + edit.label:SetText("Spell Name:") + edit.label:SetPoint("RIGHT", edit, "LEFT", -10, 0) + edit.label:SetJustifyH("RIGHT") + edit:Hide() + + -- Argument 4 + + local edit = CreateFrame("EditBox", "CliqueCustomArg4", CliqueCustomFrame, "InputBoxTemplate") + edit:SetHeight(30) + edit:SetWidth(200) + edit:SetPoint("TOPRIGHT", CliqueCustomArg3, "BOTTOMRIGHT", 0, 0) + edit:SetAutoFocus(nil) + edit:SetScript("OnTabPressed", function() + if CliqueCustomArg5:IsVisible() then + CliqueCustomArg5:SetFocus() + end + end) + + edit.label = edit:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + edit.label:SetText("Spell Name:") + edit.label:SetPoint("RIGHT", edit, "LEFT", -10, 0) + edit.label:SetJustifyH("RIGHT") + edit:Hide() + + -- Argument 5 + + local edit = CreateFrame("EditBox", "CliqueCustomArg5", CliqueCustomFrame, "InputBoxTemplate") + edit:SetHeight(30) + edit:SetWidth(200) + edit:SetPoint("TOPRIGHT", CliqueCustomArg4, "BOTTOMRIGHT", 0, 0) + edit:SetAutoFocus(nil) + edit:SetScript("OnTabPressed", function() + if CliqueCustomArg1:IsVisible() then + CliqueCustomArg1:SetFocus() + end + end) + + edit.label = edit:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + edit.label:SetText("Spell Name:") + edit.label:SetPoint("RIGHT", edit, "LEFT", -10, 0) + edit.label:SetJustifyH("RIGHT") + edit:Hide() + + -- Bottom buttons + + local button = CreateFrame("Button", "CliqueCustomButtonCancel", CliqueCustomFrame, "UIPanelButtonGrayTemplate") + button:SetHeight(24) + button:SetWidth(70) + button:SetText("Cancel") + button:SetPoint("BOTTOM", 65, 4) + button:SetScript("OnClick", buttonFunc) + + local button = CreateFrame("Button", "CliqueCustomButtonSave", CliqueCustomFrame, "UIPanelButtonGrayTemplate") + button:SetHeight(24) + button:SetWidth(70) + button:SetText("Save") + button:SetPoint("LEFT", CliqueCustomButtonCancel, "RIGHT", 6, 0) + button:SetScript("OnClick", buttonFunc) + + -- Create the macro icon frame + + CreateFrame("Frame", "CliqueIconSelectFrame", CliqueCustomFrame) + CliqueIconSelectFrame:SetWidth(296) + CliqueIconSelectFrame:SetHeight(250) + CliqueIconSelectFrame:SetPoint("CENTER",0,0) + self:SkinFrame(CliqueIconSelectFrame) + CliqueIconSelectFrame:SetFrameStrata("DIALOG") + CliqueIconSelectFrame.title:SetText("Select an icon") + CliqueIconSelectFrame:Hide() + + CreateFrame("CheckButton", "CliqueIcon1", CliqueIconSelectFrame, "CliqueIconTemplate") + CliqueIcon1:SetID(1) + CliqueIcon1:SetPoint("TOPLEFT", 25, -35) + + CreateFrame("CheckButton", "CliqueIcon2", CliqueIconSelectFrame, "CliqueIconTemplate") + CliqueIcon2:SetID(2) + CliqueIcon2:SetPoint("LEFT", CliqueIcon1, "RIGHT", 10, 0) + + CreateFrame("CheckButton", "CliqueIcon3", CliqueIconSelectFrame, "CliqueIconTemplate") + CliqueIcon3:SetID(3) + CliqueIcon3:SetPoint("LEFT", CliqueIcon2, "RIGHT", 10, 0) + + CreateFrame("CheckButton", "CliqueIcon4", CliqueIconSelectFrame, "CliqueIconTemplate") + CliqueIcon4:SetID(4) + CliqueIcon4:SetPoint("LEFT", CliqueIcon3, "RIGHT", 10, 0) + + CreateFrame("CheckButton", "CliqueIcon5", CliqueIconSelectFrame, "CliqueIconTemplate") + CliqueIcon5:SetID(5) + CliqueIcon5:SetPoint("LEFT", CliqueIcon4, "RIGHT", 10, 0) + + CreateFrame("CheckButton", "CliqueIcon6", CliqueIconSelectFrame, "CliqueIconTemplate") + CliqueIcon6:SetID(6) + CliqueIcon6:SetPoint("TOPLEFT", CliqueIcon1, "BOTTOMLEFT", 0, -10) + + CreateFrame("CheckButton", "CliqueIcon7", CliqueIconSelectFrame, "CliqueIconTemplate") + CliqueIcon7:SetID(7) + CliqueIcon7:SetPoint("LEFT", CliqueIcon6, "RIGHT", 10, 0) + + CreateFrame("CheckButton", "CliqueIcon8", CliqueIconSelectFrame, "CliqueIconTemplate") + CliqueIcon8:SetID(8) + CliqueIcon8:SetPoint("LEFT", CliqueIcon7, "RIGHT", 10, 0) + + CreateFrame("CheckButton", "CliqueIcon9", CliqueIconSelectFrame, "CliqueIconTemplate") + CliqueIcon9:SetID(9) + CliqueIcon9:SetPoint("LEFT", CliqueIcon8, "RIGHT", 10, 0) + + CreateFrame("CheckButton", "CliqueIcon10", CliqueIconSelectFrame, "CliqueIconTemplate") + CliqueIcon10:SetID(10) + CliqueIcon10:SetPoint("LEFT", CliqueIcon9, "RIGHT", 10, 0) + + CreateFrame("CheckButton", "CliqueIcon11", CliqueIconSelectFrame, "CliqueIconTemplate") + CliqueIcon11:SetID(11) + CliqueIcon11:SetPoint("TOPLEFT", CliqueIcon6, "BOTTOMLEFT", 0, -10) + + CreateFrame("CheckButton", "CliqueIcon12", CliqueIconSelectFrame, "CliqueIconTemplate") + CliqueIcon12:SetID(12) + CliqueIcon12:SetPoint("LEFT", CliqueIcon11, "RIGHT", 10, 0) + + CreateFrame("CheckButton", "CliqueIcon13", CliqueIconSelectFrame, "CliqueIconTemplate") + CliqueIcon13:SetID(13) + CliqueIcon13:SetPoint("LEFT", CliqueIcon12, "RIGHT", 10, 0) + + CreateFrame("CheckButton", "CliqueIcon14", CliqueIconSelectFrame, "CliqueIconTemplate") + CliqueIcon14:SetID(14) + CliqueIcon14:SetPoint("LEFT", CliqueIcon13, "RIGHT", 10, 0) + + CreateFrame("CheckButton", "CliqueIcon15", CliqueIconSelectFrame, "CliqueIconTemplate") + CliqueIcon15:SetID(15) + CliqueIcon15:SetPoint("LEFT", CliqueIcon14, "RIGHT", 10, 0) + + CreateFrame("CheckButton", "CliqueIcon16", CliqueIconSelectFrame, "CliqueIconTemplate") + CliqueIcon16:SetID(16) + CliqueIcon16:SetPoint("TOPLEFT", CliqueIcon11, "BOTTOMLEFT", 0, -10) + + CreateFrame("CheckButton", "CliqueIcon17", CliqueIconSelectFrame, "CliqueIconTemplate") + CliqueIcon17:SetID(17) + CliqueIcon17:SetPoint("LEFT", CliqueIcon16, "RIGHT", 10, 0) + + CreateFrame("CheckButton", "CliqueIcon18", CliqueIconSelectFrame, "CliqueIconTemplate") + CliqueIcon18:SetID(18) + CliqueIcon18:SetPoint("LEFT", CliqueIcon17, "RIGHT", 10, 0) + + CreateFrame("CheckButton", "CliqueIcon19", CliqueIconSelectFrame, "CliqueIconTemplate") + CliqueIcon19:SetID(19) + CliqueIcon19:SetPoint("LEFT", CliqueIcon18, "RIGHT", 10, 0) + + CreateFrame("CheckButton", "CliqueIcon20", CliqueIconSelectFrame, "CliqueIconTemplate") + CliqueIcon20:SetID(20) + CliqueIcon20:SetPoint("LEFT", CliqueIcon19, "RIGHT", 10, 0) + + CreateFrame("ScrollFrame", "CliqueIconScrollFrame", CliqueIconSelectFrame, "FauxScrollFrameTemplate") + CliqueIconScrollFrame:SetPoint("TOPLEFT", CliqueIcon1, "TOPLEFT", 0, 0) + CliqueIconScrollFrame:SetPoint("BOTTOMRIGHT", CliqueIcon20, "BOTTOMRIGHT", 10, 0) + + local texture = CliqueIconScrollFrame:CreateTexture(nil, "BACKGROUND") + texture:SetTexture("Interface\\ChatFrame\\ChatFrameBackground") + texture:SetPoint("TOPLEFT", CliqueIconScrollFrame, "TOPRIGHT", 14, 0) + texture:SetPoint("BOTTOMRIGHT", 23, 0) + texture:SetVertexColor(0.3, 0.3, 0.3) + + local texture = CliqueIconScrollFrame:CreateTexture(nil, "BACKGROUND") + texture:SetTexture("Interface\\ChatFrame\\ChatFrameBackground") + texture:SetPoint("TOPLEFT", CliqueIconScrollFrame, "TOPRIGHT", 4, 0) + texture:SetPoint("BOTTOMRIGHT", 14,0) + texture:SetVertexColor(0.3, 0.3, 0.3) + + CliqueIconScrollFrame:SetScript("OnVerticalScroll", function() + local MACRO_ICON_ROW_HEIGHT = 36 + FauxScrollFrame_OnVerticalScroll(MACRO_ICON_ROW_HEIGHT, function() Clique:UpdateIconFrame() end) + end) + + CliqueIconSelectFrame:SetScript("OnShow", function() Clique:UpdateIconFrame() end) + + -- Create the CliqueHelpText + CliqueFrame:CreateFontString("CliqueHelpText", "OVERLAY", "GameFontHighlight") + CliqueHelpText:SetText(L.HELP_TEXT) + CliqueHelpText:SetAllPoints() + CliqueHelpText:SetJustifyH("CENTER") + CliqueHelpText:SetJustifyV("CENTER") + CliqueHelpText:SetPoint("CENTER", 0, 0) + + self.sortList = {} + self.listSelected = 0 +end + +function Clique:ListScrollUpdate() + local idx,button + + Clique:SortList() + local clickCasts = self.sortList + local offset = FauxScrollFrame_GetOffset(CliqueListScroll) + FauxScrollFrame_Update(CliqueListScroll, table.getn(clickCasts), NUM_ENTRIES, ENTRY_SIZE) + + if not CliqueListScroll:IsShown() then + CliqueFrame:SetWidth(400) + else + CliqueFrame:SetWidth(425) + end + + for i=1,NUM_ENTRIES do + idx = offset + i + button = getglobal("CliqueList"..i) + if idx <= table.getn(clickCasts) then + Clique:FillListEntry(button,idx) + button:Show() + if idx == self.listSelected then + button:SetBackdropBorderColor(1,1,0) + else + button:SetBackdropBorderColor(0.3, 0.3, 0.3) + end + else + button:Hide() + end + end + Clique:ValidateButtons() +end + +local sortFunc = function(a,b) + local numA = a.button + local numB = b.button + + if numA == numB then + return a.modifier < b.modifier + else + return tostring(numA) < tostring(numB) + end +end + +function Clique:SortList() + self.sortList = {} + for k,v in pairs(self.editSet) do + table.insert(self.sortList, v) + end + table.sort(self.sortList, sortFunc) +end + +function Clique:ValidateButtons() + local entry = self.sortList[self.listSelected] + + if entry then + CliqueButtonDelete:Enable() + CliqueButtonEdit:Enable() + if entry.type == "spell" and entry.arg2 then + CliqueButtonMax:Enable() + else + CliqueButtonMax:Disable() + end + else + CliqueButtonDelete:Disable() + CliqueButtonEdit:Disable() + CliqueButtonMax:Disable() + end + + -- This should always be enabled + CliqueButtonCustom:Enable() + + -- Disable the help text + Clique.inuse = nil + for k,v in pairs(self.profile) do + if next(v) then + Clique.inuse = true + end + end + if Clique.inuse then + CliqueHelpText:Hide() + else + CliqueHelpText:Show() + end +end + +function Clique:FillListEntry(frame, idx) + local entry = self.sortList[idx] + local rank = string.format(" (Rank %d)", entry.rank or 0) + local type = string.format("%s%s", string.upper(string.sub(entry.type, 1, 1)), string.sub(entry.type, 2)) + local button = tonumber(string.sub(entry.button, -1, -1)) + + frame.icon:SetTexture(entry.texture or "Interface/Icons/Ability_Rogue_Sprint") + frame.binding:SetText(entry.modifier..self:GetButtonText(button)) + + if entry.type == "action" then + frame.name:SetText(string.format("Action Button %d", entry.arg1)) + elseif entry.type == "pet" then + frame.name:SetText(string.format("Pet Action %d", entry.arg1)) + elseif entry.type == "spell" then + frame.name:SetText(string.format(entry.arg2 and "%s (%s %d)" or "%s", entry.arg1, L.RANK, entry.arg2)) + elseif entry.type == "stop" then + frame.name:SetText("Stop Casting") + elseif entry.type == "target" then + frame.name:SetText("Target Unit") + elseif entry.type == "focus" then + frame.name:SetText("Set Focus Unit") + elseif entry.type == "assist" then + frame.name:SetText("Assist Unit") + end + + frame:Show() +end + +function Clique:ButtonOnClick(button) + local entry = self.sortList[self.listSelected] + local this = button or this + + if this == CliqueButtonDelete then + if InCombatLockdown() then + StaticPopup_Show("CLIQUE_COMBAT_LOCKDOWN") + return + end + + self.editSet[entry.modifier..entry.button] = nil + local len = table.getn(self.sortList) - 1 + + if self.listSelected > len then + self.listSelected = len + end + + self:DeleteAction(entry) + entry = nil + + self:ListScrollUpdate() + elseif this == CliqueButtonClose then + self:Toggle() + elseif this == CliqueButtonMax then + entry.arg2 = nil + self:DeleteAction(entry) + self:SetAction(entry) + elseif this == CliqueButtonCustom then + if CliqueCustomFrame:IsVisible() then + CliqueCustomFrame:Hide() + else + CliqueCustomFrame:Show() + end + elseif this == CliqueButtonEdit then + -- Make a copy of the entry + self.customEntry = {} + for k,v in pairs(entry) do + self.customEntry[k] = v + end + + CliqueCustomFrame:Show() + + -- Select the right radio button + for k,v in pairs(self.radio) do + if entry.type == k.type then + self:CustomRadio(k) + k:SetChecked(true) + end + end + + self.customEntry.type = entry.type + + CliqueCustomArg1:SetText(entry.arg1 or "") + CliqueCustomArg2:SetText(entry.arg2 or "") + CliqueCustomArg3:SetText(entry.arg3 or "") + CliqueCustomArg4:SetText(entry.arg4 or "") + CliqueCustomArg5:SetText(entry.arg5 or "") + + CliqueCustomButtonBinding.modifier = entry.modifier + CliqueCustomButtonBinding.button = self:GetButtonNumber(entry.button) + CliqueCustomButtonBinding:SetText(string.format("%s%s", entry.modifier, self:GetButtonText(entry.button))) + + self.editEntry = entry + + elseif this == CliqueCustomButtonCancel then + CliqueCustomFrame:Hide() + CliqueCustomButtonIcon.icon:SetTexture("Interface/Icons/Ability_Rogue_Sprint") + CliqueCustomButtonBinding:SetText("Set Click Binding") + self.customEntry = {} + self.editEntry = nil + self:CustomRadio() + + elseif this == CliqueCustomButtonSave then + -- Add custom save logic in here + local entry = self.customEntry + + entry.arg1 = CliqueCustomArg1:GetText() + entry.arg2 = CliqueCustomArg2:GetText() + entry.arg3 = CliqueCustomArg3:GetText() + entry.arg4 = CliqueCustomArg4:GetText() + entry.arg5 = CliqueCustomArg5:GetText() + + if entry.arg1 == "" then entry.arg1 = nil end + if entry.arg2 == "" then entry.arg2 = nil end + if entry.arg3 == "" then entry.arg3 = nil end + if entry.arg4 == "" then entry.arg4 = nil end + if entry.arg5 == "" then entry.arg5 = nil end + + if tonumber(entry.arg1) then entry.arg1 = tonumber(entry.arg1) end + if tonumber(entry.arg2) then entry.arg2 = tonumber(entry.arg2) end + if tonumber(entry.arg3) then entry.arg3 = tonumber(entry.arg3) end + if tonumber(entry.arg4) then entry.arg4 = tonumber(entry.arg4) end + if tonumber(entry.arg5) then entry.arg5 = tonumber(entry.arg5) end + + local pattern = "Hitem.+|h%[(.+)%]|h" + if entry.arg1 and string.find(entry.arg1, pattern) then + entry.arg1 = select(3, string.find(entry.arg1, pattern)) + end + if entry.arg2 and string.find(entry.arg2, pattern) then + entry.arg2 = select(3, string.find(entry.arg2, pattern)) + end + if entry.arg3 and string.find(entry.arg3, pattern) then + entry.arg3 = select(3, string.find(entry.arg3, pattern)) + end + if entry.arg4 and string.find(entry.arg4, pattern) then + entry.arg4 = select(3, string.find(entry.arg4, pattern)) + end + if entry.arg5 and string.find(entry.arg5, pattern) then + entry.arg5 = select(3, string.find(entry.arg5, pattern)) + end + + local issue + if not entry.type then + issue = "You must select an action type." + elseif not entry.button then + issue = "You must set a click-binding." + elseif entry.type == "action" and not entry.arg1 then + issue = "You must supply an action button number when creating a custom \"action\"." + elseif entry.type == "pet" and not entry.arg1 then + issue = "You must supply a pet action button number when creating a custom action \"pet\"." + elseif entry.type == "spell" and not (entry.arg1 or (entry.arg2 and entry.arg3) or entry.arg4) then + issue = "You must supply either a spell name and optionally an item slot/bag or name to consume when creating a \"spell\" action." + elseif entry.type == "item" and not ((entry.arg1 and entry.arg2) or entry.arg3) then + issue = "You must supply either a bag/slot, or an item name to use." + elseif entry.type == "menu" and not arg1 then + issue = "You must supply a menu function for action type \"menu\"." + end + + if issue then + StaticPopupDialogs["CLIQUE_CANT_SAVE"].text = issue + StaticPopup_Show("CLIQUE_CANT_SAVE") + return + end + + -- Delete the one we're editing, if that's the case + if self.editEntry then + local key = self.editEntry.modifier..self.editEntry.button + self.editSet[key] = nil + self:DeleteAction(self.editEntry) + self.editEntry = nil + end + + local key = entry.modifier..entry.button + self.editSet[key] = entry + self:SetAction(entry) + self:ButtonOnClick(CliqueCustomButtonCancel) + end + + Clique:ValidateButtons() + Clique:ListScrollUpdate() +end + +local click_func = function() Clique:DropDown_OnClick() end + +function Clique:DropDown_Initialize() + local info = {} + + for k,v in pairs(work) do + info = {} + info.text = v + info.value = Clique.profile[v] + info.func = click_func + UIDropDownMenu_AddButton(info) + end +end + +function Clique:DropDown_OnClick() + UIDropDownMenu_SetSelectedValue(CliqueDropDown, this.value) + Clique.editSet = this.value + self.listSelected = 0 + Clique:ListScrollUpdate() +end + +function Clique:DropDown_OnShow() + work = {} + for k,v in pairs(self.profile) do + table.insert(work, k) + end + table.sort(work) + + UIDropDownMenu_Initialize(this, function() Clique:DropDown_Initialize() end); + UIDropDownMenu_SetSelectedValue(CliqueDropDown, self.editSet) + Clique:ListScrollUpdate() +end + +-- Profile dropdown + +local work +local click_func = function() Clique:DropDownProfile_OnClick() end + +function Clique:DropDownProfile_Initialize() + local info = {} + + for k,v in ipairs(work) do + info = {} + info.text = string.sub(v, 1, 15) + + if #v > 15 then + info.text = info.text.."..." + end + + info.value = v + info.func = click_func + UIDropDownMenu_AddButton(info) + end + + info = { + text = "New profile", + value = -1, + func = click_func + } + UIDropDownMenu_AddButton(info) +end + +function Clique:DropDownProfile_OnClick() + if this.value == -1 then + StaticPopup_Show("CLIQUE_NEW_PROFILE") + return + end + + UIDropDownMenu_SetSelectedValue(CliqueDropDownProfile, this.value) + self:SetProfile(this.value) + self.listSelected = 0 + Clique:ListScrollUpdate() +end + +function Clique:DropDownProfile_OnShow() + work = {} + for k,v in pairs(self.db.profiles) do + table.insert(work, k) + end + table.sort(work) + + UIDropDownMenu_Initialize(this, function() Clique:DropDownProfile_Initialize() end); + UIDropDownMenu_SetSelectedValue(CliqueDropDownProfile, self.db.char.profileKey) + Clique:ListScrollUpdate() +end + + +function Clique:CustomBinding_OnClick() + -- This handles the binding click + local mod = self:GetModifierText() + local button = arg1 + + self.customEntry.modifier = mod + self.customEntry.button = self:GetButtonNumber(button) + this:SetText(string.format("%s%s", mod, button)) +end + +local buttonSetup = { + actionbar = { + help = "Change the actionbar. 'increment' will move it up one page, 'decrement' does the opposite. If you supply a number, the action bar will be turned to that page. You can specify 1,3 to toggle between pages 1 and 3", + arg1 = "Action:", + }, + action = { + help = "Simulate a click on an action button. Specify the number of the action button.", + arg1 = "Button Number:", + arg2 = "Unit:", + }, + pet = { + help = "Simulate a click on an pet's action button. Specify the number of the button.", + arg1 = "Pet Button Number:", + arg2 = "Unit:", + }, + spell = { + help = "Cast a spell from the spellbook. Takes a spell name, and optionally a bag and slot, or item name to use as the target of the spell (i.e. Feed Pet)", + arg1 = "Spell Name:", + arg2 = "Rank/Bag Number:", + arg3 = "Slot Number:", + arg4 = "Item Name:", + arg5 = "Unit:", + }, + item = { + help = "Use an item. Can take either a bag and slot, or an item name.", + arg1 = "Bag Number:", + arg2 = "Slot Number:", + arg3 = "Item Name:", + arg4 = "Unit:", + }, + macro = { + help = "Use a custom macro in a given index", + arg1 = "Macro Index:", + arg2 = "Macro Text:", + }, + stop = { + help = "Stops casting the current spell", + }, + target = { + help = "Targets the unit", + arg1 = "Unit:", + }, + focus = { + help = "Sets your \"focus\" unit", + arg1 = "Unit:", + }, + assist = { + help = "Assists the unit", + arg1 = "Unit:", + }, + click = { + help = "Simulate click on a button", + arg1 = "Button Name:", + }, +} + +function Clique:CustomRadio(button) + this = button or this + + local anySelected + for k,v in pairs(self.radio) do + if k ~= this then + k:SetChecked(nil) + end + end + + local entry = buttonSetup[this.type] + self.customEntry.type = this.type + + if this and this.type then + if not this:GetChecked() then + self.customEntry.type = nil + end + end + + if not entry then + CliqueCustomHelpText:SetText(L.CUSTOM_HELP) + CliqueCustomArg1:Hide() + CliqueCustomArg2:Hide() + CliqueCustomArg3:Hide() + CliqueCustomArg4:Hide() + CliqueCustomArg5:Hide() + CliqueCustomButtonBinding:SetText("Set Click Binding") + return + end + + -- Clear any open arguments + CliqueCustomArg1:SetText("") + CliqueCustomArg2:SetText("") + CliqueCustomArg3:SetText("") + CliqueCustomArg4:SetText("") + CliqueCustomArg5:SetText("") + + CliqueCustomHelpText:SetText(entry.help) + CliqueCustomArg1.label:SetText(entry.arg1) + CliqueCustomArg2.label:SetText(entry.arg2) + CliqueCustomArg3.label:SetText(entry.arg3) + CliqueCustomArg4.label:SetText(entry.arg4) + CliqueCustomArg5.label:SetText(entry.arg5) + + if entry.arg1 then CliqueCustomArg1:Show() else CliqueCustomArg1:Hide() end + if entry.arg2 then CliqueCustomArg2:Show() else CliqueCustomArg2:Hide() end + if entry.arg3 then CliqueCustomArg3:Show() else CliqueCustomArg3:Hide() end + if entry.arg4 then CliqueCustomArg4:Show() else CliqueCustomArg4:Hide() end + if entry.arg5 then CliqueCustomArg5:Show() else CliqueCustomArg5:Hide() end +end + +function Clique:UpdateIconFrame() + local MAX_MACROS = 18; + local NUM_MACRO_ICONS_SHOWN = 20; + local NUM_ICONS_PER_ROW = 5; + local NUM_ICON_ROWS = 4; + local MACRO_ICON_ROW_HEIGHT = 36; + local macroPopupOffset = FauxScrollFrame_GetOffset(CliqueIconScrollFrame); + local numMacroIcons = GetNumMacroIcons(); + + -- Icon list + for i=1, NUM_MACRO_ICONS_SHOWN do + macroPopupIcon = getglobal("CliqueIcon"..i.."Icon"); + macroPopupButton = getglobal("CliqueIcon"..i); + + if not macroPopupButton.icon then + macroPopupButton.icon = macroPopupIcon + end + + index = (macroPopupOffset * NUM_ICONS_PER_ROW) + i; + if ( index <= numMacroIcons ) then + macroPopupIcon:SetTexture(GetMacroIconInfo(index)); + macroPopupButton:Show(); + else + macroPopupIcon:SetTexture(""); + macroPopupButton:Hide(); + end + macroPopupButton:SetChecked(nil); + end + + FauxScrollFrame_Update(CliqueIconScrollFrame, ceil(numMacroIcons / NUM_ICONS_PER_ROW) , NUM_ICON_ROWS, MACRO_ICON_ROW_HEIGHT ); +end + +function Clique:SetSpellIcon() + local texture = this.icon:GetTexture() + self.customEntry.texture = texture + CliqueCustomButtonIcon.icon:SetTexture(texture) + CliqueIconSelectFrame:Hide() +end + +StaticPopupDialogs["CLIQUE_PASSIVE_SKILL"] = { + text = "You can't bind a passive skill.", +button1 = TEXT(OKAY), + OnAccept = function() + end, + timeout = 0, + hideOnEscape = 1 +} + +StaticPopupDialogs["CLIQUE_CANT_SAVE"] = { + text = "", + button1 = TEXT(OKAY), + OnAccept = function() + end, + timeout = 0, + hideOnEscape = 1 +} + +StaticPopupDialogs["CLIQUE_BINDING_PROBLEM"] = { + text = "That combination is already bound. Delete the old one before trying to re-bind.", + button1 = TEXT(OKAY), + OnAccept = function() + end, + timeout = 0, + hideOnEscape = 1 +} + +StaticPopupDialogs["CLIQUE_COMBAT_LOCKDOWN"] = { + text = "You are currently in combat. You cannot make changes to your click casting while in combat..", + button1 = TEXT(OKAY), + OnAccept = function() + end, + timeout = 0, + hideOnEscape = 1 +} + +StaticPopupDialogs["CLIQUE_NEW_PROFILE"] = { + text = TEXT("Enter the name of a new profile you'd like to create"), + button1 = TEXT(OKAY), + button2 = TEXT(CANCEL), + OnAccept = function() + Clique:SetProfile(getglobal(this:GetName().."EditBox"):GetText()) + end, + timeout = 0, + whileDead = 1, + exclusive = 1, + showAlert = 1, + hideOnEscape = 1, + hasEditBox = 1, + maxLetters = 32, + OnShow = function() + getglobal(this:GetName().."Button1"):Disable(); + getglobal(this:GetName().."EditBox"):SetFocus(); + end, + OnHide = function() + if ( ChatFrameEditBox:IsVisible() ) then + ChatFrameEditBox:SetFocus(); + end + getglobal(this:GetName().."EditBox"):SetText(""); + end, + EditBoxOnEnterPressed = function() + if ( getglobal(this:GetParent():GetName().."Button1"):IsEnabled() == 1 ) then + Clique:SetProfile(this:GetText()) + this:GetParent():Hide(); + end + end, + EditBoxOnTextChanged = function () + local editBox = getglobal(this:GetParent():GetName().."EditBox"); + local txt = editBox:GetText() + if #txt > 0 then + getglobal(this:GetParent():GetName().."Button1"):Enable(); + else + getglobal(this:GetParent():GetName().."Button1"):Disable(); + end + end, + EditBoxOnEscapePressed = function() + this:GetParent():Hide(); + ClearCursor(); + end +} diff --git a/CliqueUtils.lua b/CliqueUtils.lua new file mode 100644 index 0000000..59ba81e --- /dev/null +++ b/CliqueUtils.lua @@ -0,0 +1,47 @@ +local buttonMap = { + [1] = "LeftButton", + [2] = "RightButton", + [3] = "MiddleButton", + [4] = "Button4", + [5] = "Button5", + LeftButton = 1, + RightButton = 2, + MiddleButton = 3, + Button4 = 4, + Button5 = 5, +} + +function Clique:GetModifierText() + local modifier = "" + + if IsShiftKeyDown() then + modifier = "Shift-"..modifier + end + if IsControlKeyDown() then + modifier = "Ctrl-"..modifier + end + if IsAltKeyDown() then + modifier = "Alt-"..modifier + end + + return modifier +end + +function Clique:GetButtonNumber() + if not button then return "" end + return buttonMap[arg1] or "" +end + +function Clique:GetButtonText(num) + if not num then return "" end + num = tonumber(num) and tonumber(num) or num + return buttonMap[num] or "" +end + +function Clique:CheckBinding(key) + for k,v in pairs(self.editSet) do + if k == key then + return v + end + end +end \ No newline at end of file diff --git a/Localization.de.lua b/Localization.de.lua new file mode 100644 index 0000000..033b978 --- /dev/null +++ b/Localization.de.lua @@ -0,0 +1,23 @@ +--[[--------------------------------------------------------------------------------- + Localisation for deDE. Any commented lines need to be updated +----------------------------------------------------------------------------------]] + +local L = Clique.Locals + +if GetLocale() == "deDE" then + L.RANK = "Rang" + L.RANK_PATTERN = "Rang (%d+)" + L.CAST_FORMAT = "%s(Rang %d)" + +-- L.RACIAL_PASSIVE = "Racial Passive" + +-- L.CLICKSET_DEFAULT = "Default" +-- L.CLICKSET_HARMFUL = "Harmful actions" +-- L.CLICKSET_HELPFUL = "Helpful actions" +-- L.CLICKSET_OOC = "Out of Combat" + +-- L.BINDING_NOT_DEFINED = "Binding not defined" + +-- L.HELP_TEXT = "Welcome to Clique. For basic operation, you can navigate the spellbook and decide what spell you'd like to bind to a specific click. Then click on that spell with whatever click-binding you would like. For example, navigate to \"Flash Heal\" and shift-LeftClick on it to bind that spell to Shift-LeftClick." +-- L.CUSTOM_HELP = "This is the Clique custom edit screen. From here you can configure any of the combinations that the UI makes available to us in response to clicks. Select a base action from the left column. You can then click on the button below to set the binding you'd like, and then supply the arguments required (if any)." +end \ No newline at end of file diff --git a/Localization.en.lua b/Localization.en.lua new file mode 100644 index 0000000..91b0903 --- /dev/null +++ b/Localization.en.lua @@ -0,0 +1,23 @@ +--[[--------------------------------------------------------------------------------- + Localisation for English +----------------------------------------------------------------------------------]] + +local L = Clique.Locals + +-- This is the default locale. + L.RANK = "Rank" + L.RANK_PATTERN = "Rank (%d+)" + L.CAST_FORMAT = "%s(Rank %s)" + + L.RACIAL_PASSIVE = "Racial Passive" + L.PASSIVE = SPELL_PASSIVE + + L.CLICKSET_DEFAULT = "Default" + L.CLICKSET_HARMFUL = "Harmful actions" + L.CLICKSET_HELPFUL = "Helpful actions" + L.CLICKSET_OOC = "Out of Combat" + + L.BINDING_NOT_DEFINED = "Binding not defined" + + L.HELP_TEXT = "Welcome to Clique. For basic operation, you can navigate the spellbook and decide what spell you'd like to bind to a specific click. Then click on that spell with whatever click-binding you would like. For example, navigate to \"Flash Heal\" and shift-LeftClick on it to bind that spell to Shift-LeftClick." + L.CUSTOM_HELP = "This is the Clique custom edit screen. From here you can configure any of the combinations that the UI makes available to us in response to clicks. Select a base action from the left column. You can then click on the button below to set the binding you'd like, and then supply the arguments required (if any)." diff --git a/Localization.fr.lua b/Localization.fr.lua new file mode 100644 index 0000000..3b94726 --- /dev/null +++ b/Localization.fr.lua @@ -0,0 +1,23 @@ +--[[--------------------------------------------------------------------------------- + Localisation for frFR. Any commented lines need to be updated +----------------------------------------------------------------------------------]] + +local L = Clique.Locals + +if GetLocale() == "deDE" then + L.RANK = "Rang" + L.RANK_PATTERN = "Rang (%d+)" + L.CAST_FORMAT = "%s(Rang %d)" + +-- L.RACIAL_PASSIVE = "Racial Passive" + +-- L.CLICKSET_DEFAULT = "Default" +-- L.CLICKSET_HARMFUL = "Harmful actions" +-- L.CLICKSET_HELPFUL = "Helpful actions" +-- L.CLICKSET_OOC = "Out of Combat" + +-- L.BINDING_NOT_DEFINED = "Binding not defined" + +-- L.HELP_TEXT = "Welcome to Clique. For basic operation, you can navigate the spellbook and decide what spell you'd like to bind to a specific click. Then click on that spell with whatever click-binding you would like. For example, navigate to \"Flash Heal\" and shift-LeftClick on it to bind that spell to Shift-LeftClick." +-- L.CUSTOM_HELP = "This is the Clique custom edit screen. From here you can configure any of the combinations that the UI makes available to us in response to clicks. Select a base action from the left column. You can then click on the button below to set the binding you'd like, and then supply the arguments required (if any)." +end diff --git a/Localization.kr.lua b/Localization.kr.lua new file mode 100644 index 0000000..e8b63ec --- /dev/null +++ b/Localization.kr.lua @@ -0,0 +1,23 @@ +--[[--------------------------------------------------------------------------------- + Localisation for koKR. Any commented lines need to be updated +----------------------------------------------------------------------------------]] + +local L = Clique.Locals + +if GetLocale() == "koKR" then + L.RANK = "레벨" + L.RANK_PATTERN = "(%d+) 레벨" + L.CAST_FORMAT = "%s(%d 레벨)" + +-- L.RACIAL_PASSIVE = "Racial Passive" + +-- L.CLICKSET_DEFAULT = "Default" +-- L.CLICKSET_HARMFUL = "Harmful actions" +-- L.CLICKSET_HELPFUL = "Helpful actions" +-- L.CLICKSET_OOC = "Out of Combat" + +-- L.BINDING_NOT_DEFINED = "Binding not defined" + +-- L.HELP_TEXT = "Welcome to Clique. For basic operation, you can navigate the spellbook and decide what spell you'd like to bind to a specific click. Then click on that spell with whatever click-binding you would like. For example, navigate to \"Flash Heal\" and shift-LeftClick on it to bind that spell to Shift-LeftClick." +-- L.CUSTOM_HELP = "This is the Clique custom edit screen. From here you can configure any of the combinations that the UI makes available to us in response to clicks. Select a base action from the left column. You can then click on the button below to set the binding you'd like, and then supply the arguments required (if any)." +end diff --git a/Localization.zh.lua b/Localization.zh.lua new file mode 100644 index 0000000..0127f81 --- /dev/null +++ b/Localization.zh.lua @@ -0,0 +1,23 @@ +--[[--------------------------------------------------------------------------------- + Localisation for zhCN. Any commented lines need to be updated +----------------------------------------------------------------------------------]] + +local L = Clique.Locals + +if GetLocale() == "zhCN" then + L.RANK = "等级" + L.RANK_PATTERN = "等级 (%d+)" + L.CAST_FORMAT = "%s(等级 %d)" + +-- L.RACIAL_PASSIVE = "Racial Passive" + +-- L.CLICKSET_DEFAULT = "Default" +-- L.CLICKSET_HARMFUL = "Harmful actions" +-- L.CLICKSET_HELPFUL = "Helpful actions" +-- L.CLICKSET_OOC = "Out of Combat" + +-- L.BINDING_NOT_DEFINED = "Binding not defined" + +-- L.HELP_TEXT = "Welcome to Clique. For basic operation, you can navigate the spellbook and decide what spell you'd like to bind to a specific click. Then click on that spell with whatever click-binding you would like. For example, navigate to \"Flash Heal\" and shift-LeftClick on it to bind that spell to Shift-LeftClick." +-- L.CUSTOM_HELP = "This is the Clique custom edit screen. From here you can configure any of the combinations that the UI makes available to us in response to clicks. Select a base action from the left column. You can then click on the button below to set the binding you'd like, and then supply the arguments required (if any)." +end diff --git a/images/CliqueIcon.tga b/images/CliqueIcon.tga new file mode 100644 index 0000000..0219f56 Binary files /dev/null and b/images/CliqueIcon.tga differ diff --git a/images/backdrop.tga b/images/backdrop.tga new file mode 100644 index 0000000..f061cda Binary files /dev/null and b/images/backdrop.tga differ diff --git a/images/borders.tga b/images/borders.tga new file mode 100644 index 0000000..42f9e27 Binary files /dev/null and b/images/borders.tga differ diff --git a/images/footCorner.tga b/images/footCorner.tga new file mode 100644 index 0000000..3780e58 Binary files /dev/null and b/images/footCorner.tga differ diff --git a/images/footer.tga b/images/footer.tga new file mode 100644 index 0000000..0983828 Binary files /dev/null and b/images/footer.tga differ diff --git a/images/headCorner.tga b/images/headCorner.tga new file mode 100644 index 0000000..83b28fc Binary files /dev/null and b/images/headCorner.tga differ diff --git a/images/header.tga b/images/header.tga new file mode 100644 index 0000000..7266823 Binary files /dev/null and b/images/header.tga differ