Set Position Based On Color

Currently I have a color wheel script, it returns the HSV of whatever the color picker is hovering over.

I want to move the color picker based on a predefined color, so if i wanted to position it to hover over a different color i would just type the hex or rgb.

devforum

This is the code im using to position the color picker based on mouse position:

function UpdateColor(colourWheel, darknessPicker, darknessSlider, centreOfWheel)
	
	local colourPickerCentre = Vector2.new(
		colourWheel.Picker.AbsolutePosition.X + (colourWheel.Picker.AbsoluteSize.X/2),
		colourWheel.Picker.AbsolutePosition.Y + (colourWheel.Picker.AbsoluteSize.Y/2)
	)
	local h = (math.pi - math.atan2(colourPickerCentre.Y - centreOfWheel.Y, colourPickerCentre.X - centreOfWheel.X)) / (math.pi * 2)

	local s = (centreOfWheel - colourPickerCentre).Magnitude / (colourWheel.AbsoluteSize.X/2)

	local v = math.abs((darknessSlider.AbsolutePosition.Y - darknessPicker.AbsolutePosition.Y) / darknessPicker.AbsoluteSize.Y - 1)

	local hsv = Color3.fromHSV(math.clamp(h, 0, 1), math.clamp(s, 0, 1), math.clamp(v, 0, 1))

	darknessPicker.UIGradient.Color = ColorSequence.new{
		ColorSequenceKeypoint.new(0, Color3.fromHSV(math.clamp(h, 0, 1),1,1)), 
		ColorSequenceKeypoint.new(1, Color3.new(0, 0, 0))
	}
	
	return hsv
end

function module.movePicker(wheelPicker, colourWheel, darknessSlider, darknessPicker, buttonDown, movingSlider)

	local mousePos = uis:GetMouseLocation() - Vector2.new(0, game:GetService("GuiService"):GetGuiInset().Y)

	local centreOfWheel = Vector2.new(colourWheel.AbsolutePosition.X + (colourWheel.AbsoluteSize.X/2), colourWheel.AbsolutePosition.Y + (colourWheel.AbsoluteSize.Y/2))

	local distanceFromWheel = (mousePos - centreOfWheel).Magnitude

	if distanceFromWheel <= colourWheel.AbsoluteSize.X/2 and buttonDown then

		wheelPicker.Position = UDim2.new(0, mousePos.X - colourWheel.AbsolutePosition.X, 0, mousePos.Y - colourWheel.AbsolutePosition.Y)

	elseif movingSlider then

		darknessSlider.Position = UDim2.new(darknessSlider.Position.X.Scale, 0, 0, 
			math.clamp(
				mousePos.Y - darknessPicker.AbsolutePosition.Y, 
				0, 
				darknessPicker.AbsoluteSize.Y)
		)	
	end

	local hsv = UpdateColor(colourWheel, darknessPicker, darknessSlider, centreOfWheel)
	return hsv
end
2 Likes

Give this a go. the sin and cos may need to be swapped, and you may need to add or subtract math.pi/2 to get it where you want it.

local temp_distance = s * colourWheel.AbsoluteSize.X / 2
local positionX = math.sin(h) * temp_distance + centreOfWheel.X
local positionY = math.cos(h) * temp_distance + centreOfWheel.Y
local positionValueY = darknessPicker.AbsolutePosition.Y + darknessPicker.AbsoluteSize.Y * (v + 1)
1 Like

One way to do this would be to iterate over all possible positions on the color wheel and the darkness slider and calculate the resulting color for each position. You can then compare the resulting colors to the desired color and set the position of the color picker and the darkness slider to the position that produces the closest match.

Here’s an example of how you could modify the UpdateColor function to set the position based on the color:

function SetPositionFromColor(colourWheel, darknessPicker, darknessSlider, centreOfWheel, color)
    local closestDistance = math.huge
    local closestColourPickerCentre = nil
    local closestDarknessPickerPosition = nil
    
    for i = 0, 1, 0.01 do
        for j = 0, 1, 0.01 do
            local colourPickerCentre = Vector2.new(
                colourWheel.AbsolutePosition.X + i * colourWheel.AbsoluteSize.X,
                colourWheel.AbsolutePosition.Y + j * colourWheel.AbsoluteSize.Y
            )
            local h = (math.pi - math.atan2(colourPickerCentre.Y - centreOfWheel.Y, colourPickerCentre.X - centreOfWheel.X)) / (math.pi * 2)
            local s = (centreOfWheel - colourPickerCentre).Magnitude / (colourWheel.AbsoluteSize.X/2)
            local v = math.abs((darknessSlider.AbsolutePosition.Y - darknessPicker.AbsolutePosition.Y) / darknessPicker.AbsoluteSize.Y - 1)
            local hsv = Color3.fromHSV(h, s, v)
            local distance = (hsv - color).Magnitude
            if distance < closestDistance then
                closestDistance = distance
                closestColourPickerCentre = colourPickerCentre
                closestDarknessPickerPosition = UDim2.new(
                    darknessSlider.Position.X.Scale, 0,
                    0, darknessPicker.AbsolutePosition.Y + (1 - v) * darknessPicker.AbsoluteSize.Y
                )
            end
        end
    end
    
    local hsv = Color3.fromRGB(math.clamp(h, 0, 1), math.clamp(s, 0, 1), math.clamp(v, 0, 1))
    colourWheel.Picker.Position = UDim2.new(
        0, closestColourPickerCentre.X - colourWheel.AbsolutePosition.X - colourWheel.Picker.AbsoluteSize.X/2,
        0, closestColourPickerCentre.Y - colourWheel.AbsolutePosition.Y - colourWheel.Picker.AbsoluteSize.Y/2
    )
    darknessSlider.Position = closestDarknessPickerPosition
    
    return hsv
end

It iterates over all possible positions on the color wheel and the darkness slider and calculates the resulting color for each position. It then finds the position that produces the closest match to the desired color and sets the position of the color picker and the darkness slider accordingly. Finally, it returns the resulting color.
Note that this approach can be computationally expensive, especially for large color spaces, so you may want to optimize it or use a different approach depending on your specific use case.

1 Like

Just tried this equation, as well as a few different versions, nothing seems to make it work properly.

this is my code:

	local h, s, v = color:ToHSV()
	
	local centreOfWheel = Vector2.new(colourWheel.AbsolutePosition.X + (colourWheel.AbsoluteSize.X/2), colourWheel.AbsolutePosition.Y + (colourWheel.AbsoluteSize.Y/2))
	local temp_distance = s * colourWheel.AbsoluteSize.X / 2
	
	local positionX = math.sin(h) * temp_distance
	local positionY = math.cos(h) * temp_distance
	
	wheelPicker.Position = UDim2.new(0, positionX, 0, positionY)

I removed the + centreOfWheel.X and + centreOfWheel.Y since the color picker is parented to the color wheel, so its position doesn’t need to be accounted for.

The slider shows what the color should be

3 Likes

Yeah I goofed.
Multiply h by 2*math.pi and see if that’s any better.
As far as the position stuff goes, I was lazily reversing the code you had, so it came out more literal than it should have.

2 Likes

Thanks for all the help!
the solution wasnt exactly this but it got me on the right track, this was the final code:

	local h, s, v = color:ToHSV()
	local radH = (h * 360) - 90 -- Change Hue to degree
	
	local centreOfWheel = Vector2.new(colourWheel.AbsoluteSize.X/2, colourWheel.AbsoluteSize.Y/2)
	local temp_distance = s * colourWheel.AbsoluteSize.X / 2 -- Distance from wheel center
	
	local positionX = centreOfWheel.X + temp_distance * math.sin(math.rad(radH))
	local positionY = centreOfWheel.Y + temp_distance * math.cos(math.rad(radH))
	
	wheelPicker.Position = UDim2.new(0, positionX, 0, positionY)

	-- Darkness Slider

	local positionValueY = darknessPicker.AbsoluteSize.Y * (1-v)
	
	darknessSlider.Position = UDim2.new(.5, 0, 0, positionValueY)
4 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.