Merge branch 'master' into achievements
[QuestHelper.git] / dodads_triangles.lua
blob2a35010b6436552a087df116eb8692ecd6f0e892
1 QuestHelper_File["dodads_triangles.lua"] = "Development Version"
2 QuestHelper_Loadtime["dodads_triangles.lua"] = GetTime()
4 -- I'm really curious what people might make out of this file. I'm not actually open-sourcing it yet, but let's say that if you *were* to come up with a neat idea, and wanted to use this code, I would almost certainly be willing to let you use it. Contact me as ZorbaTHut on EFNet/Freenode/Synirc, or zorba-qh-triangles@pavlovian.net email, or ZorbaTHut on AIM.
6 local function print()
7 end
9 function matrix_create()
10 return {1, 0, 0, 0, 1, 0, 0, 0, 1}
11 end
13 function matrix_rescale(matrix, x, y)
14 matrix[1], matrix[4] = matrix[1] * x, matrix[4] * x
15 matrix[2], matrix[5] = matrix[2] * y, matrix[5] * y
16 end
17 function matrix_mult(matrix, a, b, c, d, e, f) -- this is probably buggy
18 matrix[1], matrix[2], matrix[3], matrix[4], matrix[5], matrix[6], matrix[7], matrix[8], matrix[9] =
19 matrix[1] * a + matrix[4] * b + matrix[7] * c, matrix[2] * a + matrix[5] * b + matrix[8] * c, matrix[3] * a + matrix[6] * b + matrix[9] * c,
20 matrix[1] * d + matrix[4] * e + matrix[7] * f, matrix[2] * d + matrix[5] * e + matrix[8] * f, matrix[3] * d + matrix[6] * e + matrix[9] * f,
21 matrix[7], matrix[8], matrix[9]
22 end
23 function matrix_rotate(matrix, angle)
24 matrix_mult(matrix, cos(angle), -sin(angle), 0, sin(angle), cos(angle), 0)
25 end
26 function matrix_print(matrix)
27 print(string.format("\n%f %f %f\n%f %f %f\n%f %f %f", unpack(matrix)))
28 end
30 local function dist(sx, sy, ex, ey)
31 local dx = sx - ex
32 local dy = sy - ey
33 dx, dy = dx * dx, dy * dy
34 return math.sqrt(dx + dy)
35 end
37 local function testrange(...)
38 for k = 1, select("#", ...) do
39 if not (select(k, ...) > -60000 and select(k, ...) < 60000) then
40 return true
41 end
42 end
43 end
44 -- thoughts about the transformation
45 -- start with a right triangle, define the top as the base (find a base)
46 -- rescale Y to get the right height
47 -- skew X to get the right bottom X position
48 -- now we have the right shape
49 -- rotate, rescale, translate?
51 -- for now, we define a-b as the base, which means c is the peak
53 local spots = {}
54 for k = 1, 3 do
55 local minbutton = CreateFrame("Button", nil, UIParent)
56 minbutton:SetWidth(50)
57 minbutton:SetHeight(50)
59 local minbutton_tex = minbutton:CreateTexture()
60 minbutton_tex:SetAllPoints()
61 minbutton_tex:SetTexture(1, 0, 0, 0.5)
63 minbutton.Moove = function(self, x, y)
64 minbutton:ClearAllPoints()
65 minbutton:SetPoint("CENTER", UIParent, "TOPLEFT", x, -y)
66 end
67 table.insert(spots, minbutton)
68 end
70 local function MakeTriangle(frame)
71 tex = frame:CreateTexture()
72 tex:SetTexture("Interface\\AddOns\\QuestHelper\\triangle")
74 tex.parent_frame = frame
75 -- relative to 0,1 coordinates relative to parent
76 tex.SetTriangle = function(self, ax, ay, bx, by, cx, cy)
77 -- do we need to reverse the triangle?
78 if ax * by - bx * ay + bx * cy - cx * by + cx * ay - cy * ax < 0 then
79 ax, bx = bx, ax
80 ay, by = by, ay
81 end
83 print(ax, ay, bx, by, cx, cy)
84 ax, bx, cx = ax * frame:GetWidth(), bx * frame:GetWidth(), cx * frame:GetWidth()
85 ay, by, cy = ay * frame:GetHeight(), by * frame:GetHeight(), cy * frame:GetHeight()
86 print(ax, ay, bx, by, cx, cy)
87 self:ClearAllPoints()
89 local sx = math.min(ax, bx, cx)
90 local sy = math.min(ay, by, cy)
91 local ex = math.max(ax, bx, cx)
92 local ey = math.max(ay, by, cy)
94 local disty = math.max(ex - sx, ey - sy) / 2
96 --print("TOPLEFT", frame, "TOPLEFT", math.min(ax, bx, cx) * frame:GetWidth(), math.min(ax, bx, cx) * frame:GetHeight())
97 --print("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -math.max(ax, bx, cx) * frame:GetWidth(), -math.max(ax, bx, cx) * frame:GetHeight())
98 self:SetPoint("TOPLEFT", frame, "TOPLEFT", (sx + ex) / 2 - disty, -(sy + ey) / 2 + disty)
99 self:SetPoint("BOTTOMRIGHT", frame, "TOPLEFT", (sx + ex) / 2 + disty, -(sy + ey) / 2 - disty)
101 local wid = disty * 2
102 local hei = disty * 2
104 local widextra = (wid - (ex - sx)) / 2
105 local heiextra = (hei - (ey - sy)) / 2
107 local base = matrix_create()
109 matrix_mult(base, 1, 0, -1 / 512, 0, 1, -1 / 512)
110 matrix_rescale(base, 512 / 510, 512 / 510)
112 local lenab = dist(ax, ay, bx, by)
113 local lenbc = dist(bx, by, cx, cy)
114 local lenca = dist(cx, cy, ax, ay)
115 local s = (lenab + lenbc + lenca) / 2
116 local area = math.sqrt(s * (s - lenab) * (s - lenbc) * (s - lenca)) -- heron's formula
117 -- triangle area=base*height/2, therefore height=area/base*2
118 local height = area / lenab * 2
120 print(wid, hei, disty, ex - sx, ey - sy)
121 print(lenab, lenbc, lenca)
122 print(area, height)
123 print(lenab / wid, height / hei)
125 matrix_print(base)
126 matrix_rescale(base, lenab / wid, height / hei)
127 matrix_print(base)
129 -- now we have it scaled properly, now we have to skew
130 -- right now we have:
131 -- A----------B
132 -- |
133 -- C
134 -- We want:
135 -- A------------B
137 -- C
138 -- Virtual point:
139 -- D A------------B
141 -- C
142 -- So the question is, how long is DB? Find that out, divide by height, and there's our skew constant
143 -- unit(A-B) dot (C-B) - does this work? I think so
144 -- alternatively, ((A-B) dot (C-B)) / lenab
146 print("db is", ((ax - bx) * (cx - bx) + (ay - by) * (cy - by)))
147 print("height is", height)
148 print("lenab is", lenab)
150 if height == 0 then
151 self:SetTexCoord(3, 3, 4, 4)
152 return
155 -- same as matrix_mult(base, 1, (nastything), 0, 1) (I think? maybe not?)
156 matrix_mult(base, 1, -((ax - bx) * (cx - bx) + (ay - by) * (cy - by)) / lenab / height, 0, 0, 1, 0)
157 --base[2] = base[2] - ((ax - bx) * (cx - bx) + (ay - by) * (cy - by)) / lenab / height * base[5]
159 matrix_print(base)
161 -- next: we sit and rotate on it
163 local angle = atan2(ax - bx, ay - by)
164 print(angle)
166 matrix_rotate(base, -angle - 90) -- this will take adjustment
168 matrix_print(base)
170 -- now we translate to the expected position
172 print(ax - sx, ay - sy, (ax - sx) / lenab, (ay - sy) / lenab, (ax - sx) / wid, (ay - sy) / hei)
174 matrix_mult(base, 1, 0, tigo or ((ax - sx + widextra) / wid), 0, 1, togo or ((ay - sy + heiextra) / hei))
175 --base[3] = base[3] + (ax - sx) / lenab
176 --base[6] = base[6] + (ay - sy) / lenab
178 --[[matrix_rescale(base, 0.5, 0.5)
179 base[3] = base[3] + wing
180 base[6] = base[6] + wong]]
183 local A, B, C, D, E, F = base[1], base[2], base[3], base[4], base[5], base[6]
185 local det = A*E - B*D
186 local ULx, ULy, LLx, LLy, URx, URy, LRx, LRy
188 ULx, ULy = ( B*F - C*E ) / det, ( -(A*F) + C*D ) / det
189 LLx, LLy = ( -B + B*F - C*E ) / det, ( A - A*F + C*D ) / det
190 URx, URy = ( E + B*F - C*E ) / det, ( -D - A*F + C*D ) / det
191 LRx, LRy = ( E - B + B*F - C*E ) / det, ( -D + A -(A*F) + C*D ) / det
193 if testrange(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy) then
194 self:SetTexCoord(3, 3, 4, 4)
195 return
198 --QuestHelper:TextOut(string.format("%f %f %f %f %f %f %f %f %f", det, ULx, ULy, LLx, LLy, URx, URy, LRx, LRy))
199 --QuestHelper:TextOut(string.format("%f %f %f %f %f %f", A, B, C, D, E, F))
201 self:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy); -- the sound you hear is vomiting
203 --[[spots[1]:Moove(ax, ay)
204 spots[2]:Moove(bx, by)
205 spots[3]:Moove(cx, cy)]]
208 return tex
211 local alloc = {}
213 function CreateTriangle(frame)
214 if alloc[frame] and #alloc[frame] > 0 then
215 return table.remove(alloc[frame])
216 else
217 return MakeTriangle(frame)
221 function ReleaseTriangle(tri)
222 if not alloc[tri.parent_frame] then alloc[tri.parent_frame] = {} end
223 table.insert(alloc[tri.parent_frame], tri)
224 tri:Hide()
231 local function MakeLine(frame)
232 tex = frame:CreateTexture()
233 tex:SetTexture("Interface\\AddOns\\QuestHelper\\line")
235 tex.parent_frame = frame
236 -- relative to 0,1 coordinates relative to parent
237 tex.SetLine = function(self, ax, ay, bx, by)
238 -- do we need to reverse the triangle? NOTE: a lot of this code is unsurprisingly copied from triangle. were you surprised by this?
239 --[[
240 if ax * by - bx * ay + bx * cy - cx * by + cx * ay - cy * ax < 0 then
241 ax, bx = bx, ax
242 ay, by = by, ay
243 end]]
245 print(ax, ay, bx, by)
246 ax, bx = ax * frame:GetWidth(), bx * frame:GetWidth()
247 ay, by = ay * frame:GetHeight(), by * frame:GetHeight()
248 print(ax, ay, bx, by)
249 self:ClearAllPoints()
251 local sx = math.min(ax, bx)
252 local sy = math.min(ay, by)
253 local ex = math.max(ax, bx)
254 local ey = math.max(ay, by)
256 local disty = math.max(ex - sx, ey - sy) / 2 + 20
258 --print("TOPLEFT", frame, "TOPLEFT", math.min(ax, bx, cx) * frame:GetWidth(), math.min(ax, bx, cx) * frame:GetHeight())
259 --print("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -math.max(ax, bx, cx) * frame:GetWidth(), -math.max(ax, bx, cx) * frame:GetHeight())
260 self:SetPoint("TOPLEFT", frame, "TOPLEFT", (sx + ex) / 2 - disty, -(sy + ey) / 2 + disty)
261 self:SetPoint("BOTTOMRIGHT", frame, "TOPLEFT", (sx + ex) / 2 + disty, -(sy + ey) / 2 - disty)
263 local wid = disty * 2
264 local hei = disty * 2
266 local widextra = (wid - (ex - sx)) / 2
267 local heiextra = (hei - (ey - sy)) / 2
269 local base = matrix_create()
271 matrix_mult(base, 1, 0, -1 / 512, 0, 1, 0)
272 matrix_rescale(base, 512 / 510, 1 / disty)
274 local lenny = dist(ax, ay, bx, by)
275 print("lendist", lenny, disty * 2)
276 matrix_rescale(base, lenny / (disty * 2), 1)
279 local angle = atan2(ax - bx, ay - by)
280 matrix_rotate(base, -angle - 90)
283 print("trans", 1, 0, tigo or ((ax - sx + widextra) / wid), 0, 1, togo or ((ay - sy + heiextra) / hei))
284 matrix_mult(base, 1, 0, tigo or ((ax - sx + widextra) / wid), 0, 1, togo or ((ay - sy + heiextra) / hei))
285 matrix_print(base)
287 local A, B, C, D, E, F = base[1], base[2], base[3], base[4], base[5], base[6]
289 local det = A*E - B*D
290 local ULx, ULy, LLx, LLy, URx, URy, LRx, LRy
292 ULx, ULy = ( B*F - C*E ) / det, ( -(A*F) + C*D ) / det
293 LLx, LLy = ( -B + B*F - C*E ) / det, ( A - A*F + C*D ) / det
294 URx, URy = ( E + B*F - C*E ) / det, ( -D - A*F + C*D ) / det
295 LRx, LRy = ( E - B + B*F - C*E ) / det, ( -D + A -(A*F) + C*D ) / det
297 if testrange(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy) then
298 self:SetTexCoord(3, 3, 4, 4)
299 return
302 --QuestHelper:TextOut(string.format("%f %f %f %f %f %f %f %f %f", det, ULx, ULy, LLx, LLy, URx, URy, LRx, LRy))
303 --QuestHelper:TextOut(string.format("%f %f %f %f %f %f", A, B, C, D, E, F))
304 self:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy); -- the sound you hear is vomiting
306 --[[spots[1]:Moove(ax, ay)
307 spots[2]:Moove(bx, by)
308 spots[3]:Moove(cx, cy)]]
311 return tex
316 -- haha
317 -- yeeeeaah, I just overrode a local variable with another near-identical local variable
318 -- that's gonna bite me someday
319 local alloc = {}
321 -- guess whether I changed this code after copying it
322 -- hint:
323 -- I didn't change this code after copying it
324 -- are you shocked
325 -- man, if you've read this far in the QH sourcecode, you sure as hell better not be shocked
326 -- 'cause
327 -- yeah
328 -- that'd be kind of sad.
329 function CreateLine(frame)
330 if alloc[frame] and #alloc[frame] > 0 then
331 return table.remove(alloc[frame])
332 else
333 return MakeLine(frame)
337 function ReleaseLine(tri)
338 if not alloc[tri.parent_frame] then alloc[tri.parent_frame] = {} end
339 table.insert(alloc[tri.parent_frame], tri)
340 tri:Hide()
343 -- note: variable name is "tritest". try to guess why
344 function testit()
345 if tritest then tritest:Hide() end
346 tritest = CreateLine(UIParent)
347 tritest:SetLine(0.5, 0.6, 0.8, 0.7)
348 tritest:Show()