Народ у меня есть slider в проекте который двигает другого но вроде не должен.
Это часть кода который работает когда нажимаю на slider -
public void ChangeValue()
{
float h, s, v;
Color.RGBToHSV(GetNewColor(), out h, out s, out v);
Color color = Color.HSVToRGB(h, s, ValueSlider.value);
SetColor(color);
}
В нём есть функция SetColor которая получает Color32 и меняет позицию кнопки в цветном круге -
public void SetColor(Color32 color32)
{
float hue, saturation, value;
float transparence;
float rotation, distance;
Color.RGBToHSV(color32, out hue, out saturation, out value);
transparence = color32.a;
rotation = hue * 360 * Mathf.Deg2Rad;
distance = saturation * maxDistance;
Knob.transform.position = new Vector2(Center.x + distance * Mathf.Sin(rotation), Center.y + distance * Mathf.Cos(rotation));
TransparenceSlider.value = transparence / 255;
NewColor = color32;
NewColorImage.color = color32;
}
Как вы видите сверху переменная Value вообще не влияет на Knob.transform.position он только для того чтобы можно было использовать функцию Color.RGBToHSV.
И ещё это может понадобиться -
Center = ColorsRawImage.transform.position;
maxDistance = ColorsRawImage.GetComponent<RectTransform>().rect.width / 2;
Мне надо любым образом решить проблему с Slider-ом.
P.S. Если что-то ещё будет нужно скажите я добавлю.
Вот полный скрипт если нужно -
public RawImage ColorsRawImage;
Texture2D ColorsTexture;
public Image Knob;
public Image SelectedColorImage, NewColorImage;
public Slider ValueSlider, TransparenceSlider;
float maxDistance;
bool onCanvas;
Vector2 Center;
Color32 SelectedColor, NewColor;
[Header("Main")]
public Image OpenButton;
/* ==================================== Start =====================================*/
private void Start()
{
/* ==================================== Colors Texture =====================================*/
ColorsTexture = new Texture2D(399, 399)
{
filterMode = FilterMode.Point
};
ColorsRawImage.texture = ColorsTexture;
maxDistance = ColorsRawImage.GetComponent<RectTransform>().rect.width / 2;
Vector2Int CenterInt = new Vector2Int(ColorsTexture.width / 2 + 1, ColorsTexture.height / 2 + 1);
Center = ColorsRawImage.transform.position;
for (int y = 0; y < ColorsTexture.height; y++)
{
for (int x = 0; x < ColorsTexture.width; x++)
{
ColorsTexture.SetPixel(x, y, Color.white);
}
}
int maxRadius = ColorsTexture.width / 2;
for (float radius = 0; radius <= maxRadius; radius++)
{
for (float angle = 0; angle <= 360; angle += 0.1f)
{
int x = (int)(CenterInt.x + radius * Mathf.Sin(angle * Mathf.Deg2Rad));
int y = (int)(CenterInt.y + radius * Mathf.Cos(angle * Mathf.Deg2Rad));
Color color = Color.HSVToRGB(angle / 360, radius / maxRadius, 1);
ColorsTexture.SetPixel(x, y, color);
}
}
ColorsTexture.Apply();
/* ==================================== Initializing Color =====================================*/
SetColor(new Color32(255, 170, 85, 255));
RefreshColor();
}
/* ==================================== Update =====================================*/
private void Update()
{
float distance = 0, rotation = 0;
if (Input.GetMouseButtonDown(0))
{
Vector2 PressedPosition = Input.mousePosition;
Vector2 Center = ColorsRawImage.transform.position;
Vector2 PressedVector = new Vector2(PressedPosition.x - Center.x, PressedPosition.y - Center.y);
distance = Mathf.Sqrt
(
Mathf.Pow(PressedVector.x, 2) + Mathf.Pow(PressedVector.y, 2)
);
if (distance <= maxDistance)
{
onCanvas = true;
}
else
{
onCanvas = false;
}
}
if (Input.GetMouseButton(0) && onCanvas)
{
Vector2 VerticalVector = new Vector2(0, maxDistance);
Vector2 PressedPosition = Input.mousePosition;
Vector2 PressedVector = new Vector2(PressedPosition.x - Center.x, PressedPosition.y - Center.y);
/* ==================================== Get Position =====================================*/
distance = Mathf.Sqrt
(
Mathf.Pow(PressedVector.x, 2) + Mathf.Pow(PressedVector.y, 2)
);
if (distance != 0)
{
rotation = Mathf.Acos
(
(VerticalVector.x * PressedVector.x + VerticalVector.y * PressedVector.y) /
Mathf.Sqrt
(
(Mathf.Pow(VerticalVector.x, 2) + Mathf.Pow(VerticalVector.y, 2)) *
(Mathf.Pow(PressedVector.x, 2) + Mathf.Pow(PressedVector.y, 2))
)
);
}
if (PressedPosition.x < Center.x)
{
rotation = 2 * Mathf.PI - rotation;
}
/* ==================================== Set Color =====================================*/
Color color;
if (distance <= maxDistance)
{
color = Color.HSVToRGB(rotation * Mathf.Rad2Deg / 360, distance / maxDistance, 255);
}
else
{
color = Color.HSVToRGB(rotation * Mathf.Rad2Deg / 360, 1, 255);
}
Color32 color32 = new Color32((byte)color.r, (byte)color.g, (byte)color.b, (byte)(TransparenceSlider.value * 255));
SetColor(color32);
}
}
/* ==================================== Functions =====================================*/
public void ChangeValue()
{
float hue, saturation, value;
Color.RGBToHSV(GetNewColor(), out hue, out saturation, out value);
Color color = Color.HSVToRGB(hue, saturation, ValueSlider.value);
SetColor(new Color32((byte)(color.r * 255), (byte)(color.g * 255), (byte)(color.b * 255), NewColor.a));
}
public void ChangeTransparence()
{
float transparence = TransparenceSlider.value;
SetColor(new Color32(GetNewColor().r, GetNewColor().g, GetNewColor().b, (byte)(transparence * 255)));
}
/* ==================================== Global Functions =====================================*/
public void SetColor(Color32 color32)
{
float hue, saturation, value;
float transparence;
float rotation, distance;
Color.RGBToHSV(color32, out hue, out saturation, out value);
transparence = color32.a;
rotation = hue * 360 * Mathf.Deg2Rad;
distance = saturation * maxDistance;
Knob.transform.position = new Vector2(Center.x + distance * Mathf.Sin(rotation), Center.y + distance * Mathf.Cos(rotation));
//ValueSlider.value = value;
TransparenceSlider.value = transparence / 255;
NewColor = color32;
NewColorImage.color = color32;
}
public void RefreshColor()
{
SelectedColor = NewColor;
SelectedColorImage.color = NewColor;
OpenButton.color = NewColor;
}
public Color32 GetSelectedColor()
{
return SelectedColor;
}
public Color32 GetNewColor()
{
return NewColor;
}
2 проблемы:
Value
цвет ставится в центральную точку - черный/белый цвет, из какого бы цвета Value
не устанавливалсяПроблема #1
Что такое HSV цвет с Value == 0
? Это черный цвет, RGB(0, 0, 0)
, когда мы поднимем Value
обратно в 1, то совершенно закономерно получим белый цвет и вот почему:
Сделаем цепочку преобразований от, допустим, бирюзового цвета в черный и обратно через Value
:
Value
до нуля: HSV(124, 184, 255) -> HSV(124, 184, 0)
HSV(124, 184, 0) -> RGB(0, 0, 0)
RGB(0, 0, 0) -> HSV(0, 0, 0)
Value
в единицу: HSV(0, 0, 0) -> HSV(0, 0, 255)
После всех этих махинаций видно, что HSV значения до и после преобразования отличаются: (124, 184, 0) -> (0, 0, 0)
. Цветовое представление RGB и HSV никак не связаны, они лишь имеют преобразования друг в друга.
Данный пример является самым показательным:
У HSV цвета может быть 255^2 черных одинаковых цветов: (0-255, 0-255, 0)
, когда у RGB это ровно одна комбинация: (0, 0, 0)
. Из-за этого преобразования и теряется Hue-Saturation
информация.
Как решить эту проблему?
Раз уж нужно использовать HSV колесо и получать с него RGB цвета - храните для этого цветового колеса HSV значение цвета и реализуйте метод, возвращающий RGB значение через преобразование HSV цвета.
Проблема #2
Ну тут вообще детская ошибка - неправильное округление:
SetColor(
new Color32(
(byte)(color.r * 255),
(byte)(color.g * 255),
(byte)(color.b * 255),
NewColor.a)
);
Выводим эти числа до и после преобразования в байт и видим такую картину:
Данный код всегда округляет вниз - операция floor
, что и приводит к ошибкам преобразования в HSV.
Как решить эту проблему?
Перестать использовать миллиард преобразований из HSV в RGB и обратно, тем более если речь идет про Color32
, где значения цветовых каналов - это целые значения из диапазона [0..255]
, а HSV
и Color
- это дробные значения [0..1]
. Зачем нужно все туда-сюда дергать, если проще просто хранить все в HSV и при необходимости преобразовывать в RGB хоть Color
, хоть Color32
?
Исправленный под ошибки выше код, непонятные мне методы я просто убрал - сами допишете, что вам там нужно:
public class HSV_Circle : MonoBehaviour
{
struct HSV {
public float hue;
public float saturation;
public float value;
public float transparence;
}
public RawImage ColorsRawImage;
Texture2D ColorsTexture;
public Image Knob;
public Image SelectedColorImage, NewColorImage;
public Slider ValueSlider, TransparenceSlider;
float maxDistance;
bool onCanvas;
Vector2 Center;
HSV hsv_color;
//Color32 SelectedColor, NewColor;
[Header("Main")]
public Image OpenButton;
/* ==================================== Start =====================================*/
private void Start() {
/* ==================================== Colors Texture =====================================*/
ColorsTexture = new Texture2D(399, 399) {
filterMode = FilterMode.Point
};
ColorsRawImage.texture = ColorsTexture;
maxDistance = ColorsRawImage.GetComponent<RectTransform>().rect.width / 2;
Vector2Int CenterInt = new Vector2Int(ColorsTexture.width / 2 + 1, ColorsTexture.height / 2 + 1);
Center = ColorsRawImage.transform.position;
for (int y = 0; y < ColorsTexture.height; y++) {
for (int x = 0; x < ColorsTexture.width; x++) {
ColorsTexture.SetPixel(x, y, Color.white);
}
}
int maxRadius = ColorsTexture.width / 2;
for (float radius = 0; radius <= maxRadius; radius++) {
for (float angle = 0; angle <= 360; angle += 0.1f) {
int x = (int)(CenterInt.x + radius * Mathf.Sin(angle * Mathf.Deg2Rad));
int y = (int)(CenterInt.y + radius * Mathf.Cos(angle * Mathf.Deg2Rad));
Color color = Color.HSVToRGB(angle / 360, radius / maxRadius, 1);
ColorsTexture.SetPixel(x, y, color);
}
}
ColorsTexture.Apply();
/* ==================================== Initializing Color =====================================*/
hsv_color = new HSV();
hsv_color.value = 1;
SetColor();
}
/* ==================================== Update =====================================*/
private void Update() {
float distance = 0, rotation = 0;
if (Input.GetMouseButtonDown(0)) {
Vector2 PressedPosition = Input.mousePosition;
Vector2 Center = ColorsRawImage.transform.position;
Vector2 PressedVector = new Vector2(PressedPosition.x - Center.x, PressedPosition.y - Center.y);
distance = Mathf.Sqrt
(
Mathf.Pow(PressedVector.x, 2) + Mathf.Pow(PressedVector.y, 2)
);
if (distance <= maxDistance) {
onCanvas = true;
}
else {
onCanvas = false;
}
}
if (Input.GetMouseButton(0) && onCanvas) {
Vector2 VerticalVector = new Vector2(0, maxDistance);
Vector2 PressedPosition = Input.mousePosition;
Vector2 PressedVector = new Vector2(PressedPosition.x - Center.x, PressedPosition.y - Center.y);
/* ==================================== Get Position =====================================*/
distance = Mathf.Sqrt
(
Mathf.Pow(PressedVector.x, 2) + Mathf.Pow(PressedVector.y, 2)
);
if (distance != 0) {
rotation = Mathf.Acos
(
(VerticalVector.x * PressedVector.x + VerticalVector.y * PressedVector.y) /
Mathf.Sqrt
(
(Mathf.Pow(VerticalVector.x, 2) + Mathf.Pow(VerticalVector.y, 2)) *
(Mathf.Pow(PressedVector.x, 2) + Mathf.Pow(PressedVector.y, 2))
)
);
}
if (PressedPosition.x < Center.x) {
rotation = 2 * Mathf.PI - rotation;
}
/* ==================================== Set Color =====================================*/
hsv_color.hue = rotation * Mathf.Rad2Deg / 360;
hsv_color.value = ValueSlider.value;
hsv_color.transparence = TransparenceSlider.value;
if (distance <= maxDistance) {
hsv_color.saturation = distance / maxDistance;
}
else {
hsv_color.saturation = 1;
}
SetColor();
}
}
/* ==================================== Functions =====================================*/
public void ChangeValue() {
hsv_color.value = ValueSlider.value;
SetColor();
}
public void ChangeTransparence() {
hsv_color.transparence = TransparenceSlider.value;
SetColor();
}
/* ==================================== Global Functions =====================================*/
public void SetColor() {
float rotation = hsv_color.hue * 360 * Mathf.Deg2Rad;
float distance = hsv_color.saturation * maxDistance;
Knob.transform.position = new Vector2(Center.x + distance * Mathf.Sin(rotation), Center.y + distance * Mathf.Cos(rotation));
NewColorImage.color = GetSelectedColor();
}
public Color32 GetSelectedColor() {
return Color.HSVToRGB(hsv_color.hue, hsv_color.saturation, hsv_color.value);
}
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Пытался уже решить этот вопрос, но никак не получаеться решить проблему
Нужен совет правильно я сделал проверку в layoutsphp
Использую saveHTML() для сохранения данных в файл, но данная функция перестраивает структуру кодаБыло так:
Сайт работал в кодировке UTF-8Конфигурация сервера не соответствует требованиям