Thread Tools Display Modes
09-12-12, 04:08 PM   #1
Haleth
This Space For Rent
 
Haleth's Avatar
Featured
Join Date: Sep 2008
Posts: 1,173
Updating ArtPad

Hello.

A guildie asked me if I could update ArtPad. The addon still works, but the communication part doesn't. It's supposed to show your drawings to party and raid members. If the receiving party has the 'adminonly' (/ap adminonly) option enabled, they will only receive drawings from party/raid leaders.

I started debugging it and other than one obvious change (GetNumRaidMembers() -> GetNumGroupMembers(), which is not even needed if the adminonly mode is set to false) the only problem seems to be that the addon messages sent out are not received by others; CHAT_MSG_ADDON does not fire. They are recieved by the sender himself though (easily shown using event trace and test prints).

This is the code:

Code:
--[[
--
--	ArtPad
--	by Dust of Turalyon
--
--	Naming Convention:
--	- Methods are first letter upper case, camel case
--	- Member variables are first letter lower case
--	- Static handlers start with "On".
--
--]]

--[[ Protocol ]]
-- d(<x>,<y>,<a>,<b>)	-- Draw a line from (x,y) to (a,b)
-- c(<x>,<y>)		-- Clear a point at (x,y)
-- c(<x>,<y>,<a>,<b>)	-- Clear a line from (x,y) to (a,b)
-- c()			-- Clear Canavas
-- f(<r>,<g>,<b>,<a>)	-- Change to given color
-- t(<x>,<y>,"<t>")	-- Draw text t with bottom left corner at (x,y)

ArtPad =
{
-- [[ Version data from the TOC file ]]
version = GetAddOnMetadata("ArtPad", "Version");
saveVersion = GetAddOnMetadata("ArtPad", "X-SaveVersion");
protocolVersion = GetAddOnMetadata("ArtPad", "X-ProtocolVersion");

-- [[ Event Handling ]]
events = {
	["VARIABLES_LOADED"] =
		function (this)
			local ArtPad_Settings_Default = {
				["SaveVersion"]	= this.saveVersion;
				["AdminOnly"]	= true; -- Ignore non-raid admins
				["WarnClear"]	= true; -- Warn before clearing screen
			};
			if not ArtPad_Settings then
				ArtPad_Settings = ArtPad_Settings_Default;
			elseif ArtPad_Settings["SaveVersion"] < this.saveVersion then
				ArtPad_Settings = ArtPad_Settings_Default;
			end;
		end;
	["PLAYER_LOGIN"] =
		function (this)
		end;
	["PLAYER_REGEN_DISABLED"] =
		function (this)
			-- Close window when entering combat
			if this.mainFrame:IsShown() then
				this.mainFrame:Hide();
			end;
		end;
	["PLAYER_REGEN_ENABLED"] =
		function (this)
		end;
	["CHAT_MSG_ADDON"] =
		function (this, prefix, message, disType, sender)
			if prefix == "ArtPad" and sender ~= UnitName("player") then
				if not this:ValidateSender(sender) then
					return;
				end;

				local x,y,a,b = string.match(message, "d%((%d+),(%d+),(%d+),(%d+)%)");
				if x then
					this:DrawLine(x,y,a,b);
					return;
				end;
				local x,y = string.match(message, "c%((%d+),(%d+)%)");
				if x then
					this:ClearLine(x,y);
					return;
				end;

				local x,y,a,b = string.match(message, "c%((%d+),(%d+),(%d+),(%d+)%)");
				if x then
					this:ClearLine(x,y,a,b);
					return;
				end;

				local r,g,b,a = string.match(message, "f%((%d%.?%d*),(%d%.?%d*),(%d%.?%d*),(%d%.?%d*)%)");
				if r then
					this:SetColor(r,g,b,a);
					return;
				end;

				local x,y,t = string.match(message, "t%((%d+),(%d+),\"([^\"]+)\"%)");
				if x then
					this:CreateText(x,y,t);
					return;
				end;

				local a, b = string.find(message, "c%(%)");
				if a then
					this:ClearCanavas();
					return;
				end;
			end;
		end;
};

-- [[ Event Management ]]
RegisterEvents = function (this, eventList)
	for event, handler in pairs(eventList) do
		this.eventFrame:RegisterEvent(event);
	end
end;

UnregisterEvents = function (this, eventList)
	for event, handler in pairs(eventList) do
		this.eventFrame:UnregisterEvent(event);
	end
end;

-- [[ Button Handling ]]
buttons = {
	["Close"] =
		function (frame, button, down)
			local this = frame.pad; -- Static Method
			this.mainFrame:Hide();
		end;
	["Clear"] =
		function (frame, button, down)
			local this = frame.pad; -- Static Method
			this:ClearCanavas();
			this:SendClear();
		end;
	["Text"] =
		function (frame, button, down)
			local this = frame.pad; -- Static Method
			if this.state == "SLEEP" then
				this.textInput:SetText("");
				this.textInput:Show();
			end;
		end;
	["ColorWhite"] =
		function (frame, button, down)
			local this = frame.pad; -- Static Method
			this:SetColor(1,1,1,0.75);
			this:SendColor(1,1,1,0.75);
		end;
	["ColorGrey"] =
		function (frame, button, down)
			local this = frame.pad; -- Static Method
			this:SetColor(0.5,0.5,0.5,0.75);
			this:SendColor(0.5,0.5,0.5,0.75);
		end;
	["ColorRed"] =
		function (frame, button, down)
			local this = frame.pad; -- Static Method
			this:SetColor(1,0,0,0.75);
			this:SendColor(1,0,0,0.75);
		end;
	["ColorGreen"] =
		function (frame, button, down)
			local this = frame.pad; -- Static Method
			this:SetColor(0,1,0,0.75);
			this:SendColor(0,1,0,0.75);
		end;
	["ColorBlue"] =
		function (frame, button, down)
			local this = frame.pad; -- Static Method
			this:SetColor(0,0,1,0.75);
			this:SendColor(0,0,1,0.75);
		end;
};

shortcuts = {
	["Close"] = "ESCAPE";
	["Clear"] = "C";
	["Text"] = "T";
	["ColorWhite"] = "1";
	["ColorGrey"] = "2";
	["ColorRed"] = "3";
	["ColorGreen"] = "4";
	["ColorBlue"] = "5";
};


-- [[ Load Event Handling ]]
OnLoad = function (this)
	--Slash command
	SlashCmdList["ARTPAD"] = this.OnSlashCommand;
	SLASH_ARTPAD1 = "/artpad";
	SLASH_ARTPAD2 = "/ap";

	this.mainFrame:SetScript("OnEnter", this.OnEnter);
	this.mainFrame:SetScript("OnLeave", this.OnLeave);

	--this.mainFrame:EnableKeyboard(true);
	--this.mainFrame:SetScript("OnKeyDown", this.OnKeyDown);
	--this.mainFrame:SetScript("OnKeyUp", this.OnKeyUp);

	this.mainFrame:EnableMouse(true);
	this.mainFrame:SetScript("OnMouseDown", this.OnMouseDown);
	this.mainFrame:SetScript("OnMouseUp", this.OnMouseUp);

	this.mainFrame:SetScript("OnShow", this.OnShow);
	this.mainFrame:SetScript("OnHide", this.OnHide);

	this.textInput:SetScript("OnEnterPressed", this.OnTextEnter);
	this.textInput:SetScript("OnEscapePressed", this.OnTextEscape);

	this.eventFrame:SetScript("OnEvent", this.OnEvent);
	this:RegisterEvents(this.events);

	-- NOT REENTRANT!
	this.OnLoad = nil;
end;

-- [[ Frame Event Handling ]]
OnEvent = function (frame, event, ...)
	local this = frame.pad; -- Static Method

	if this.events[event] then
		this.events[event](this, ...);
	else
		this:Message("ArtPad Error: Unknown Event");
	end;
end;

-- [[ Keyboard Event Handling ]]
OnKeyDown = function (frame, key)
	local this = frame.pad; -- Static Method
end;

OnKeyUp = function (frame, key)
	local this = frame.pad; -- Static Method
	if (key == "ESCAPE") then
		frame:Hide();
	end;
end;

-- [[ Mouse Event Handling ]]
state = "SLEEP";

OnMouseDown = function (frame, button)
	local this = frame.pad; -- Static Method
	if this.FrameMouseDown(frame) then
		this.state = "FRAME";
	elseif this.state == "SLEEP" then
		if button == "LeftButton" then
			this.state = "PAINT";
		else
			this.state = "CLEAR";
		end;
	elseif this.state == "TEXT" then
		this:CreateText(this.lastX, this.lastY,
			this.textInput:GetText());
		this:SendText(this.lastX, this.lastY,
			this.textInput:GetText());
		this.state = "SLEEP";
	end;
end;

OnMouseUp = function (frame, button)
	local this = frame.pad; -- Static Method
	this.FrameMouseUp(frame);
	this.state = "SLEEP";
end;

-- [[ Override Handling ]]
OnShow = function (frame)
	local this = frame.pad; -- Static Method
	-- Set Override
	for b, k in pairs(this.shortcuts) do
		SetOverrideBindingClick(this.mainFrame, true, k, "ArtPad_MainFrame_"..b);
	end;
end;

OnHide = function (frame)
	local this = frame.pad; -- Static Method
	-- Clear Override
	ClearOverrideBindings(this.mainFrame);
end;

-- [[ Tracking Functions ]]
OnEnter = function (frame, motion)
	local this = frame.pad; -- Static Method
	this.mainFrame:SetScript("OnUpdate", this.OnUpdate);
end;

OnLeave = function (frame, motion)
	local this = frame.pad; -- Static Method
	this.mainFrame:SetScript("OnUpdate", nil);
	this.state = "SLEEP";
	this.lastX = nil;
	this.lastY = nil;

end;

mouseX = -1;
mouseY = -1;
OnUpdate = function (frame, elapsed)
	local this = frame.pad; -- Static Method
	local mx, my = GetCursorPosition();
	if mx == this.mouseX and my == this.mouseY then
		return;
	else
		this.mouseX = mx;
		this.mouseY = my;
	end;
	local x, y;		-- Local coordinates
	local scale = this.mainFrame:GetScale()*UIParent:GetScale();

	mx = mx/scale;
	my = my/scale;
	x = math.floor(mx - this.mainFrame:GetLeft());
	y = math.floor(my - this.mainFrame:GetBottom());

	if this.state ~= "SLEEP" then
		this:HandleMove(x, y, this.lastX, this.lastY);
	end;

	this.lastX = x;
	this.lastY = y;
end;

HandleMove = function (this, ...)
	if this.state == "PAINT" then
		this:DrawLine(...);
		this:SendLine(...);
	elseif this.state == "CLEAR" then
		this:ClearLine(...);
		this:SendClear(...);
	end;
end;

OnTextEnter = function (frame)
	local this = frame.pad; -- Static Method
	this.state = "TEXT";
	frame:Hide();
end;

OnTextEscape = function (frame)
	local this = frame.pad; -- Static Method
	frame:Hide();
end;

-- [[ Authorisation ]]
ValidateSender = function (this, sender)
	if ArtPad_Settings["AdminOnly"] then
		-- Check if sender is a raid admin
		local maxNum = GetNumRaidMembers();
		local authorized = false;
		if (maxNum > 0) then
			for i=1,maxNum do
				local name, rank = GetRaidRosterInfo(i);
				if name == sender then
					authorized = rank > 0;
				end;
			end;
		end;
		return authorized;
	else
		-- No check needed, all are allowed
		return true;
	end;
end;

slashCommands = {
	["show"] =
		function (this)
			this.mainFrame:Show();
		end;
	["hide"] =
		function (this)
			this.mainFrame:Hide();
		end;
	["toggle"] =
		function (this)
			if this.mainFrame:IsShown() then
				this.mainFrame:Hide();
			else
				this.mainFrame:Show();
			end;
		end;
	["clear"] =
		function (this)
			this:ClearCanavas();
		end;
	["adminonly"] =
		function (this, state)
			-- TODO: Generalize
			-- Set
			if state == "off" or state == "false" then
				ArtPad_Settings["AdminOnly"] = false;
			elseif state == "on" or state == "true" then
				ArtPad_Settings["AdminOnly"] = true;
			else -- Toggle
				if ArtPad_Settings["AdminOnly"] then
					ArtPad_Settings["AdminOnly"] = false;
				else
					ArtPad_Settings["AdminOnly"] = true;
				end;
			end;
			if ArtPad_Settings["AdminOnly"] then
				this:Message("ArtPad: AdminOnly enabled");
			else
				this:Message("ArtPad: AdminOnly disabled");
			end;
		end;
};

OnSlashCommand = function (msg)
	local this = ArtPad; -- Static Method
	local cmd, arg = string.match(msg, "^(%a*)%s*(.*)$");
	if cmd then
		cmd = string.lower(cmd);
		if this.slashCommands[cmd] then
			this.slashCommands[cmd](this, arg);
		else
			this:Message("ArtPad:")
			this:Message("/ap [show | hide | toggle | clear]")
			this:Message("/ap [adminonly]")
		end;
	end;
end;

-- [[ Misc ]]
Message = function (this, msg)
	DEFAULT_CHAT_FRAME:AddMessage(msg);
end;

-- [[ Frame Setup and handling ]]
mainFrameWidth = 800;
mainFrameHeight = 600;
mainFrameScale = 1;

mainFrame = nil;	-- For input/output
eventFrame = nil;	-- For event processing

textInput = nil;

brushColorSample = nil;

CreateFrames = function (this)
	local frameM = CreateFrame("Frame", nil, UIParent);
	local frameE = CreateFrame("Frame", nil, UIParent);
	this.mainFrame = frameM;
	this.mainFrame.pad = this;
	this.eventFrame = frameE;
	this.eventFrame.pad = this;

	frameM:SetFrameStrata("DIALOG");
	frameM:SetWidth(this.mainFrameWidth);
	frameM:SetHeight(this.mainFrameHeight);
	frameM:SetScale(this.mainFrameScale);
	frameM:SetPoint("CENTER", 0, 0);
	frameM:SetMovable(true);
	frameM:SetClampedToScreen(true);
	frameM:Hide();

	local frameT = CreateFrame("EditBox", nil, frameM);
	this.textInput = frameT;
	this.textInput.pad = this;

	frameT:SetPoint("BOTTOMLEFT", frameM, "BOTTOMLEFT", 5, 5);
	frameT:SetPoint("TOPRIGHT", frameM, "BOTTOMLEFT", 205, 25);
	frameT:SetFont("Fonts\\FRIZQT__.TTF",12);
	frameT:Hide();

	local t = frameM:CreateTexture(nil, "BACKGROUND");
	t:SetTexture(0,0,0,0.5);
	t:SetAllPoints(frameM);

	local b = frameM:CreateTexture(nil, "ARTWORK");
	b:SetPoint("TOPRIGHT", frameM, "TOPRIGHT", -10, -10);
	b:SetWidth(10); b:SetHeight(10);
	b:SetTexture(1,1,1,1);
	this.brushColorSample = b;

	local a = frameM:CreateFontString(nil, "ARTWORK");
	a:SetPoint("TOPLEFT", frameM, "TOPLEFT", 10, -10);
	a:SetTextColor(0.5, 0.5, 0.5, 0.5);
	a:SetFont("Fonts\\FRIZQT__.TTF",16);
	a:SetJustifyH("LEFT")
	a:SetText("ArtPad v."..this.version);
	local h = frameM:CreateFontString(nil, "ARTWORK");
	h:SetPoint("TOPLEFT", frameM, "TOPLEFT", 10, -30);
	h:SetTextColor(0.5, 0.5, 0.5, 0.5);
	h:SetFont("Fonts\\FRIZQT__.TTF",12);
	h:SetJustifyH("LEFT")
	local hs = "";
	for b, s in pairs(this.shortcuts) do
		hs = hs .. "> " .. b .. ": ".. s .. "\n";
	end;
	h:SetText(hs);

	-- Buttons (NOT REENTRANT!)
	for b, f in pairs(this.buttons) do
		local button = CreateFrame("Button", "ArtPad_MainFrame_"..b, frameM);
		button:SetScript("OnClick", f);
		button.pad = this;
	end

	this.CreateFrames = nil;
end;

FrameMouseDown = function (frame)
	if (IsShiftKeyDown()) then
		frame:StartMoving();
		return true;
--	elseif (IsAltKeyDown()) then
--		local w = frame:GetWidth();
--		local h = frame:GetHeight();
--		local x, y = frame:GetCenter();
--		local mx, my = GetCursorPosition();
--		local scaleL, scaleW;
--		scaleL = frame:GetScale();
--		scaleW = UIParent:GetScale();
--		mx = mx/scaleW;
--		my = my/scaleW;
--		x = x*scaleL;
--		y = y*scaleL
--		x = mx - x;
--		y = my - y;
--		x = x/w*h;
--		if (abs(x) > abs(y)) then
--			if (x > 0) then
--				frame:StartSizing("RIGHT");
--			else
--				frame:StartSizing("LEFT");
--			end;
--		else
--			if (y > 0) then
--				frame:StartSizing("TOP");
--			else
--				frame:StartSizing("BOTTOM");
--			end;
--		end;
--		return true;
	end;
	return false;
end;

FrameMouseUp = function (frame)
	frame:StopMovingOrSizing();
end;

-- [[ Drawing ]]

brushColor = { r = 1.0; g = 1.0; b = 1.0; a = 0.75; };

mainLines = {};
junkLines = {};
mainTexts = {};
junkTexts = {};

SendLine = function (this, x, y, oldX, oldY)
	if oldY and oldY then
		SendAddonMessage("ArtPad", "d("..x..","..y..","..oldX..","..oldY..")", "RAID");
	else
		--SendAddonMessage("ArtPad", "d("..x..","..y..")", "RAID");
	end;
end;

SendClear = function (this, x, y, oldX, oldY)
	if oldY and oldY then
		SendAddonMessage("ArtPad", "c("..x..","..y..","..oldX..","..oldY..")", "RAID");
	elseif x and y then
		SendAddonMessage("ArtPad", "c("..x..","..y..")", "RAID");
	else
		SendAddonMessage("ArtPad", "c()", "RAID");
	end;
end;

SendColor = function (this, r, g, b, a)
	SendAddonMessage("ArtPad", "f("..r..","..g..","..b..","..a..")", "RAID");
end;

SendText = function (this, x, y, text)
	SendAddonMessage("ArtPad", "t("..x..","..y..",\""..text.."\")", "RAID");
end;

DrawLine = function (this, x, y, oldX, oldY)
	if oldX and oldY then
		this:CreateLine(x,y, oldX, oldY);
	else
		--this:CreateLine(x,y);
	end;
end;

ClearLine = function (this, x, y, oldX, oldY)
	for i = #this.mainLines, 1, -1 do
		local px = this.mainLines[i]["lax"];
		local py = this.mainLines[i]["lay"];
		local qx = this.mainLines[i]["lbx"];
		local qy = this.mainLines[i]["lby"];
		-- TODO: Don't only check for intersections, but also min distance
		-- http://www.softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm
		if this:LineLineIntersect(x,y,oldX,oldY,px,py,qx,qy) then
			this:JunkLine(i);
		end;
	end;
	for i = #this.mainTexts, 1, -1 do
		local px = this.mainTexts[i]["lax"];
		local py = this.mainTexts[i]["lay"];
		local qx = this.mainTexts[i]["lbx"];
		local qy = this.mainTexts[i]["lby"];
		if this:LineLineIntersect(x,y,oldX,oldY,px,py,qx,qy) then
			this:JunkText(i);
		end;
	end;
end;

PointPointDist = function (this, px, py, qx, qy)
	return math.sqrt(math.pow(px-qx,2) + math.pow(py-qy,2));
end;

LinePointDist = function (this, lax, lay, lbx, lby, px, py)
	-- http://www.softsurfer.com/Archive/algorithm_0102/algorithm_0102.htm
	-- Note: Not working
	return math.abs((lay-lby)*px+(lbx-lax)*py+(lax*lby-lbx*lay)/
		math.sqrt(math.pow(lbx-lax,2)+math.pow(lby-lay,2)));
end;

LineLineIntersect = function (this, ax0, ay0, ax1, ay1, bx0, by0, bx1, by1)
	--http://www.softsurfer.com/Archive/algorithm_0104/algorithm_0104B.htm#intersect2D_SegSeg()
	local ux, uy = ax1-ax0, ay1-ay0;
	local vx, vy = bx1-bx0, by1-by0;
	local wx, wy = ax0-bx0, ay0-by0;
	local D = ux*vy - uy*vx;

	if (D == 0) then
		-- Parallel
		return false;
	else
		local sI = (vx*wy-vy*wx) / D;
		if (sI < 0 or sI > 1) then -- no intersect with S1
			return false;
		end;

		local tI = (ux*wy-uy*wx) / D;
		if (tI < 0 or tI > 1) then -- no intersect with S2
			return false;
		end;

		return true;
	end;
end;

-- A square brush
ClearCanavas = function (this)
	if ArtPad_Settings["WarnClear"] then
		-- TODO: Ask for permission to clear
	end;
	for i = #this.mainLines, 1, -1 do
		this:JunkLine(i);
	end;
	for i = #this.mainTexts, 1, -1 do
		this:JunkText(i);
	end;
end;

SetColor = function (this, r, g, b, a)
	this.brushColor.r = r;
	this.brushColor.g = g;
	this.brushColor.b = b;
	this.brushColor.a = a;
	this.brushColorSample:SetTexture(r,g,b,a);
end;

SetTexColor = function (this, tex)
	tex:SetVertexColor(this.brushColor.r,
		this.brushColor.g,
		this.brushColor.b,
		this.brushColor.a);
end;

-- [[ Line Handling ]]
-- Allocator
CreateLine = function (this, x, y, a, b)
	local ix = math.floor(x);
	local iy = math.floor(y);
	local ia = math.floor(a);
	local ib = math.floor(b);

	local cx, cy = (ix + ia)/2, (iy + ib)/2;
	local dx, dy = ix-ia, iy-ib;
	local dmax = math.max(math.abs(dx),math.abs(dy));
	local dr = math.sqrt(dx*dx + dy*dy);
	local scale = 1/dmax*32;
	local sinA, cosA = dy/dr*scale, dx/dr*scale;
	if dr == 0 then
		return nil;
	end

	local pix;
	if #(this.junkLines) > 0 then
		pix = table.remove(this.junkLines); -- Recycling ftw!
	else
		pix = this.mainFrame:CreateTexture(nil, "OVERLAY");
		pix:SetTexture("Interface\\AddOns\\ArtPad\\line.tga");
	end;
	this:SetTexColor(pix);
	pix:ClearAllPoints();

	pix:SetPoint("CENTER", this.mainFrame, "BOTTOMLEFT", cx, cy);
	pix:SetWidth(dmax); pix:SetHeight(dmax);
	pix:SetTexCoord(this.GetCoordsForTransform(
		cosA, sinA, -(cosA+sinA)/2+0.5,
		-sinA, cosA, -(-sinA+cosA)/2+0.5));
	pix:Show();
	pix["lax"] = ix;
	pix["lay"] = iy;
	pix["lbx"] = ia;
	pix["lby"] = ib;

	table.insert(this.mainLines, pix);

	return pix, #this.mainLines;
end;

-- Deallocator
JunkLine = function (this, id)
	if this.mainLines[id] then
		local pix = table.remove(this.mainLines, id);
		if pix then
			table.insert(this.junkLines, pix);
			pix:Hide();
		end;
	end;
end;

-- [[ Text Handling ]]
CreateText = function (this, x, y, text)
	local ix = math.floor(x);
	local iy = math.floor(y);

	if #(this.junkTexts) > 0 then
		tex = table.remove(this.junkTexts); -- Recycling ftw!
	else
		tex = this.mainFrame:CreateFontString(nil, "OVERLAY");
	end;
	tex:SetFont("Fonts\\FRIZQT__.TTF",12);
	tex:SetJustifyH("LEFT");
	tex:SetPoint("BOTTOMLEFT", this.mainFrame, "BOTTOMLEFT", ix, iy);
	tex:SetTextColor(this.brushColor.r, this.brushColor.g,
		this.brushColor.b, this.brushColor.a);

	tex:SetText(text);
	tex:Show();
	tex["lax"] = ix;
	tex["lay"] = iy;
	tex["lbx"] = ix + tex:GetWidth();
	tex["lby"] = iy + tex:GetHeight();

	table.insert(this.mainTexts, tex);

	return tex, #this.mainTexts;
end;

JunkText = function (this, id)
	if this.mainTexts[id] then
		local tex = table.remove(this.mainTexts, id);
		if tex then
			table.insert(this.junkTexts, tex);
			tex:Hide();
		end;
	end;
end;

-- [[ Projection ]]
GetCoordsForTransform = function(A, B, C, D, E, F)
	-- http://www.wowwiki.com/SetTexCoord_Transformations
	local det = A*E - B*D;
	local ULx, ULy, LLx, LLy, URx, URy, LRx, LRy;

	ULx, ULy = ( B*F - C*E ) / det, ( -(A*F) + C*D ) / det;
	LLx, LLy = ( -B + B*F - C*E ) / det, ( A - A*F + C*D ) / det;
	URx, URy = ( E + B*F - C*E ) / det, ( -D - A*F + C*D ) / det;
	LRx, LRy = ( E - B + B*F - C*E ) / det, ( -D + A -(A*F) + C*D ) / det;

	return ULx, ULy, LLx, LLy, URx, URy, LRx, LRy;
end;


}

ArtPad:CreateFrames();
ArtPad:OnLoad();

-- [[ Binding Constants ]]

BINDING_HEADER_ARTPAD = "ArtPad";
BINDING_NAME_ARTPAD_SHOW = "Show Art Window";
BINDING_NAME_ARTPAD_HIDE = "Hide Art Window";
BINDING_NAME_ARTPAD_TOGGLE = "Toggle Art Window";
From what I can see, all of the SendAddonMessage() functions still use the correct parameters and should be sending their messages to the party/raid group.

Is it possible that addon messages are restricted server-side or that there is something else blocking them?
  Reply With Quote
09-12-12, 05:02 PM   #2
Barjack
A Black Drake
AddOn Author - Click to view addons
Join Date: Apr 2009
Posts: 89
There was a change a while back that required addons to "register" their message prefix using RegisterAddonMessagePrefix. I've not used the system myself so I'm not sure of the specifics, but it might be worth looking into.
  Reply With Quote
09-12-12, 05:34 PM   #3
Haleth
This Space For Rent
 
Haleth's Avatar
Featured
Join Date: Sep 2008
Posts: 1,173
Ooh, I see. Stupid oversight on my part - thanks!

I'll see if I can get this working again now. I'll send a PM to the author and see if he wants to upload the changes or is okay with a fan update.

Edit: Got it working, will get an updated version online (either through the author's upload or fan update).

I fixed the filter as well to match the new grouping system where everyone in a non-raid group is assist.

Last edited by Haleth : 09-12-12 at 06:32 PM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Updating ArtPad


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off