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


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