vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 --------------------------------------------------------------------------
2 -- MobileFrames.lua
3 --------------------------------------------------------------------------
4 --[[
5 Mobile Minimap Buttons
6  
7 By: AnduinLothar <KarlKFI@cosmosui.org>
8  
9 Makes the Minimap Buttons draggable around the minimap with adjustable angle.
10 Control-Drag to change angle.
11 Control-Right-Click to bring up menu.
12 Menu: Reset, Reset All, Disable.
13  
14 Possible ToDo: Shift-Ctrl-Drag to change radius.
15  
16 Change Log:
17 v1.71
18 -Changed the radius calculation to make compatible with AddOns that allow changes to the radius setting of their buttons e.g. Gatherer, AlphaMap
19 -Updated the API.txt
20 v1.7
21 -Now automaticly makes mobile the following addon buttons: Soundtrack, Cirk's Blessings, CritLine, AlphaMap, and Natur EnemyCastBar.
22 v1.6
23 -Changed dragging and reset menu to control click to avoid conflict with battlegrounds button
24 -Fixed bug that wasn't saving posistions of icons unless you tapped them
25 v1.52
26 -Updated TOC to 11100
27 -Fixed Census button mask.
28 v1.51
29 -New Buttons are now Anchored when first made mobile. (Fixed OnLoad error with Atlas)
30 -Updated German Localization
31 v1.5 (1/15/06)
32 -Fixed Shift-OnClick option overridding to still work for clicks under half a second. (Fixes battleground minimap)
33 -Now automaticly makes mobile the following addon buttons: Atlas, CTRA, Wardrobe, Yatlas, Gatherer, Earth, IEF, CTA.
34 (Addon Buttons are only on English client until localized.)
35 v1.4 (1/4/06)
36 -Disabled OnDrag events of registered addon buttons (Wardrobe now correctly stops dragging)
37 -Fixed nil OnLoad bug by delaying frame loading until after PLAYER_ENTERING_WORLD on a fresh load
38 -Updated TOC to 10900
39 v1.3 (11/24/05)
40 -Dynamicly added buttons now save accross sessions
41 Demo additions:
42 /script MobileMinimapButtons_AddButton("AtlasButton","Atlas Button");
43 /script MobileMinimapButtons_AddButton("CT_RASets_Button","CT Raid Assist Button");
44 /script MobileMinimapButtons_AddButton("Wardrobe.IconFrame","Wardrobe Button");
45 /script MobileMinimapButtons_AddButton("TheYatlasButton","Yatlas Button");
46 /script MobileMinimapButtons_AddButton("GathererUI_IconFrame","Gatherer Button");
47 /script MobileMinimapButtons_AddButton("EarthMinimapButton","Earth Button");
48 /script MobileMinimapButtons_AddButton("IEFMinimapButton","Improved Error Frame Button");
49 /script MobileMinimapButtons_AddButton("CTA_MinimapIcon","Call To Arms Button");
50 v1.2 (10/27/05)
51 -Chnaged OnClick handling to allow for Casting via OnClick
52 -Implimented HasScript so that you no longer have to pass weather the frame is a button or not.
53 v1.11 (10/25/05)
54 -Fixed an obscure OnClick bug involving Khaos
55 v1.1 (10/18/05)
56 -Added dynamic button adding using MobileMinimapButtons_AddButton at any time.
57 -See API.txt for details on how to make your addon's button mobile.
58 v1.0 (9/30/05)
59 -Initial Release
60  
61  
62 $Id: MobileMinimapButtons.lua 2025 2005-07-02 23:51:34Z KarlKFI $
63 $Rev: 2025 $
64 $LastChangedBy: KarlKFI $
65 $Date: 2005-07-02 16:51:34 -0700 (Sat, 02 Jul 2005) $
66  
67  
68 ]]--
69  
70 --Update +1 if you change the list of frames in the localization!
71 local tempListVersion = MOBILE_MINIMAP_BUTTONS_LIST_VERSION;
72 local tempFrameList = MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS;
73  
74 MobileMinimapButtons_Debug = false;
75 MobileMinimapButtons_Coords = {};
76 MobileMinimapButtons_Enabled = true;
77 MobileMinimapButtons_CurrentlyEnabled = {};
78 MobileMinimapButtons_NextClickDisabled = nil;
79  
80 MobileMinimapButtons_FullSizeButtons = {
81 --Fullsize buttons use the 1/2 width offset rather than the normal 1/4 width
82 ["MiniMapTrackingFrame"] = true,
83 };
84  
85 MobileMinimapButtons_MaskParentButtons = {
86 --Parents that aren't attached hinder dragging, attach them.
87 ["AtlasButton"] = "AtlasButtonFrame",
88 ["CensusButton"] = "CensusButtonFrame",
89 ["CT_RASets_Button"] = "CT_RASetsFrame",
90 ["TheYatlasButton"] = "YatlasButtonFrame",
91 ["AM_MinimapButton"] = "AM_MinimapFrame",
92 };
93  
94 function MobileMinimapButtons_OnLoad()
95 this:RegisterEvent("VARIABLES_LOADED");
96 this:RegisterEvent("PLAYER_ENTERING_WORLD");
97 if (Khaos) then
98 MobileMinimapButtons_RegisterForKhaos();
99 end
100 end
101  
102 function MobileMinimapButtons_OnEvent(event)
103 if (event == "VARIABLES_LOADED") then
104 --Make sure list has new frames, but don't remove added ones
105 if (MOBILE_MINIMAP_BUTTONS_LIST_VERSION) and (tempListVersion > MOBILE_MINIMAP_BUTTONS_LIST_VERSION) then
106 for frameName, localizedFrameName in tempFrameList do
107 if (not MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS[frameName]) then
108 MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS[frameName] = localizedFrameName;
109 end
110 end
111 MOBILE_MINIMAP_BUTTONS_LIST_VERSION = tempListVersion;
112 end
113 tempFrameList = nil;
114 tempListVersion = nil
115 MobileMinimapButtons_EnteringWorldFromFullLoad = true;
116  
117 elseif (event == "PLAYER_ENTERING_WORLD") then
118 if (MobileMinimapButtons_EnteringWorldFromFullLoad) then
119 --Loop Through Minimap Buttons
120 for frameName, localizedFrameName in MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS do
121 if (Sea.util.getValue(frameName)) then
122 MobileMinimapButtons_MakeMobile(frameName, localizedFrameName);
123 end
124 end
125 MobileMinimapButtons_EnteringWorldFromFullLoad = nil;
126 MobileMinimapButtons_FramesLoaded = true;
127 end
128 end
129 end
130  
131 function MobileMinimapButtons_AddButton(frameName, localizedFrameName)
132 if (not frameName) or (not Sea.util.getValue(frameName)) then
133 Sea.io.print("MobileMinimapButtons Error: Cannot add ", frameName, " (", localizedFrameName, ") called from ", this:GetName(), ". The button does not exist.");
134 return;
135 elseif (MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS[frameName]) then
136 if (MobileMinimapButtons_FramesLoaded) then
137 Sea.io.print("MobileMinimapButtons Error: Cannot add ", frameName, " (", localizedFrameName, ") called from ", this:GetName(), ". Duplicate already registered.");
138 end
139 return;
140 end
141 MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS[frameName] = localizedFrameName;
142 if (MobileMinimapButtons_FramesLoaded) then
143 MobileMinimapButtons_MakeMobile(frameName, localizedFrameName);
144 if (not MobileMinimapButtons_Enabled) then
145 --Override Disable to redisable
146 MobileMinimapButtons_Enabled = true;
147 MobileMinimapButtons_Disable();
148 end
149 end
150 end
151  
152  
153 function MobileMinimapButtons_MakeMobile(frameName, localizedFrameName)
154 if (MobileMinimapButtons_CurrentlyEnabled[frameName]) then
155 -- Already Mobile
156 return;
157 end
158  
159 local frame = Sea.util.getValue(frameName);
160  
161 --Store the current position as the reset coords
162 MobileMinimapButtons_StoreResetPosition(frameName);
163  
164 --Load Frame Script Element Hooks
165 Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnEvent", "replace", "OnEvent" );
166 if (frame:HasScript("OnClick")) then
167 --Enable Click events
168 --frame:RegisterForClicks("LeftButton", "RightButton");
169 Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnClick", "replace", "OnClick" );
170 end
171 Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnMouseDown", "replace", "OnMouseDown" );
172 Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnMouseUp", "replace", "OnMouseUp" );
173 Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnHide", "replace", "OnHide" );
174 Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnUpdate", "replace", "OnUpdate" );
175  
176 --Make sure all the Buttons are Mobile
177 if (not frame:IsMovable()) then
178 frame:SetMovable(1);
179 end
180  
181 --Disable OnDrag events by passing no arguments
182 frame:RegisterForDrag();
183  
184 --Reposition Buttons to Saved Coords
185 local coords = MobileMinimapButtons_Coords[frameName];
186 frame:ClearAllPoints();
187 if (coords) and (coords.x) and (coords.y) then
188 frame:SetPoint("CENTER", "Minimap", "CENTER", coords.x, coords.y);
189 else
190 frame:SetPoint("CENTER", "Minimap", "CENTER", frame.resetX, frame.resetY);
191 end
192  
193 --Set as enabled for this session
194 MobileMinimapButtons_CurrentlyEnabled[frameName] = localizedFrameName;
195 --Save for later
196 MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS[frameName] = localizedFrameName;
197  
198 --Elevate Buttons Above the MiniMap
199 frame:SetFrameLevel(frame:GetFrameLevel()+1);
200  
201 --Attach Parent Buttons
202 local maskFrame = Sea.util.getValue(MobileMinimapButtons_MaskParentButtons[frameName])
203 if (maskFrame) then
204 maskFrame:SetAllPoints(frame);
205 end
206 end
207  
208 function MobileMinimapButtons_StoreResetPosition(frameName)
209 local frame = Sea.util.getValue(frameName);
210 local centerX, centerY = Minimap:GetCenter();
211 local thisX, thisY = frame:GetCenter();
212 local radius;
213  
214 local diffX = centerX - thisX;
215 local diffY = centerY - thisY;
216 local dist = (diffX * diffX) + (diffY * diffY);
217 radius = math.sqrt(dist);
218  
219 local x = math.abs(thisX - centerX);
220 local y = math.abs(thisY - centerY);
221 local xSign = 1;
222 local ySign = 1;
223 if not (thisX >= centerX) then
224 xSign = -1;
225 end
226 if not (thisY >= centerY) then
227 ySign = -1;
228 end
229 --Sea.io.print(xSign*x,", ",ySign*y);
230 local angle = math.atan(x/y);
231 x = math.sin(angle)*radius;
232 y = math.cos(angle)*radius;
233 frame.resetX = xSign*x;
234 frame.resetY = ySign*y;
235 end
236  
237 function MobileMinimapButtons_Reset(frame)
238 if (frame) then
239 frame.isMoving = false;
240 frame:ClearAllPoints();
241 frame:SetPoint("CENTER", "Minimap", "CENTER", frame.resetX, frame.resetY);
242 frame:SetUserPlaced(false);
243 MobileMinimapButtons_Coords[frame:GetName()] = nil;
244 end
245 end
246  
247 function MobileMinimapButtons_ResetAll()
248 for frameName, localizedFrameName in MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS do
249 local frame = Sea.util.getValue(frameName);
250 MobileMinimapButtons_Reset(frame);
251 end
252 end
253  
254 function MobileMinimapButtons_Disable()
255 if (not MobileMinimapButtons_Enabled) then
256 return;
257 end
258 for frameName, localizedFrameName in MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS do
259 --Reset Location without forgetting coords
260 local frame = Sea.util.getValue(frameName);
261 if (frame) then
262 frame.isMoving = false;
263 frame:ClearAllPoints();
264 frame:SetPoint("CENTER", "Minimap", "CENTER", frame.resetX, frame.resetY);
265 frame:SetUserPlaced(false);
266  
267 --Unload Frame Script Element Hooks
268 Sea.util.unhook( frameName, "MobileMinimapButtons_Master_OnEvent", "replace", "OnEvent" );
269 if (frame:HasScript("OnClick")) then
270 Sea.util.unhook( frameName, "MobileMinimapButtons_Master_OnClick", "replace", "OnClick" );
271 end
272 Sea.util.unhook( frameName, "MobileMinimapButtons_Master_OnMouseDown", "replace", "OnMouseDown" );
273 Sea.util.unhook( frameName, "MobileMinimapButtons_Master_OnMouseUp", "replace", "OnMouseUp" );
274 Sea.util.unhook( frameName, "MobileMinimapButtons_Master_OnHide", "replace", "OnHide" );
275 Sea.util.unhook( frameName, "MobileMinimapButtons_Master_OnUpdate", "replace", "OnUpdate" );
276 end
277 end
278 MobileMinimapButtons_Enabled = nil;
279 end
280  
281 function MobileMinimapButtons_ReEnable()
282 if (MobileMinimapButtons_Enabled) then
283 return;
284 end
285 for frameName, localizedFrameName in MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS do
286 --Load Frame Script Element Hooks
287 local frame = Sea.util.getValue(frameName);
288 if (frame) then
289 Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnEvent", "replace", "OnEvent" );
290 if (frame:HasScript("OnClick")) then
291 Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnClick", "replace", "OnClick" );
292 end
293 Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnMouseDown", "replace", "OnMouseDown" );
294 Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnMouseUp", "replace", "OnMouseUp" );
295 Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnHide", "replace", "OnHide" );
296 Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnUpdate", "replace", "OnUpdate" );
297  
298 --Reposition Buttons to Saved Coords
299 local coords = MobileMinimapButtons_Coords[frameName];
300 if (coords) and (coords.x) and (coords.y) then
301 local frame = Sea.util.getValue(frameName);
302 frame:ClearAllPoints();
303 frame:SetPoint("CENTER", "Minimap", "CENTER", coords.x, coords.y);
304 end
305 end
306 end
307 MobileMinimapButtons_Enabled = true;
308 end
309  
310 function MobileMinimapButtons_Master_OnMouseDown()
311 Sea.io.dprint("MobileMinimapButtons_Debug", "MobileMinimapButtons_Master_OnMouseDown(", arg1, ")");
312 if (IsControlKeyDown()) then
313 if (arg1 == "LeftButton") then
314 this.isMoving = 0;
315 local centerX, centerY = Minimap:GetCenter();
316 local thisX, thisY = this:GetCenter();
317 local diffX = centerX - thisX;
318 local diffY = centerY - thisY;
319 local dist = (diffX * diffX) + (diffY * diffY);
320 this.radius = math.sqrt(dist);
321 end
322 else
323 return true;
324 end
325 end
326  
327 function MobileMinimapButtons_Master_OnMouseUp()
328 Sea.io.dprint("MobileMinimapButtons_Debug", "MobileMinimapButtons_Master_OnMouseUp(", arg1, ")");
329 local frameName = this:GetName();
330 if (this.isMoving) then
331 if (MouseIsOver(this)) and (this.isMoving > GetFramerate()) then
332 --Only disable OnClick if it was dragging longer than 1 second (accounts for shift-OnClicking)
333 MobileMinimapButtons_NextClickDisabled = true;
334 end
335 if (not MobileMinimapButtons_Coords[frameName]) then
336 MobileMinimapButtons_Coords[frameName] = {};
337 end
338 MobileMinimapButtons_Coords[frameName].x = this.currentX;
339 MobileMinimapButtons_Coords[frameName].y = this.currentY;
340 this.isMoving = false;
341 this.radius = nil;
342 elseif (MouseIsOver(this)) then
343 if (IsControlKeyDown()) and (arg1 == "RightButton") then
344 --MobileMinimapButtons_Reset(this);
345 MobileMinimapButtonsDropDown.displayMode = "MENU";
346 ToggleDropDownMenu(1, frameName, MobileMinimapButtonsDropDown, frameName);
347 --MobileMinimapButtonsDropDown_Reposition(frameName);
348 MobileMinimapButtons_NextClickDisabled = true;
349 else
350 --MobileMinimapButtons_NextClickDisabled = nil;
351 return true;
352 end
353 else
354 return true;
355 end
356 end
357  
358 function MobileMinimapButtons_Master_OnClick()
359 if (not MobileMinimapButtons_NextClickDisabled) then
360 Sea.io.dprint("MobileMinimapButtons_Debug", "MobileMinimapButtons_Master_OnClick(", arg1, ") Orig Called.");
361 return true;
362 else
363 Sea.io.dprint("MobileMinimapButtons_Debug", "MobileMinimapButtons_Master_OnClick(", arg1, ") Orig Not Called.");
364 MobileMinimapButtons_NextClickDisabled = nil;
365 end
366 end
367  
368 function MobileMinimapButtons_Master_OnHide()
369 this.isMoving = false;
370 return true;
371 end
372  
373 function MobileMinimapButtons_Master_OnUpdate()
374 if (this.isMoving) then
375 this.isMoving = this.isMoving+1;
376 local mouseX, mouseY = GetCursorPosition();
377 local centerX, centerY = Minimap:GetCenter();
378 local scale = Minimap:GetEffectiveScale();
379 mouseX = mouseX / scale;
380 mouseY = mouseY / scale;
381 local radius;
382  
383 if ( not this.radius ) then
384 if (MobileMinimapButtons_FullSizeButtons[this:GetName()]) then
385 radius = ((Minimap:GetRight()-Minimap:GetLeft())/2) + ((this:GetRight()-this:GetLeft())/2);
386 else
387 radius = ((Minimap:GetRight()-Minimap:GetLeft())/2) + ((this:GetRight()-this:GetLeft())/4);
388 end
389 else
390 radius = this.radius;
391 end
392  
393 local x = math.abs(mouseX - centerX);
394 local y = math.abs(mouseY - centerY);
395 local xSign = 1;
396 local ySign = 1;
397 if not (mouseX >= centerX) then
398 xSign = -1;
399 end
400 if not (mouseY >= centerY) then
401 ySign = -1;
402 end
403 --Sea.io.print(xSign*x,", ",ySign*y);
404 local angle = math.atan(x/y);
405 x = math.sin(angle)*radius;
406 y = math.cos(angle)*radius;
407 this.currentX = xSign*x;
408 this.currentY = ySign*y;
409 this:ClearAllPoints();
410 this:SetPoint("CENTER", "Minimap", "CENTER", this.currentX, this.currentY);
411 else
412 return true;
413 end
414 end
415  
416 -- <= == == == == == == == == == == == == =>
417 -- => Menu
418 -- <= == == == == == == == == == == == == =>
419  
420 function MobileMinimapButtons_LoadDropDownMenu()
421 --Title
422 local info = {};
423 info.text = MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS[UIDROPDOWNMENU_MENU_VALUE];
424 info.notClickable = 1;
425 info.isTitle = 1;
426 UIDropDownMenu_AddButton(info, 1);
427  
428 --Reset
429 local info = {};
430 info.text = RESET;
431 info.value = "Reset";
432 info.func = function() MobileMinimapButtons_Reset(Sea.util.getValue(UIDROPDOWNMENU_MENU_VALUE)) end;
433 --info.notCheckable = 1;
434 UIDropDownMenu_AddButton(info, 1);
435  
436 --Reset All
437 local info = {};
438 info.text = RESET_ALL;
439 info.value = "ResetAll";
440 info.func = MobileMinimapButtons_ResetAll;
441 --info.notCheckable = 1;
442 UIDropDownMenu_AddButton(info, 1);
443  
444 MobileMinimapButtonsDropDown_Reposition(UIDROPDOWNMENU_MENU_VALUE);
445 end
446  
447 function MobileMinimapButtonsDropDown_OnLoad()
448 UIDropDownMenu_Initialize(this, MobileMinimapButtons_LoadDropDownMenu, "MENU");
449 end
450  
451 function MobileMinimapButtonsDropDown_Reposition(anchorName)
452 local customPoint = "TOPLEFT"; --Default Anchor
453 local offscreenY, offscreenX, anchorPoint, relativePoint, offsetX, offsetY;
454 local listFrame = getglobal("DropDownList"..UIDROPDOWNMENU_MENU_LEVEL);
455 -- Determine whether the menu is off the screen or not
456 local offscreenY, offscreenX;
457 --Hack for built in bug
458 if ( not listFrame:GetRight() ) then
459 return;
460 end
461  
462 if ( listFrame:GetBottom() < WorldFrame:GetBottom() ) then
463 offscreenY = 1;
464 end
465 if ( listFrame:GetRight() > WorldFrame:GetRight() ) then
466 offscreenX = 1;
467 end
468  
469 local anchorPoint, relativePoint, offsetX, offsetY;
470 if ( offscreenY == 1 ) then
471 if ( offscreenX == 1 ) then
472 anchorPoint = string.gsub(customPoint, "TOP(.*)", "BOTTOM%1");
473 anchorPoint = string.gsub(anchorPoint, "(.*)LEFT", "%1RIGHT");
474 relativePoint = "TOPRIGHT";
475 offsetX = 0;
476 offsetY = 14;
477 else
478 anchorPoint = string.gsub(customPoint, "TOP(.*)", "BOTTOM%1");
479 relativePoint = "TOPLEFT";
480 offsetX = 0;
481 offsetY = 14;
482 end
483 else
484 if ( offscreenX == 1 ) then
485 anchorPoint = string.gsub(customPoint, "(.*)LEFT", "%1RIGHT");
486 relativePoint = "BOTTOMRIGHT";
487 offsetX = 0;
488 offsetY = -14;
489 else
490 anchorPoint = customPoint;
491 relativePoint = "BOTTOMLEFT";
492 offsetX = 0;
493 offsetY = -14;
494 end
495 end
496 listFrame:ClearAllPoints();
497 listFrame:SetPoint(anchorPoint, anchorName, relativePoint, offsetX, offsetY);
498  
499 -- Reshow the "MENU" border
500 getglobal(listFrame:GetName().."Backdrop"):Hide();
501 getglobal(listFrame:GetName().."MenuBackdrop"):Show();
502 --getglobal(listFrame:GetName().."Backdrop"):Show();
503 --getglobal(listFrame:GetName().."MenuBackdrop"):Hide();
504 end
505  
506 -- <= == == == == == == == == == == == == =>
507 -- => Khaos Registration
508 -- <= == == == == == == == == == == == == =>
509  
510 function MobileMinimapButtons_RegisterForKhaos()
511 local optionSet = {
512 id="MobileMinimapButtons";
513 text=MOBILE_MINIMAP_BUTTONS_HEADER;
514 helptext=MOBILE_MINIMAP_BUTTONS_HEADER_INFO;
515 difficulty=1;
516 default = {checked = true};
517 callback = function(checked)
518 if (checked) then
519 MobileMinimapButtons_ReEnable();
520 else
521 MobileMinimapButtons_Disable();
522 end
523 end;
524 options={
525 {
526 id="Header";
527 text=MOBILE_MINIMAP_BUTTONS_HEADER;
528 helptext=MOBILE_MINIMAP_BUTTONS_HEADER_INFO;
529 type=K_HEADER;
530 };
531 {
532 id="ResetAll";
533 type=K_BUTTON;
534 text=MOBILE_MINIMAP_BUTTONS_RESET_ALL_TEXT;
535 helptext=MOBILE_MINIMAP_BUTTONS_RESET_ALL_TEXT_INFO;
536 callback=MobileMinimapButtons_ResetAll;
537 setup={buttonText=RESET_ALL};
538 };
539 };
540 };
541 Khaos.registerOptionSet(
542 "frames",
543 optionSet
544 );
545 end