local Z={}Z.default=function(Z,q,C)local A=q.Name local G=q.ValueType local k=CreateTextBox(C)k.Size=UDim2.new(1,-2*Styles.Margin,1,0)k.Position=UDim2.new(0,Styles.Margin,0,0)local function u()local q=Z[A]k.Text=ToString(q,G.Name)end if not C then k.FocusLost:connect(function(C)Set(Z,q,ToValue(k.Text,G.Name))u()end)end u()Z.Changed:connect(function(Z)if Z==A then u()end end)return k end Z.bool=function(Z,q,C)local A=q.Name local G=Z[A]local k,u=CreateCheckbox(G,C,function(C)Set(Z,q,not G)end)k.Position=UDim2.new(0,Styles.Margin,0,Styles.Margin)u(G)local function c()G=Z[A]u(G)end Z.Changed:connect(function(Z)if Z==A then c()end end)if Z:IsA("\066\111\111\108\086\097\108\117\101")then Z.Changed:connect(function(Z)c()end)end c()return k end Z.BrickColor=function(Z,q,C)local A=q.Name local G,k,u=CreateBrickColor(C,function(C)Set(Z,q,C)end)local function c()local q=Z[A]u.BackgroundColor3=q.Color k.Text=tostring(q)end c()Z.Changed:connect(function(Z)if Z==A then c()end end)return G end Z.Color3=function(Z,q,C)local A=q.Name local G,k,u=CreateColor3Control(C)k.FocusLost:connect(function(C)Set(Z,q,ToValue(k.Text,"\067\111\108\111\114\051"))local G=Z[A]u.BackgroundColor3=G k.Text=ToString(G,"\067\111\108\111\114\051")end)local function c()local q=Z[A]u.BackgroundColor3=q k.Text=ToString(q,"\067\111\108\111\114\051")end c()Z.Changed:connect(function(Z)if Z==A then c()end end)return G end Z.Enum=function(Z,q,C)local A=q.Name local G=q.ValueType local k=Z[A].Name local u={}for Z,q in pairs(Enum[tostring(G.Name)]:GetEnumItems())do table.insert(u,q.Name)end local c,b=CreateDropDown(u,k,C,function(C)Set(Z,q,C)end)local function W()local q=Z[A].Name b.Text=tostring(q)end W()Z.Changed:connect(function(Z)if Z==A then W()end end)return c end Z.Object=function(Z,q,C)local A=q.Name local G=q.ValueType local k=CreateObject(C,function() end)k.Size=UDim2.new(1,-2*Styles.Margin,1,0)k.Position=UDim2.new(0,Styles.Margin,0,0)local function u()if AwaitingObjectObj==Z then if AwaitingObjectValue==true then k.Text="\083\101\108\101\099\116 \097\110 \079\098\106\101\099\116"return end end local q=Z[A]k.Text=ToString(q,G.Name)end if not C then k.MouseButton1Click:connect(function()if AwaitingObjectValue then AwaitingObjectValue=false u()return end AwaitingObjectValue=true AwaitingObjectObj=Z AwaitingObjectProp=q k.Text="\083\101\108\101\099\116 \097\110 \079\098\106\101\099\116"end)k.Cancel.Visible=true k.Cancel.MouseButton1Click:connect(function()Z[A]=nil end)end u()Z.Changed:connect(function(Z)if Z==A then u()end end)if Z:IsA("\079\098\106\101\099\116\086\097\108\117\101")then Z.Changed:connect(function(Z)u()end)end return k end function GetControl(q,C,A)local G=C.ValueType local k=nil if G.Category=="\069\110\117\109"and RbxApi.Enums[G.Name]then k=Z.Enum(q,C,A)elseif G.Category=="\067\108\097\115\115"and RbxApi.Classes[G.Name]then k=Z.Object(q,C,A)elseif Z[G.Name]then k=Z[G.Name](q,C,A)else k=Z.default(q,C,A)end return k end
-- Code for handling controls of various data types --

local Controls = {}

Controls["default"] = function(object, propertyData, readOnly)
	local propertyName = propertyData["Name"]
	local propertyType = propertyData["ValueType"]

	local box = CreateTextBox(readOnly)
	box.Size = UDim2.new(1, -2 * Styles.Margin, 1, 0)
	box.Position = UDim2.new(0, Styles.Margin, 0, 0)

	local function update()
		local value = object[propertyName]
		box.Text = ToString(value, propertyType.Name)
	end

	if not readOnly then
		box.FocusLost:connect(function(enterPressed)
			Set(object, propertyData, ToValue(box.Text, propertyType.Name))
			update()
		end)
	end

	update()

	object.Changed:connect(function(property)
		if property == propertyName then
			update()
		end
	end)

	return box
end

Controls["bool"] = function(object, propertyData, readOnly)
	local propertyName = propertyData["Name"]
	local checked = object[propertyName]

	local checkbox, setValue = CreateCheckbox(checked, readOnly, function(value)
		Set(object, propertyData, not checked)
	end)
	checkbox.Position = UDim2.new(0, Styles.Margin, 0, Styles.Margin)

	setValue(checked)

	local function update()
		checked = object[propertyName]
		setValue(checked)
	end

	object.Changed:connect(function(property)
		if property == propertyName then
			update()
		end
	end)

	if object:IsA("BoolValue") then
		object.Changed:connect(function(val)
			update()
		end)
	end

	update()

	return checkbox
end

Controls["BrickColor"] = function(object, propertyData, readOnly)
	local propertyName = propertyData["Name"]

	local frame, label, brickColorBox = CreateBrickColor(readOnly, function(brickColor)
		Set(object, propertyData, brickColor)
	end)

	local function update()
		local value = object[propertyName]
		brickColorBox.BackgroundColor3 = value.Color
		label.Text = tostring(value)
	end

	update()

	object.Changed:connect(function(property)
		if property == propertyName then
			update()
		end
	end)

	return frame
end

Controls["Color3"] = function(object, propertyData, readOnly)
	local propertyName = propertyData["Name"]

	local frame, textBox, colorBox = CreateColor3Control(readOnly)

	textBox.FocusLost:connect(function(enterPressed)
		Set(object, propertyData, ToValue(textBox.Text, "Color3"))
		local value = object[propertyName]
		colorBox.BackgroundColor3 = value
		textBox.Text = ToString(value, "Color3")
	end)

	local function update()
		local value = object[propertyName]
		colorBox.BackgroundColor3 = value
		textBox.Text = ToString(value, "Color3")
	end

	update()

	object.Changed:connect(function(property)
		if property == propertyName then
			update()
		end
	end)

	return frame
end

Controls["Enum"] = function(object, propertyData, readOnly)
	local propertyName = propertyData["Name"]
	local propertyType = propertyData["ValueType"]

	local enumName = object[propertyName].Name

	local enumNames = {}
	for _, enum in pairs(Enum[tostring(propertyType.Name)]:GetEnumItems()) do
		table.insert(enumNames, enum.Name)
	end

	local dropdown, propertyLabel = CreateDropDown(enumNames, enumName, readOnly, function(value)
		Set(object, propertyData, value)
	end)
	--dropdown.Parent = frame

	local function update()
		local value = object[propertyName].Name
		propertyLabel.Text = tostring(value)
	end

	update()

	object.Changed:connect(function(property)
		if property == propertyName then
			update()
		end
	end)

	return dropdown
end

Controls["Object"] = function(object, propertyData, readOnly)
	local propertyName = propertyData["Name"]
	local propertyType = propertyData["ValueType"]

	local box = CreateObject(readOnly, function() end)
	box.Size = UDim2.new(1, -2 * Styles.Margin, 1, 0)
	box.Position = UDim2.new(0, Styles.Margin, 0, 0)

	local function update()
		if AwaitingObjectObj == object then
			if AwaitingObjectValue == true then
				box.Text = "Select an Object"
				return
			end
		end
		local value = object[propertyName]
		box.Text = ToString(value, propertyType.Name)
	end

	if not readOnly then
		box.MouseButton1Click:connect(function()
			if AwaitingObjectValue then
				AwaitingObjectValue = false
				update()
				return
			end
			AwaitingObjectValue = true
			AwaitingObjectObj = object
			AwaitingObjectProp = propertyData
			box.Text = "Select an Object"
		end)

		box.Cancel.Visible = true
		box.Cancel.MouseButton1Click:connect(function()
			object[propertyName] = nil
		end)
	end

	update()

	object.Changed:connect(function(property)
		if property == propertyName then
			update()
		end
	end)

	if object:IsA("ObjectValue") then
		object.Changed:connect(function(val)
			update()
		end)
	end

	return box
end

function GetControl(object, propertyData, readOnly)
	local propertyType = propertyData["ValueType"]
	local control = nil

	if propertyType.Category == "Enum" and RbxApi.Enums[propertyType.Name] then
		control = Controls["Enum"](object, propertyData, readOnly)
	elseif propertyType.Category == "Class" and RbxApi.Classes[propertyType.Name] then
		control = Controls["Object"](object, propertyData, readOnly)
	elseif Controls[propertyType.Name] then
		control = Controls[propertyType.Name](object, propertyData, readOnly)
	else
		control = Controls["default"](object, propertyData, readOnly)
	end
	return control
end
