Guest User

Untitled

a guest
Jan 11th, 2026
40
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 35.96 KB | None | 0 0
  1. return function(plugin,pluginBase,dock,requestClose,EasyLSpageCalback)
  2.     ---------------
  3.     --//Pre-Run\\--
  4.     ---------------
  5.  
  6.     local pageConnections = {}
  7.  
  8.     -------------------
  9.     --//Static Defs\\--
  10.     -------------------
  11.  
  12.     local resource = pluginBase:WaitForChild("PluginCode"):WaitForChild("Core"):WaitForChild("Resource")
  13.     local OOP = resource:WaitForChild("OOP")
  14.     local ELSOOP = OOP:WaitForChild("ELSPage")
  15.     local patternGroupObject = require(ELSOOP:WaitForChild("PatternGroupObject"))
  16.     local traditionalButton = require(OOP:WaitForChild("TraditionalButton"))
  17.     local nodeTreeObject = require(OOP:WaitForChild("NodeTree"))(plugin,pluginBase,dock)
  18.     local traditionalDropdown = require(OOP:WaitForChild("TraditionalDropdown"))
  19.     local traditionalSelector = require(OOP:WaitForChild("TraditionalSelector"))(plugin,pluginBase,dock)
  20.     local pluginSettings = require(resource:WaitForChild("LocalSettings"))
  21.     --local defaultPatternData = require(resource:WaitForChild("DefaultPatternData"))
  22.     -- @depricated
  23.     local ezlsEnum = require(resource:WaitForChild("Enumerators"))
  24.     local primaryDCASHelper = require(resource:WaitForChild("PrimaryDockContextActionHelper"))
  25.    
  26.     local page = dock:WaitForChild("UIContainer"):WaitForChild("EasyLS"):WaitForChild("MainContainer"):WaitForChild("ELSPage")
  27.     local mainPanelContainer = page:WaitForChild("MainPanelContainer")
  28.     local lightGroups = mainPanelContainer:WaitForChild("Groups")
  29.     local groupsEditor = mainPanelContainer:WaitForChild("GroupsEditor")
  30.     local optionsFrame = mainPanelContainer:WaitForChild("Options")
  31.     local addGroupContainer = lightGroups:WaitForChild("AddLightGroup"):WaitForChild("AddLightContainer")
  32.     local addGroupButton = addGroupContainer:WaitForChild("AddButton")
  33.  
  34.     local leftPanelContainer = page:WaitForChild("LeftPanelContainer")
  35.     local leftPanelBackground = leftPanelContainer:WaitForChild("LeftPanelBackground")
  36.     local leftPanelBorder = leftPanelContainer:WaitForChild("LeftPanelBorder")
  37.     local leftPanelContent = leftPanelBackground:WaitForChild("Content")
  38.     local leftPanelEditorContainer = leftPanelContent:WaitForChild("Editor")
  39.     local leftPanelGroupsContainer = leftPanelContent:WaitForChild("Groups")
  40.     local pageSelectorButtons = leftPanelBackground:WaitForChild("PageSelector"):WaitForChild("Pages")
  41.     local editorPageButton = pageSelectorButtons:WaitForChild("Editor")
  42.     local groupsPageButton = pageSelectorButtons:WaitForChild("Groups")
  43.     local optionsPageButton = pageSelectorButtons:WaitForChild("Options")
  44.     local leftPanelEditorContainerMainFrame = leftPanelEditorContainer:WaitForChild("Main")
  45.     local patternSelectDropdown = leftPanelEditorContainerMainFrame:WaitForChild("PatternSelect")
  46.     local pausePlay = leftPanelEditorContainer:WaitForChild("MiniButtons"):WaitForChild("PausePlay")
  47.     local pauseButton = pausePlay:WaitForChild("Pause")
  48.     local playButton = pausePlay:WaitForChild("Play")
  49.  
  50.     local colorSelectorContainer = leftPanelEditorContainerMainFrame:WaitForChild("ColorSelector"):WaitForChild("MainContainer")
  51.     local colorSelectorTitle = colorSelectorContainer:WaitForChild("TextContainer"):WaitForChild("TextLabel")
  52.     local colorSelectorLeftArrow = colorSelectorContainer:WaitForChild("LeftArrowContainer"):WaitForChild("Button")
  53.     local colorSelectorRightArrow = colorSelectorContainer:WaitForChild("RightArrowContainer"):WaitForChild("Button")
  54.  
  55.     local dataEditMenuBackground = leftPanelGroupsContainer:WaitForChild("Background")
  56.     local dataEditMenuTitle = dataEditMenuBackground:WaitForChild("Title")
  57.     local dataEditMenuIndexValue = dataEditMenuBackground:WaitForChild("Index"):WaitForChild("Value")
  58.     local dataEditMenuDoneButton = dataEditMenuBackground:WaitForChild("LowerButtons"):WaitForChild("Done")
  59.     local dataEditMenuRemoveButton = dataEditMenuBackground:WaitForChild("LowerButtons"):WaitForChild("Remove")
  60.    
  61.     local leftPanelColumnEditorContainer = leftPanelEditorContainer:WaitForChild("LightEditor")
  62.     local halogenOptions = leftPanelColumnEditorContainer:WaitForChild("LightEditor"):WaitForChild("LightColumnEditor"):WaitForChild("HalogenOptions")
  63.    
  64.     local templates = pluginBase:WaitForChild("Storage"):WaitForChild("Templates")
  65.  
  66.     local dataSerializerRef = { --used to access verious properties of PatternObjects and PatternGroupObjects with the same keys
  67.         name = {pg="name",p="patternName"},
  68.         index = {pg="playbackPriority",p="patternIndex"},
  69.     }
  70.  
  71.     --------------------
  72.     --//Dynamic Defs\\--
  73.     --------------------
  74.  
  75.     local patternGroups = {} --all pattern groups
  76.  
  77.     local patternDepthMap = {} --maps patterns in linear order to patterns in depth in pattern groups: {patternGroupIndex=patGroupIndex,patternindex=patIndex}
  78.     local loadedPattern = nil --data object for loaded pattern
  79.     local queuedPattern = nil --data object for queued pattern
  80.  
  81.     local addGroupButtonObject = nil
  82.     local playButtonObject = nil
  83.     local pauseButtonObject = nil
  84.     local patternSelectDropdownObject = nil
  85.     local patternNodeTree = nil
  86.     local colorSelectorObject = nil
  87.  
  88.     local windows = {
  89.         {
  90.             button = editorPageButton,
  91.             containers = {leftPanelEditorContainer,lightGroups},
  92.         },
  93.         {
  94.             button = groupsPageButton,
  95.             containers = {leftPanelGroupsContainer,groupsEditor},
  96.         },
  97.         --[[{
  98.             button = optionsPageButton,
  99.             containers = {optionsFrame},
  100.         },]]
  101.     }
  102.     local currentWindow = 0
  103.  
  104.     local isOpen = false --page is currently open
  105.     local playing = true --paused or playing
  106.  
  107.     local dataEditMenuOpen = {false} --false when closed, true when open with second and [third] param set to pattern group and pattern if applicable
  108.     local dataEditMenuConnections = {}
  109.     local dataEditMenuDoneButtonObject = nil
  110.     local dataEditMenuRemoveButtonObject = nil
  111.  
  112.     local columnEditorContent = nil --light that is currently being edited by the column editor
  113.     local columnEditorDoneButtonObject = nil
  114.     local columnLightEditorBulbTypeDropdownObject = nil
  115.     local columnLightEditorFadeInDropdownObject = nil
  116.     local columnLightEditorFadeOutDropdownObject = nil
  117.     local columnEditorConnections = {}
  118.  
  119.     local currentConfig = {}
  120.  
  121.     -------------------
  122.     --//Preset Defs\\--
  123.     -------------------
  124.    
  125.     local miscDirectory = { -- a directory of misc functions to be called from parent EasyLS module
  126.         colorRemovedFromPallete = function(colorIndex) --makes indexes of colors match up after a color is removed
  127.             for _,patternGroupData in ipairs(patternGroups) do
  128.                 for _,patternData in ipairs(patternGroupData.patternObjects) do
  129.                     for _,lightGroupData in ipairs(patternData.lightGroups) do
  130.                         for _,columnData in ipairs(lightGroupData.lightColumns) do
  131.                             if columnData._type == ezlsEnum.ClassType.LightColumnObject then
  132.                                 for _,lightData in ipairs(columnData.lightData) do
  133.                                     if lightData[1] > colorIndex then
  134.                                         lightData[1]-=1
  135.                                     elseif lightData[1] == colorIndex then
  136.                                         lightData[1] = -1
  137.                                     end
  138.                                 end
  139.                             end
  140.                         end
  141.                     end
  142.                 end
  143.             end
  144.         end,
  145.        
  146.         getKeybindOptions = function()
  147.             local allOptions = {}
  148.            
  149.             --//Index functions for each specific pattern and pattern group
  150.             local function indexPG(pg)
  151.                 table.insert(allOptions,
  152.                     {
  153.                         object=pg,
  154.                         getRawName = function() -- used by compiler
  155.                             return "PG_"..pg.name
  156.                         end,
  157.                         getName = function() --<font size=''> </font>
  158.                             return "<b>"..pg.name.."</b> <font size='10'><font transparency='.5'>(Group)</font></font>"
  159.                         end,
  160.                         actions={
  161.                             {name="Cycle",bindType=ezlsEnum.KeybindActionType.ToggleAction}, --defines keybind restriction data
  162.                             {name="Off",bindType=ezlsEnum.KeybindActionType.ToggleAction},
  163.                         }, --The first action provided will be auto selected when this category is selected.  is it the default action
  164.                     }
  165.                 )
  166.             end
  167.             local function indexP(p)
  168.                 table.insert(allOptions,
  169.                     {
  170.                         object=p,
  171.                         getRawName = function() -- used by compiler
  172.                             return "P_"..p.patternName
  173.                         end,
  174.                         getName = function()
  175.                             return p.patternName.." <font size='10'><font transparency='.5'>(Pattern)</font></font>"
  176.                         end,
  177.                         actions={
  178.                             {name="Toggle",bindType=ezlsEnum.KeybindActionType.ToggleAction}, --defines keybind restriction data
  179.                             {name="On",bindType=ezlsEnum.KeybindActionType.ToggleAction},
  180.                             {name="Off",bindType=ezlsEnum.KeybindActionType.ToggleAction},
  181.                             {name="Activate",bindType=ezlsEnum.KeybindActionType.ActivateAction},
  182.                         }, --The first action provided will be auto selected when this category is selected.  is it the default action
  183.                     }
  184.                 )
  185.             end
  186.            
  187.             for _,pg in ipairs(patternGroups) do
  188.                 indexPG(pg)
  189.                 for _,p in ipairs(pg.patternObjects) do
  190.                     indexP(p)
  191.                 end
  192.             end
  193.            
  194.             --//Custom Functions
  195.             table.insert(allOptions,
  196.                 {
  197.                     object="All ELS",
  198.                     getRawName = function() -- used by compiler
  199.                         return "All ELS"
  200.                     end,
  201.                     getName = function()
  202.                         return "All ELS"
  203.                     end,
  204.                     actions={
  205.                         {name="Off",bindType=ezlsEnum.KeybindActionType.ToggleAction},
  206.                     },
  207.                 }
  208.             )
  209.            
  210.            
  211.             for _,option in ipairs(allOptions) do
  212.                 setmetatable(option,{
  213.                     __tostring = function(t)
  214.                         return t.getName()
  215.                     end,
  216.                     __eq = function(self,t) --overwrite EQ here so when dropdown object compares these tables, it will be based off object not name
  217.                         return typeof(t)=="table" and self.object==t.object
  218.                     end,
  219.                 })
  220.                 for _,actionTable in ipairs(option.actions) do --//Make sure all option actions tostring metamethod point to their name field.  tostring is called on that data in dropdown object
  221.                     setmetatable(actionTable,{
  222.                         __tostring = function(t)
  223.                             return t.name
  224.                         end,
  225.                         __eq = function(self,t)
  226.                             return typeof(t)=="table" and self.name==t.name
  227.                         end,
  228.                     })
  229.                 end
  230.             end
  231.            
  232.             warn("GETTING OPTIONS")
  233.            
  234.             return allOptions
  235.         end,
  236.        
  237.     }
  238.    
  239.     local fadeOptions = {"Linear","Quad","Exponential"}
  240.    
  241.     -----------------
  242.     --//Fucntions\\--
  243.     -----------------
  244.  
  245.     local function c(con) --short statement to index a connection to the page, so i dont have to write this out every time
  246.         table.insert(pageConnections,con)
  247.     end
  248.  
  249.     local function accessPatternObjectFromMapIndex(i)
  250.         local patternDepthResult = patternDepthMap[i]
  251.         if patternDepthResult then
  252.             return patternGroups[patternDepthResult.patternGroupIndex].patternObjects[patternDepthResult.patternIndex]
  253.         else
  254.             return nil
  255.         end
  256.     end
  257.  
  258.     local function playPatterns()
  259.         if not playing then
  260.             playButton.Visible = false
  261.             playButtonObject:SetState(false)
  262.             pauseButton.Visible = true
  263.             if loadedPattern then
  264.                 for _,v in ipairs(loadedPattern.lightGroups) do
  265.                     v:PlayPattern()
  266.                 end
  267.             end
  268.             playing = true
  269.             pauseButtonObject:SetState(true)
  270.         end
  271.     end
  272.  
  273.     local function pausePatterns()
  274.         if playing then
  275.             pauseButton.Visible = false
  276.             playButton.Visible = true
  277.             pauseButtonObject:SetState(false)
  278.             if loadedPattern then
  279.                 for _,v in ipairs(loadedPattern.lightGroups) do
  280.                     v:PausePattern()
  281.                 end
  282.             end
  283.             playing = false
  284.             playButtonObject:SetState(true)
  285.         end
  286.     end
  287.  
  288.     local function unloadPattern(patternObject)
  289.         if patternObject then
  290.             patternObject:UnloadFromEditor()
  291.  
  292.             loadedPattern = nil
  293.         end
  294.     end
  295.  
  296.     local function loadPattern(patternObject)
  297.         if isOpen then --load the pattern
  298.             playPatterns() --whenever we switch patterns, start with it playing
  299.  
  300.             unloadPattern(loadedPattern) --unload existing pattern
  301.  
  302.             --//load new pattern
  303.             if patternObject then
  304.                 patternObject:LoadToEditor()
  305.             end
  306.  
  307.             loadedPattern = patternObject --def as loaded pattern
  308.         else --queue pattern to be loaded when menu is opened
  309.             if patternObject ~= queuedPattern then
  310.                 queuedPattern = patternObject
  311.             end
  312.         end
  313.     end
  314.  
  315.     local function resumeData()
  316.         for _,v in pairs(patternGroups) do
  317.             v:Resume()
  318.         end
  319.  
  320.         loadPattern(queuedPattern)
  321.         queuedPattern = nil
  322.     end
  323.  
  324.     local function pauseData()
  325.         for _,v in pairs(patternGroups) do
  326.             v:Yield()
  327.         end
  328.  
  329.         queuedPattern = loadedPattern
  330.         unloadPattern(loadedPattern)
  331.     end
  332.  
  333.     local function syncPatterns() --called whenever a pattern is added, removed, or its index is changed
  334.         local absolutePatternToGroupAndPattern = {}
  335.         local absolutePatternToName = {}
  336.  
  337.         for patternGroupIndex,patternGroupObject in pairs(patternGroups) do
  338.             for patternIndex,patternObject in pairs(patternGroupObject.patternObjects) do
  339.                 table.insert(absolutePatternToGroupAndPattern,{patternGroupIndex=patternGroupIndex,patternIndex=patternIndex})
  340.                 table.insert(absolutePatternToName,patternObject)
  341.             end
  342.         end
  343.  
  344.         patternDepthMap = absolutePatternToGroupAndPattern --update depth map.
  345.        
  346.         local reselectedPatternIndex = patternSelectDropdownObject:UpdateOptions(absolutePatternToName,true)
  347.         reselectedPatternIndex = reselectedPatternIndex or 1 --if nothing was able to be reselected, queue the default pattern
  348.        
  349.         if isOpen then
  350.             unloadPattern(loadedPattern)
  351.             loadPattern(accessPatternObjectFromMapIndex(reselectedPatternIndex))
  352.         else
  353.             queuedPattern = accessPatternObjectFromMapIndex(reselectedPatternIndex)
  354.         end
  355.     end
  356.  
  357.     local function canAddNewPattern(nodeMap)
  358.         return patternGroups[nodeMap[1]]:CanMakeNewPattern()
  359.     end
  360.  
  361.     local function newPattern(nodeMap)
  362.         local patternGroup = patternGroups[nodeMap[1]]
  363.  
  364.         patternGroup:RawNewPattern(#patternGroup.patternObjects+1)
  365.     end
  366.  
  367.     local function rawRemovePatternGroup(index)
  368.         patternGroups[index]:Cleanup()
  369.  
  370.         table.remove(patternGroups,index)
  371.  
  372.         for i=index,#patternGroups do
  373.             patternGroups[i]:SyncOrder(i)
  374.         end
  375.  
  376.         syncPatterns()
  377.     end
  378.  
  379.     local function removePatternGroup(index)
  380.         rawRemovePatternGroup(index)
  381.     end
  382.  
  383.     local function rawNewPatternGroup(priority,name)
  384.         local group = patternGroupObject.new(priority,name)
  385.         table.insert(patternGroups,group)
  386.         group:Initialize()
  387.  
  388.         if isOpen then
  389.             group:Resume()
  390.         end
  391.  
  392.         return group
  393.     end
  394.  
  395.     local function canAddPatternGroup()
  396.         return #patternGroups < pluginSettings.elsSettings.maxPatternGroups
  397.     end
  398.  
  399.     local function newPatternGroup(priority,name)
  400.         --//fill priority at lowest if not given
  401.         if type(priority)~="number" then
  402.             local highestNum = 0
  403.             for _,patternGroup in pairs(patternGroups) do
  404.                 local p = patternGroup.playbackPriority
  405.                 highestNum = p>highestNum and p or highestNum
  406.             end
  407.             priority = highestNum+1
  408.         end
  409.  
  410.         --//make light group if allowed
  411.         if canAddPatternGroup() then
  412.             local group = rawNewPatternGroup(priority,name)
  413.  
  414.             return group
  415.         else
  416.             warn("Max pattern groups reached")
  417.         end
  418.     end
  419.  
  420.     local function clearData()
  421.         for i=1,#patternGroups do
  422.             rawRemovePatternGroup(1)
  423.         end
  424.  
  425.         loadedPattern = nil
  426.     end
  427.  
  428.     local function rawUpdatePatternGroupIndex(patternGroupIndex,newIndex)
  429.         --//make raw data change
  430.         local d = patternGroups[patternGroupIndex]
  431.         table.remove(patternGroups,patternGroupIndex)
  432.         table.insert(patternGroups,newIndex,d)
  433.  
  434.         --//sync objects to reflect change
  435.         for i = math.min(patternGroupIndex,newIndex),math.max(patternGroupIndex,newIndex) do
  436.             patternGroups[i]:SyncOrder(i)
  437.         end
  438.  
  439.         --//sync second table that lists data in terms of patterns instead of pattern groups
  440.         patternNodeTree:MoveNode({},patternGroupIndex,newIndex)
  441.         syncPatterns()
  442.  
  443.         --//return new value
  444.         return newIndex
  445.     end
  446.  
  447.     local function updatePatternGroupIndex(patternGroupIndex,newIndex) --returns new pattern group index
  448.         local result = patternGroupIndex --nothing changed, so just spit out the old value
  449.  
  450.         local newIndex = tonumber(newIndex)
  451.         if newIndex then
  452.             newIndex = math.clamp(newIndex,1,#patternGroups)--verify newindex is within range, if not clamp to range
  453.             if patternGroupIndex~=newIndex then --verify newindex is given and a number
  454.                 result = rawUpdatePatternGroupIndex(patternGroupIndex,newIndex) --carry out update and spit out new index
  455.             end
  456.         end
  457.  
  458.         return result
  459.     end
  460.    
  461.     local function resetDataEditMenuData()
  462.         for _,c in ipairs(dataEditMenuConnections) do
  463.             c:Disconnect()
  464.         end
  465.         table.clear(dataEditMenuConnections)
  466.  
  467.         dataEditMenuDoneButtonObject:SetState(false)
  468.         dataEditMenuRemoveButtonObject:SetState(false)
  469.     end
  470.    
  471.     local function closeDataEditMenu()
  472.         dataEditMenuBackground.Visible = false
  473.        
  474.         resetDataEditMenuData()
  475.     end
  476.  
  477.     local function openDataEditMenu(patternGroupIndex,patternIndex)
  478.         --//when provided with 1 param, assumes pattern group.  if given 2, assumes pattern
  479.         local dataObject = patternGroups[patternGroupIndex]
  480.         local dataType = "pg" --pg for group, p for pattern
  481.         if patternIndex then
  482.             dataObject = dataObject.patternObjects[patternIndex]
  483.             dataType = "p"
  484.         end
  485.  
  486.         --//open menu, load data, init connections
  487.         dataEditMenuBackground.Visible = true
  488.         dataEditMenuTitle.Text = dataObject[dataSerializerRef.name[dataType]]
  489.  
  490.         dataEditMenuIndexValue.Text = dataObject[dataSerializerRef.index[dataType]] --init value to show existing index
  491.         table.insert(dataEditMenuConnections,dataEditMenuIndexValue.FocusLost:Connect(function()
  492.             local text = dataEditMenuIndexValue.Text
  493.  
  494.             --//determine new index
  495.             local result = patternIndex and patternGroups[patternGroupIndex]:MovePattern(patternIndex,text) or updatePatternGroupIndex(patternGroupIndex,text)
  496.  
  497.             --//update ui to reflect result
  498.             dataEditMenuIndexValue.Text = result
  499.  
  500.             --//make sure this function is aware of change
  501.             resetDataEditMenuData()
  502.             openDataEditMenu(patternIndex and patternGroupIndex or result, patternIndex and result or nil)
  503.         end))
  504.  
  505.         dataEditMenuDoneButtonObject:SetState(true)
  506.  
  507.         dataEditMenuRemoveButtonObject.callback = function()
  508.             if patternIndex then --treat as pattern object
  509.                 patternGroups[patternGroupIndex]:RemovePattern(patternIndex)
  510.             else --treat as pattern group object
  511.                 removePatternGroup(patternGroupIndex)
  512.             end
  513.  
  514.             closeDataEditMenu()
  515.         end
  516.         dataEditMenuRemoveButtonObject:SetState(true)
  517.     end
  518.  
  519.     local function dispatchNodeMapUpcall(f,...)
  520.         patternNodeTree[f](patternNodeTree,...)--calling an oop function with . and passing self as param 1 to fake oop principles
  521.     end
  522.  
  523.     local function editNodeCallback(nodeLocation)
  524.         openDataEditMenu(nodeLocation[1],nodeLocation[2])
  525.     end
  526.  
  527.     local function nodeNameChangedCallback(nodeLocation,oldName,newName) --terrible practice.  shld just have both object inheret from a baseclass with a name property
  528.         local node = #nodeLocation==1 and patternGroups[nodeLocation[1]] or patternGroups[nodeLocation[1]]["patternObjects"][nodeLocation[2]]
  529.  
  530.         return node:ChangeName(newName)
  531.     end
  532.  
  533.     ---
  534.     ---below is column editor stuff
  535.     ---
  536.    
  537.     local function closeColumnEditor() --closes column editor
  538.         columnLightEditorBulbTypeDropdownObject.callback = nil
  539.         columnLightEditorFadeInDropdownObject.callback = nil
  540.         columnLightEditorFadeOutDropdownObject.callback = nil
  541.        
  542.         for _,v in columnEditorConnections do
  543.             v:Disconnect()
  544.         end
  545.         table.clear(columnEditorConnections)
  546.        
  547.         leftPanelColumnEditorContainer.Visible = false
  548.         columnEditorContent = nil
  549.     end
  550.     local function openColumnEditor(columnDataRef) --display this data in light column
  551.         if columnDataRef==columnEditorContent then
  552.             closeColumnEditor()
  553.             return
  554.         elseif columnEditorContent then
  555.             closeColumnEditor()
  556.         end
  557.        
  558.         leftPanelColumnEditorContainer.Visible = false
  559.         columnEditorContent = columnDataRef
  560.        
  561.         if columnDataRef._type==ezlsEnum.ClassType.LightColumnObject then  --if this is a light column.  Make another case for rotators
  562.             leftPanelColumnEditorContainer.LightEditor.LightColumnEditor.Visible = true
  563.             leftPanelColumnEditorContainer.LightEditor.RotatorColumnEditor.Visible = false
  564.            
  565.             leftPanelColumnEditorContainer.LightEditor.LightColumnEditor.Title.Text = #columnDataRef.columnName>0 and columnDataRef.columnName or "Unnamed Light"
  566.            
  567.             --Initialize UI
  568.             if columnDataRef.fadeData then
  569.                 columnLightEditorBulbTypeDropdownObject:UpdateSelection(2) --select halogen
  570.                 halogenOptions.Visible = true
  571.                
  572.                 columnLightEditorFadeInDropdownObject:UpdateSelection(table.find(fadeOptions,columnDataRef.fadeData.FadeInMethod))
  573.                 columnLightEditorFadeOutDropdownObject:UpdateSelection(table.find(fadeOptions,columnDataRef.fadeData.FadeOutMethod))
  574.                
  575.                 halogenOptions.FadeInTime.Field.Input.Text = columnDataRef.fadeData.FadeInTime
  576.                 halogenOptions.FadeOutTime.Field.Input.Text = columnDataRef.fadeData.FadeOutTime
  577.             else
  578.                 columnLightEditorBulbTypeDropdownObject:UpdateSelection(1) --select LED
  579.                 halogenOptions.Visible = false
  580.             end
  581.            
  582.             --Connect UI to backend data
  583.             columnLightEditorBulbTypeDropdownObject.callback = function(i)
  584.                 if i==1 then --LED
  585.                     halogenOptions.Visible = false
  586.                     columnDataRef.fadeData = nil
  587.                 elseif i==2 then --halogen
  588.                     halogenOptions.Visible = true
  589.                    
  590.                     columnDataRef.fadeData = {
  591.                         FadeInMethod="Quad",
  592.                         FadeInTime=.1,
  593.                         FadeOutMethod="Linear",
  594.                         FadeOutTime=.3,
  595.                     }
  596.                    
  597.                     halogenOptions.FadeInTime.Field.Input.Text = columnDataRef.fadeData.FadeInTime
  598.                     halogenOptions.FadeOutTime.Field.Input.Text = columnDataRef.fadeData.FadeOutTime
  599.                     columnLightEditorFadeInDropdownObject:UpdateSelection(table.find(fadeOptions,columnDataRef.fadeData.FadeInMethod))
  600.                     columnLightEditorFadeOutDropdownObject:UpdateSelection(table.find(fadeOptions,columnDataRef.fadeData.FadeOutMethod))
  601.                 end
  602.             end
  603.            
  604.             columnLightEditorFadeInDropdownObject.callback = function(i)
  605.                 columnDataRef.fadeData.FadeInMethod = fadeOptions[i]
  606.             end
  607.             table.insert(columnEditorConnections,halogenOptions.FadeInTime.Field.Input.FocusLost:Connect(function()
  608.                 local text = halogenOptions.FadeInTime.Field.Input.Text
  609.                 if tonumber(text) then
  610.                     columnDataRef.fadeData.FadeInTime = tonumber(text)
  611.                 else
  612.                     halogenOptions.FadeInTime.Field.Input.Text = columnDataRef.fadeData.FadeInTime --revert
  613.                 end
  614.             end))
  615.             columnLightEditorFadeOutDropdownObject.callback = function(i)
  616.                 columnDataRef.fadeData.FadeOutMethod = fadeOptions[i]
  617.             end
  618.             table.insert(columnEditorConnections,halogenOptions.FadeOutTime.Field.Input.FocusLost:Connect(function()
  619.                 local text = halogenOptions.FadeOutTime.Field.Input.Text
  620.                 if tonumber(text) then
  621.                     columnDataRef.fadeData.FadeOutTime = tonumber(text)
  622.                 else
  623.                     halogenOptions.FadeOutTime.Field.Input.Text = columnDataRef.fadeData.FadeOutTime --revert
  624.                 end
  625.             end))
  626.         end
  627.        
  628.         leftPanelColumnEditorContainer.Visible = true
  629.     end
  630.     local function updateColumnEditorProperty(columnRef,property,new) --update menu name if its changed while menu is open
  631.         if columnRef==columnEditorContent then
  632.             leftPanelColumnEditorContainer.LightEditor.LightColumnEditor.Title.Text = #new>0 and new or "Unnamed Light"
  633.         end
  634.     end
  635.     local function columnDeleted(columnRef) --column data is reference, check if its currently open. if so, close menu
  636.         if not columnEditorContent then return end
  637.         if columnRef==columnEditorContent._super then --cast to superclass bc columnRef comes in from the superclass
  638.             closeColumnEditor()
  639.         end
  640.     end
  641.  
  642.     ---
  643.     ---
  644.     ---
  645.  
  646.     local function upCall(f,...)
  647.         if f == "isOpen" then
  648.             return isOpen
  649.         elseif f == "isPlaying" then
  650.             return playing
  651.         elseif f == "syncPatterns" then
  652.             syncPatterns()
  653.         elseif f == "openDataEditMenu" then
  654.             openDataEditMenu(...)
  655.         elseif f == "nodeMap" then
  656.             dispatchNodeMapUpcall(...)
  657.         elseif f == "getCurrentColorIndex" then
  658.             return colorSelectorObject.selected
  659.         elseif f == "OpenColumnEditor" then
  660.             openColumnEditor(...)
  661.         elseif f == "UpdateColumnEditorProperty" then
  662.             updateColumnEditorProperty(...)
  663.         elseif f == "ColumnDeleted" then
  664.             columnDeleted(...)
  665.         end
  666.     end
  667.  
  668.     local function toWindow(i)
  669.         if i~=currentWindow then
  670.             local currentWindowData = windows[currentWindow]
  671.             local newWindowData = windows[i]
  672.  
  673.             if currentWindowData then
  674.                 for _,v in pairs(currentWindowData.containers) do
  675.                     v.Visible = false
  676.                 end
  677.                 coroutine.resume(coroutine.create(function() --wrap in thread and catch errors that may rise if plugin is destroyed while unloading (idk why this happens but its out of my control)
  678.                     currentWindowData.button:FindFirstChild("Selected").BackgroundColor3 = Color3.new(1,1,1)
  679.                     currentWindowData.button:FindFirstChild("Selected"):TweenSize(UDim2.new(0,0,0,1),Enum.EasingDirection.In,Enum.EasingStyle.Quad,.1,true,function()
  680.                         currentWindowData.button:FindFirstChild("Selected").Visible = false
  681.                     end)
  682.                 end))
  683.             end
  684.             if newWindowData then
  685.                 for _,v in pairs(newWindowData.containers) do
  686.                     v.Visible = true
  687.                 end
  688.                 coroutine.resume(coroutine.create(function()
  689.                     newWindowData.button:FindFirstChild("Selected").Visible = true
  690.                     newWindowData.button:FindFirstChild("Selected").BackgroundColor3 = Color3.new(1,1,1)
  691.                     newWindowData.button:FindFirstChild("Selected"):TweenSize(UDim2.new(.8,0,0,1),Enum.EasingDirection.In,Enum.EasingStyle.Quad,.1,true)
  692.                 end))
  693.             end
  694.  
  695.             currentWindow = i
  696.         end
  697.     end
  698.  
  699.     local function newLightGroup() --helper fucntion to cast new LG call down to active pattern object
  700.         loadedPattern:AddGroup("",true) --construct "default" data in this group to avoid undefined behavior
  701.     end
  702.  
  703.     local function colorSelectionChanged(newColorIndex)
  704.         local colorData = currentConfig.colorPallete[newColorIndex]
  705.         if not colorData then return end --if there is no color data at all somehow
  706.         colorSelectorTitle.Text = colorData[1]
  707.         colorSelectorContainer.BackgroundColor3 = colorData[2]
  708.     end
  709.  
  710.     local function initialize(tabWindow,tabIndex)
  711.         --//initialize objects
  712.         patternGroupObject = patternGroupObject(plugin,pluginBase,dock,requestClose,EasyLSpageCalback,upCall,pluginSettings.stressTestMode)
  713.  
  714.         --//init buttons
  715.         addGroupButtonObject = traditionalButton.new(plugin,addGroupButton,{},pluginSettings.normalMouseID,pluginSettings.buttonHoverID,{{addGroupButton,{ImageTransparency=0}}})
  716.         addGroupButtonObject.callback = newLightGroup
  717.  
  718.         playButtonObject = traditionalButton.new(plugin,playButton,{},pluginSettings.normalMouseID,pluginSettings.buttonHoverID,{})
  719.         playButtonObject.callback = playPatterns
  720.  
  721.         pauseButtonObject = traditionalButton.new(plugin,pauseButton,{},pluginSettings.normalMouseID,pluginSettings.buttonHoverID,{})
  722.         pauseButtonObject.callback = pausePatterns
  723.  
  724.         dataEditMenuDoneButtonObject = traditionalButton.new(plugin,dataEditMenuDoneButton,{TextColor3=Color3.new(1,1,1),BackgroundColor3=dataEditMenuDoneButton.TextColor3},pluginSettings.normalMouseID,pluginSettings.buttonHoverID,{})
  725.         dataEditMenuDoneButtonObject.callback = closeDataEditMenu
  726.  
  727.         dataEditMenuRemoveButtonObject = traditionalButton.new(plugin,dataEditMenuRemoveButton,{TextColor3=Color3.new(1,1,1),BackgroundColor3=dataEditMenuRemoveButton.TextColor3},pluginSettings.normalMouseID,pluginSettings.buttonHoverID,{})
  728.        
  729.         --//create pattern selector dropdown
  730.         patternSelectDropdownObject = traditionalDropdown.new(plugin,dock,patternSelectDropdown,pluginSettings.normalMouseID,pluginSettings.buttonHoverID)
  731.         patternSelectDropdownObject.callback = function(i)
  732.             loadPattern(accessPatternObjectFromMapIndex(i))
  733.         end
  734.  
  735.         --//column editor stuff
  736.         columnLightEditorBulbTypeDropdownObject = traditionalDropdown.new(plugin,dock,leftPanelColumnEditorContainer.LightEditor.LightColumnEditor.BulbType.BulbTypeDropdown,pluginSettings.normalMouseID,pluginSettings.buttonHoverID)
  737.         columnLightEditorBulbTypeDropdownObject:UpdateOptions({"LED","Halogen"})
  738.        
  739.         columnLightEditorFadeInDropdownObject = traditionalDropdown.new(plugin,dock,halogenOptions.FadeInMethod.DropdownContainer,pluginSettings.normalMouseID,pluginSettings.buttonHoverID)
  740.         columnLightEditorFadeInDropdownObject:UpdateOptions(fadeOptions)
  741.        
  742.         columnLightEditorFadeOutDropdownObject = traditionalDropdown.new(plugin,dock,halogenOptions.FadeOutMethod.DropdownContainer,pluginSettings.normalMouseID,pluginSettings.buttonHoverID)
  743.         columnLightEditorFadeOutDropdownObject:UpdateOptions(fadeOptions)
  744.        
  745.         columnEditorDoneButtonObject = traditionalButton.new(plugin,leftPanelColumnEditorContainer.Done,{TextColor3=Color3.new(1,1,1),BackgroundColor3=leftPanelColumnEditorContainer.Done.TextColor3},pluginSettings.normalMouseID,pluginSettings.buttonHoverID,{})
  746.         columnEditorDoneButtonObject.callback = closeColumnEditor
  747.        
  748.         --//create color selector
  749.         colorSelectorObject = traditionalSelector.new(colorSelectionChanged,colorSelectorLeftArrow,colorSelectorRightArrow)
  750.        
  751.         --//create pattern node tree for pattern edit menu
  752.         patternNodeTree = nodeTreeObject.new(groupsEditor,
  753.             {
  754.                 {
  755.                     defaultNodeName = "Car Name",
  756.  
  757.                     nodeNameChangedCallback = nil,
  758.  
  759.                     nodeButtons = {
  760.  
  761.                     },
  762.  
  763.                     addSubnodeFunctions = {
  764.                         canAdd = canAddPatternGroup,
  765.                         addCallback = newPatternGroup,
  766.                     },
  767.                 },
  768.                 {
  769.                     defaultNodeName = "New Pattern Group",
  770.  
  771.                     nodeNameChangedCallback = nodeNameChangedCallback,
  772.  
  773.                     nodeButtons = {
  774.                         {4370186570,editNodeCallback}
  775.                     },
  776.  
  777.                     addSubnodeFunctions = {
  778.                         canAdd = canAddNewPattern,
  779.                         addCallback = newPattern,
  780.                     },
  781.                 },
  782.                 {
  783.                     defaultNodeName = "New Pattern",
  784.  
  785.                     nodeNameChangedCallback = nodeNameChangedCallback,
  786.  
  787.                     nodeButtons = {
  788.                         {4370186570,editNodeCallback}
  789.                     },
  790.  
  791.                     addSubnodeFunctions = nil
  792.                 }
  793.             }
  794.         )
  795.        
  796.         --//Init keybind group
  797.         EasyLSpageCalback.keybindAPI.registerBindGroup("ELS",function() --function should return whether or not to display this bind group when keybinds page is opened
  798.             return EasyLSpageCalback.getTabState(tabIndex)
  799.         end)
  800.     end
  801.  
  802.     local function loadData(carObject,pageData) --recieves data once when a car is loaded into the editor, fills editor with cars data
  803.         clearData() --clear all existing data to load from a blank slate when a new car is selected
  804.        
  805.         if not pageData then warn("No page data") pageData = {} end
  806.        
  807.         patternNodeTree:RenameNode({},"ELS Controller")
  808.        
  809.         for patternGroupIndex,patternGroupData in pageData do
  810.             local pg = rawNewPatternGroup(patternGroupIndex,patternGroupData[1])
  811.             for patternIndex,patternData in patternGroupData[2] do
  812.                 local p = pg:RawNewPattern(patternIndex,patternData[1])
  813.                 for lightGroupIndex,lightGroupData in patternData[2] do
  814.                     local lg = p:AddGroup(lightGroupData[1])
  815.                     lg:RawUpdateTempo(lightGroupData[2])
  816.                     lg:RawUpdateSteps(lightGroupData[3])
  817.                     for columnIndex,columnData in lightGroupData[5] do
  818.                         if columnData[1]=="LightColumnObject" then
  819.                             local lc = lg:RawCreateLightColumn(columnData[2][1],columnData[2][3])
  820.                             --coloring lights depends on colorpallete of config file, so it is done below in linkData
  821.                         elseif columnData[1]=="SpacerObject" then
  822.                         elseif columnData[1]=="RotatorObject" then
  823.                         else
  824.                             warn("Unrecognized column type "..tostring(columnData[1]))
  825.                         end
  826.                     end
  827.                 end
  828.             end
  829.         end
  830.     end
  831.     local function linkData(carObject,pageData)
  832.         for patternGroupIndex,patternGroupData in pageData do
  833.             local pg = patternGroups[patternGroupIndex]
  834.             for patternIndex,patternData in patternGroupData[2] do
  835.                 local p = pg.patternObjects[patternIndex]
  836.                 for lightGroupIndex,lightGroupData in patternData[2] do
  837.                     local lg = p.lightGroups[lightGroupIndex]
  838.                     for columnIndex,columnData in lightGroupData[5] do
  839.                         if columnData[1]=="LightColumnObject" then
  840.                             local lc = lg.lightColumns[columnIndex]
  841.                             for rowIndex,rowColorIndex in columnData[2][2] do
  842.                                 if rowColorIndex==0 then continue end --row is uncolored
  843.                                 lc:HighlightLight(rowIndex,rowColorIndex)
  844.                             end
  845.                         elseif columnData[1]=="SpacerObject" then
  846.                         elseif columnData[1]=="RotatorObject" then
  847.                         else
  848.                             warn("Unrecognized column type "..tostring(columnData[1]))
  849.                         end
  850.                     end
  851.                 end
  852.             end
  853.         end
  854.        
  855.         if isOpen then
  856.             resumeData()
  857.         end
  858.         toWindow(1)
  859.     end
  860.  
  861.     local function validateAllLightNames()
  862.         for _, patternGroup in ipairs(patternGroups) do
  863.             for _, pattern in ipairs(patternGroup.patternObjects) do
  864.                 for _, lightGroup in ipairs(pattern.lightGroups) do
  865.                     for _, lightColumn in ipairs(lightGroup.lightColumns) do
  866.                         if lightColumn._type == ezlsEnum.ClassType.LightColumnObject then
  867.                             lightColumn:ValidateLightName()
  868.                         end
  869.                     end
  870.                 end
  871.             end
  872.         end
  873.     end
  874.  
  875.     local function onOpen()
  876.         --//Define page opening
  877.         local instanceID = newproxy()
  878.         isOpen = instanceID
  879.  
  880.         --//button connections
  881.         for windowIndex,windowData in pairs(windows) do
  882.             table.insert(pageConnections,windowData.button.MouseButton1Click:Connect(function()
  883.                 toWindow(windowIndex)
  884.             end))
  885.             table.insert(pageConnections,windowData.button.MouseEnter:Connect(function()
  886.                 plugin:GetMouse().Icon = pluginSettings.buttonHoverID
  887.                 if currentWindow ~= windowIndex then --dont highlight a tab thats selected
  888.                     windowData.button:FindFirstChild("Selected").BackgroundColor3 = Color3.new(.3,.3,.3)
  889.                     windowData.button:FindFirstChild("Selected").Visible = true
  890.                     windowData.button:FindFirstChild("Selected"):TweenSize(UDim2.new(.8,0,0,1),Enum.EasingDirection.In,Enum.EasingStyle.Quad,.1,true)
  891.                 end
  892.             end))
  893.             table.insert(pageConnections,windowData.button.MouseLeave:Connect(function()
  894.                 plugin:GetMouse().Icon = pluginSettings.normalMouseID
  895.                 if currentWindow ~= windowIndex then --dont unhighlight a tab thats selected
  896.                     windowData.button:FindFirstChild("Selected").BackgroundColor3 = Color3.new(.3,.3,.3)
  897.                     windowData.button:FindFirstChild("Selected"):TweenSize(UDim2.new(0,0,0,1),Enum.EasingDirection.In,Enum.EasingStyle.Quad,.1,true,function(completed)
  898.                         windowData.button:FindFirstChild("Selected").Visible = false
  899.                     end)
  900.                 end
  901.             end))
  902.         end
  903.  
  904.         --//resume objects
  905.         addGroupButtonObject:SetState(true)
  906.         patternSelectDropdownObject:SetState(true)
  907.         pauseButtonObject:SetState(true)
  908.         playButtonObject:SetState(true)
  909.         patternNodeTree:SetState(true)
  910.         colorSelectorObject:SetState(true)
  911.        
  912.         columnLightEditorBulbTypeDropdownObject:SetState(true)
  913.         columnLightEditorFadeInDropdownObject:SetState(true)
  914.         columnLightEditorFadeOutDropdownObject:SetState(true)
  915.         columnEditorDoneButtonObject:SetState(true)
  916.        
  917.         --//update color selector
  918.         currentConfig = EasyLSpageCalback.getConfig()
  919.         colorSelectorObject:SetOptions(currentConfig.colorPallete)
  920.  
  921.         --//resume data objects
  922.         resumeData()
  923.  
  924.         --//bind done button for column editor
  925.         table.insert(pageConnections,leftPanelColumnEditorContainer.Done.MouseButton1Click:Connect(closeColumnEditor))
  926.        
  927.         --//keybinds
  928.         primaryDCASHelper.DCAS:BindAction("Color_Forward",function()
  929.             colorSelectorObject:CycleForwards()
  930.         end,Enum.KeyCode.E,Enum.UserInputState.Begin)
  931.        
  932.         primaryDCASHelper.DCAS:BindAction("Color_Backward",function()
  933.             colorSelectorObject:CycleBackwards()
  934.         end,Enum.KeyCode.Q,Enum.UserInputState.Begin)
  935.        
  936.         --//validate light names
  937.         validateAllLightNames()
  938.        
  939.         --//tween menu border
  940.         task.defer(function()
  941.             while isOpen == instanceID do
  942.                 for i = 1,255,.25 do
  943.                     leftPanelBorder.BackgroundColor3 = Color3.fromHSV(i/255,1,1)
  944.                     task.wait()
  945.                 end
  946.             end
  947.         end)
  948.     end
  949.  
  950.     local function onClose()
  951.         --//Close page instance
  952.         isOpen = false
  953.  
  954.         for _,connection in pairs(pageConnections) do
  955.             connection:Disconnect()
  956.         end
  957.         table.clear(pageConnections)
  958.    
  959.         --//pause objects
  960.         addGroupButtonObject:SetState(false)
  961.         patternSelectDropdownObject:SetState(false)
  962.         pauseButtonObject:SetState(false)
  963.         playButtonObject:SetState(false)
  964.         patternNodeTree:SetState(false)
  965.         colorSelectorObject:SetState(false)
  966.         columnLightEditorBulbTypeDropdownObject:SetState(false)
  967.         columnLightEditorFadeInDropdownObject:SetState(false)
  968.         columnLightEditorFadeOutDropdownObject:SetState(false)
  969.         columnEditorDoneButtonObject:SetState(false)
  970.        
  971.         --//remove binds
  972.         primaryDCASHelper.DCAS:UnbindAction("Color_Forward")
  973.  
  974.         primaryDCASHelper.DCAS:UnbindAction("Color_Backward")
  975.        
  976.         --//close column editor
  977.         closeColumnEditor()
  978.    
  979.         --//pause data objects
  980.         pauseData()
  981.     end
  982.    
  983.     local function getCompilerData()
  984.         local data = {}
  985.        
  986.         for i,v in ipairs(patternGroups) do
  987.             data[i] = v:PullData()
  988.         end
  989.        
  990.         return data
  991.     end
  992.    
  993.     ------------
  994.     --//Core\\--
  995.     ------------
  996.  
  997.     local page = {}
  998.  
  999.     page.initialize = initialize
  1000.  
  1001.     page.loadData = loadData
  1002.     page.linkData = linkData
  1003.  
  1004.     page.onOpen = onOpen
  1005.     page.onClose = onClose
  1006.    
  1007.     page.getCompilerData = getCompilerData
  1008.    
  1009.     page.miscDirectory = miscDirectory
  1010.    
  1011.     return page
  1012. end
Advertisement
Add Comment
Please, Sign In to add comment