Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --//Rewrite of nodeTree which stores data by reference as opposed to by value
- return function(plugin,pluginBase,dock)
- ------------
- --//VARS\\--
- ------------
- --//constants
- local UITemplates = pluginBase:WaitForChild("Storage"):WaitForChild("Templates"):WaitForChild("NodeTree2")
- local pluginResource = pluginBase:WaitForChild("PluginCode"):WaitForChild("Core"):WaitForChild("Resource")
- local button2 = require(pluginResource:WaitForChild("OOP"):WaitForChild("Button2"))(plugin,pluginBase)
- local pluginConfig = require(pluginResource:WaitForChild("LocalSettings"))
- local contentObjects = {} --contentobjectName=contentobject
- for _,v in script:WaitForChild("ContentTypes"):GetChildren() do --populate
- contentObjects[v.Name] = require(v)(plugin,pluginBase,dock)
- end
- -----------------
- --//FUNCTIONS\\--
- -----------------
- --//A lot of functions that are implemented in both tree and node are defined here, for consistency
- local function getSubnode(self,subn)
- if type(subn)=="number" then --subnode is index
- return self.subnodes[subn]
- elseif table.find(self.subnodes,subn) then --subnode is the actual node
- return subn
- else --subn may be nodes data
- for _,v in self.subnodes do
- if v.data==subn then
- return v
- end
- end
- end
- end
- local function removeNode(node,parentNode) --node to be removed, parentNode?.
- --disconnect this branch from parent node
- local subnodesTable = parentNode and parentNode.subnodes or node.parentNode.subnodes
- table.remove(subnodesTable,table.find(subnodesTable,node))
- --clean node
- node:SetState(false) --remove all connections of this
- node:PrepareCleanup() --call :Delete on all add button objects
- node.UIInstance:Destroy() --destroy UI
- table.clear(node) --not strictly necessary, but helpful for debugging so if something is holding a stale reference to this node it will likley error.
- end
- local function removeSubnode(self,subn)
- local subn = getSubnode(self,subn)
- removeNode(subn,self)
- return subn
- end
- -----------
- --//OOP\\--
- -----------
- --//OOP FOR NODE, NOT ROOT THOUGH. SEE <TREE> BELOW FOR ROOT
- local node2 = {}
- --nodeData is the data object this node corresponds to, implements __tostring if this is userdata
- --parent node is the parent node data instance, or the root
- --parent frame is where this node gets parented to
- --contents table describes what UI elements we want in this node, array of {name,...} where ... is passed to the content object constructor
- --add function is the function that gets called when the add button is clicked, or nil if we dont want an add button
- function node2.new(nodeData,rootNode,parentNode,parentFrame,contentsTable,addFunction)
- local self = setmetatable({},{__index=node2,
- __iter = function(t)
- return next,t.subnodes
- end
- })
- self.data = nodeData --data object this node correlates to. Should implement __tostring for display name
- self.rootNode = rootNode --points to root node instance
- self.parentNode = parentNode --points to parent node
- self.depth = parentNode.depth+1 --0 correspsonds to root node, each level down increases by 1. this is the depth of THIS node
- self.subnodes = {} --ordered array of subnodes
- self.contents = {} --Array of {contentObject}
- self.state = parentNode.state
- self.addFunction = addFunction
- self.addButton = nil --defined as button object in the case we have an addFunction
- self.UIInstance = self:Construct(parentNode,parentFrame,contentsTable)
- return self
- end
- function node2:Construct(parentNode,parentFrame,contentsTable) --constructs this node's UI
- local node = UITemplates.Node:Clone()
- --Construct node contents
- for _,contentData in ipairs(contentsTable) do
- local contentObject = contentObjects[contentData[1]]
- contentData = table.clone(contentData)
- table.remove(contentData,1) --remove name, leaving constructor data
- table.insert(self.contents,contentObject.new(self,node.Contents,unpack(contentData))) --provide content data to content object, after base data
- end
- --Add add button under this node, if applicable
- if self.addFunction then
- node.ChildrenContainer.Visible = true --show drop bar
- local addContainer = UITemplates.AddContainer:Clone()
- local addButtonObject = button2.new(addContainer.AddButton,"TraditionalBlue")
- addButtonObject.MouseButton1Click:Connect(function()
- self.addFunction(self)
- end)
- self.addButton = addButtonObject
- addContainer.Parent = node.ChildrenContainer.ChildNodes
- end
- node.LayoutOrder = #parentNode.subnodes
- node.Parent = parentFrame
- return node
- end
- --//Where nodeData is the data this node represents
- --//Node contents are the elemets that display in this node, and their corresponding data
- --//Add data is the function that is called when we add a subnode, or nil if we dont want the user to have that button
- function node2:AddSubnode(nodeData,nodeContents,addData)
- self.UIInstance.ChildrenContainer.Visible = true --make sure you can see children being added
- local new = node2.new(nodeData,self.rootNode,self,self.UIInstance.ChildrenContainer.ChildNodes,nodeContents)
- table.insert(self.subnodes,new)
- return new
- end
- function node2:RemoveSubnode(subn) --Funds subnode subn from children nodes, and removes it with its descendants. Subn can be an index, or value of subn's data, or subn itself
- return removeSubnode(self,subn)
- end
- function node2:Remove() --removes this node
- return removeNode(self)
- end
- function node2:GetSubnode(subn) --subnode can be an index, or value of node.data
- return getSubnode(self,subn)
- end
- function node2:PrepareCleanup() --removes all add buttons before :Destroy is called
- for _,v in self.subnodes do
- v:PrepareCleanup()
- end
- if self.addButton then
- self.addButton:Destroy()
- end
- end
- function node2:SetState(s)
- self.state = s
- if self.addButton then --reset button on open and close
- self.addButton:Unhighlight()
- end
- for _,v in self.subnodes do
- v:SetState(s)
- end
- end
- ----
- --//OOP FOR TREE (AKA, THE ROOT)
- ----
- local tree = {}
- --parentFrame is frame the tree will be parented to
- --addFunction is nil if we do not want users to have an add button under this.
- --Otherwise, its the functiont that will be called when a user clicks addNode
- function tree.new(parentFrame,addFunction)
- local self = setmetatable({},{__index=tree,
- __iter = function(t)
- return next,t.subnodes
- end
- })
- self.depth = 0
- self.subnodes = {}
- self.addFunction = addFunction
- self.addButton = nil
- self.UIInstance = self:Construct(parentFrame)
- return self
- end
- function tree:Construct(parentFrame)
- local treeContainer = UITemplates.Tree:Clone()
- if self.addFunction then
- local addContainer = UITemplates.AddContainer:Clone()
- local addButtonObject = button2.new(addContainer.AddButton,"TraditionalBlue")
- addButtonObject.MouseButton1Click:Connect(function()
- self.addFunction(self)
- end)
- self.addButton = addButtonObject
- addContainer.Parent = treeContainer
- end
- treeContainer.Parent = parentFrame
- return treeContainer
- end
- function tree:AddSubnode(nodeData,nodeContents,addFunction)
- local new = node2.new(nodeData,self,self,self.UIInstance,nodeContents,addFunction)
- table.insert(self.subnodes,new)
- return new
- end
- function tree:GetSubnode(subn) --subnode can be an index, or value of node.data
- return getSubnode(self,subn)
- end
- function tree:RemoveSubnode(subn)
- return removeSubnode(self,subn)
- end
- function tree:ClearAllData() --deletes all descending nodes, resetting the tree
- while #self.subnodes>0 do
- removeNode(self.subnodes[1],self) --eliminate overhead by directly calling removenode. even better would be to just clean them all then clear the table.
- end
- end
- function tree:Destroy() --Deletes the entire tree, and all descending nodes, for cleanup
- self:ClearAllData()
- self:SetState(false) --remove all connections
- self.UIInstance:Destroy()
- end
- function tree:SetState(s)
- self.state = s
- for _,v in self.subnodes do
- v:SetState(s)
- end
- end
- return tree
- end
Advertisement
Add Comment
Please, Sign In to add comment