I should’ve been a little more specific with my last post. How do I search through the children of children?
how do I get the descendants, and how do I compare them?
right now I have two similar things
this is for a theme system I am trying to write, kind of similar to the one arsenal uses. my issue is I need to figure out how to go through all the descendants of one and find the other’s counterpart, then apply the set values in the folders of one into the values of the UI. I thought about using GetDescendants() and FindFirstDescendant(), but unfortunately I get an error that is confusing, saying that it’s not enabled. please help
I’m not sure which parts you are trying to differentiate, but you can use v:IsA() to identify if the object iterated is the specified classname. For example, if you wanted test to see if a object iterated had the name of “Main” and was a folder, you could do:
for i,v in ipairs(object:GetDescendants()) do
if v:IsA('Folder') and v.Name == 'Main' then
-- do stuff here
end
end
I meant to find the counterpart of one descending group of things. for example, if I get the canvas group folder, it should try to find the canvas group UI and then set the UI color to the color specified in the folder
Ah, I see what you mean. Instead of using GetDescendants(), do a nested for loop using GetChildren(). For example, do a for loop in the main directory and get the children of which I assume would have all your folders and GUI’s, etc. Then check if the name of object is “CanvasGroup” and if it is, do another for loop with GetChildren. If you have different types of UI instances in the folder, you can use :IsA().
for i,v in ipairs(maindir:GetChildren()) do
if v.Name == "CanvasGroup" and v:IsA('Folder') then
for t,k in ipairs(v:GetChildren()) do
-- do stuff
end
end
end
There are likely better ways depending on exactly what you need done, but you could do something like this
local uiRoot = Customization --set this to the path of the ui "Customization"
local folderRoot = Customization --set this to the path of the folder "Customization"
local function myCode(ui, folder) --put whatever code you want in this function. Those 2 variables will match. You need to check that it's an item you want first
--code here
print(ui:GetFullName())
print(folder:GetFullName())
print("---------------------------------------") --This example just prints the names to show that they match in different locations. (though I don't have studio installed atm, so I can't test, but I can't see a reason it wouldn't work
end
local function matchRecursive(ui, folder)
if ui:GetChildren() and folder:GetChildren() then
for _, item in pairs(ui:GetChildren()) do
if folder:FindFirstChild(item.Name) then
matchRecursive(item, folder[item.Name])
end
end
end
myCode(ui, folder)
end
matchRecursive(uiRoot, folderRoot)
The myCode function is set up to be called for every match. It’s like that function is connected to a getDescendants loop. So just run whatever code in there.
I can’t seem to get it to work, and I am assuming that the “matchLoop” is a mistake meant to be matchRecursive since it is underlined in red and left as an undefined function, and the names seem similar enough, but even after changing that I can’t seem to get it to print anything more than the first UI and folder objects. also I noticed that it’s checking the UI for a name that matches the folders, but I am trying to check for UI that matches the name of the folders so I changed that too.
local uiRoot = script.RootUI --set this to the path of the ui "Customization"
local folderRoot = script.Theme.Value.UIOverrides.Customization --set this to the path of the folder "Customization"
local colors = folderRoot:WaitForChild("Colors", 5)
local UIOverrides = folderRoot:WaitForChild("UIOverrides", 5)
local function myCode(ui, folder) --put whatever code you want in this function. Those 2 variables will match. You need to check that it's an item you want first
--code here
print(ui:GetFullName())
print(folder:GetFullName())
print("---------------------------------------") --This example just prints the names to show that they match in different locations. (though I don't have studio installed atm, so I can't test, but I can't see a reason it wouldn't work
local StringVal = folder:FindFirstChildWhichIsA("StringValue")
if folder:FindFirstChildWhichIsA("StringValue") then
if StringVal.Name == "BackgroundColor3" then
ui.BackgroundColor3 = colors:FindFirstChild(StringVal.Value).Value
end
end
end
local function matchRecursive(ui, folder)
if ui:GetChildren() and folder:GetChildren() then
for _, item in pairs(ui:GetChildren()) do
if folder:FindFirstChild(item.Name) then
matchRecursive(item, folder[item.Name])
end
end
end
myCode(ui, folder)
end
matchRecursive(uiRoot, folderRoot)
local Names = {}
for i,v in pairs (path:GetDescendants()) do
if not table.find(Names,v.Name) then
table.insert(Names,v.Name)
else
-- do code you want to do
end
I’d need to make a ton of different attributes then + I’d still need to figure out the script to “match” descendants
based on what I’m seeing, that checks and stores names, I don’t think that would try to match one group of descendants to another
that would be checking specifically for a folder named canvas group, then get it’s children. what I’m looking for is to “match” an item to another of the same name in a similar line of descendants.
then in each theme I set what thing has what individual color (I don’t set a value for it to pick a color in the color folder from in the UI itself because then it can allow me to have more control over the UI themes)
Let me start off by saying that this is a really complex way of doing something really simple. You could keep each theme having different colors but use Attributes on your UI Elements to tell the script to apply specific properties to specific colors. This avoids the folder being extremely huge as you shown here.
But, I found a very quick method of doing this with a couple of things I made assumptions for
The values in each folder that represents UI isn’t a ‘Color3Value’, I seen that you were explaining that those are assigned to the 9 colors that each theme has, so I treat them as ‘StringValues’ instead.
A UI element can have the same name as another inside of the ancestor, so we can’t use GetDescendants because we can add a lot of confusion to the game engine and it might assign colors incorrectly when we try to get it’s counterpart.
I solve this by working recursively so I can pair an object in the theme’s UIOverride folder to an actual UI element.
This code should work just fine:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
local themes = ReplicatedStorage.Themes
local theme = themes.Default --> This would be different by what theme they choose
local uiOverrides = theme.Overrides
local uiColors = theme.Colors
local function ApplyTheme(currentThemeFolder, currentGui)
for _, child in pairs(currentThemeFolder:GetChildren()) do
if child:IsA("Folder") then
ApplyTheme(child, currentGui[child.Name])
elseif child:IsA("ValueBase") then
local colorName = child.Value
local colorValue = uiColors[colorName].Value
currentGui[child.Name] = colorValue
end
end
end
ApplyTheme(uiOverrides, playerGui)
I worked on fixing your problem in this place and I’ve attached it to this message if you want to see it in action. ThemesExample.rbxl (38.5 KB)