Skip to content

Commit

Permalink
Add color preview in colorPicker
Browse files Browse the repository at this point in the history
  • Loading branch information
Jannify committed Nov 16, 2024
1 parent c25991d commit 52d7ec2
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 85 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using NitroxClient.Unity.Helper;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace NitroxClient.MonoBehaviours.Gui.MainMenu.ServerJoin;

public class MainMenuColorPickerPreview : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
private Image previewImage;
private CanvasGroup cg;

public void Init(uGUI_ColorPicker colorPicker)
{
GameObject colorPreview = new("ColorPreview");
colorPreview.transform.SetParent(colorPicker.pointer.transform);
colorPreview.transform.localPosition = new Vector3(-30, 30, 0);
colorPreview.transform.localRotation = Quaternion.identity;
colorPreview.transform.localScale = new Vector3(0.4f, 0.4f, 0.4f);
previewImage = colorPreview.AddComponent<Image>();
previewImage.sprite = CreateCircleSprite();
cg = colorPreview.AddComponent<CanvasGroup>();
cg.alpha = 0;

colorPicker.onColorChange.AddListener(OnColorPickerDrag);
}

private static Sprite CreateCircleSprite()
{
const int HALF_SIZE = 50;
const int RADIUS = 42;
Texture2D tex = new(HALF_SIZE * 2, HALF_SIZE * 2);
for (int y = -HALF_SIZE; y <= HALF_SIZE; y++)
{
for (int x = -HALF_SIZE; x <= HALF_SIZE; x++)
{
bool isInsideCircle = x * x + y * y <= RADIUS * RADIUS;
tex.SetPixel(HALF_SIZE + x, HALF_SIZE + y, isInsideCircle ? Color.white : Color.clear);
}
}

tex.Apply();
return Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f), 200);
}

private void OnColorPickerDrag(ColorChangeEventData data) => previewImage.color = data.color;

public void OnPointerDown(PointerEventData _)
{
StopAllCoroutines();
StartCoroutine(cg.ShiftAlpha(1, 0.25f, 1.5f, true));
}

public void OnPointerUp(PointerEventData _)
{
StopAllCoroutines();
StartCoroutine(cg.ShiftAlpha(0, 0.25f, 1.5f, false));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class MainMenuJoinServerPanel : MonoBehaviour, uGUI_INavigableIconGrid, u
private GameObject playerSettingsPanel;
private TextMeshProUGUI header;
private uGUI_ColorPicker colorPicker;
private MainMenuColorPickerPreview colorPickerPreview;
private Slider saturationSlider;
private uGUI_InputField playerNameInputField;

Expand Down Expand Up @@ -73,6 +74,8 @@ private IEnumerator AsyncSetup(GameObject savedGamesRef)
colorPicker.pointer.localScale = new Vector3(1f, 1.46f, 1);
saturationSlider = colorPicker.saturationSlider;
saturationSlider.transform.localPosition = new Vector3(197, 0, 0);
colorPickerPreview = colorPicker.gameObject.AddComponent<MainMenuColorPickerPreview>();
colorPickerPreview.Init(colorPicker);

GameObject buttonLeft = Instantiate(newGameButtonRef, parent);
buttonLeft.GetComponent<RectTransform>().sizeDelta = new Vector2(160, 45);
Expand Down Expand Up @@ -199,6 +202,10 @@ public void SelectItem(object item)
if (selectedItem == selectableItems[1])
{
colorPicker.pointer.GetComponent<Image>().color = Color.cyan;
if (GameInput.GetPrimaryDevice() == GameInput.Device.Controller)
{
colorPickerPreview.OnPointerDown(null);
}
}
else if (selectedItem == selectableItems[3] || selectedItem == selectableItems[4])
{
Expand Down Expand Up @@ -233,7 +240,14 @@ public void DeselectItem()
}
else if (selectedItem.TryGetComponent(out uGUI_ColorPicker selectedColorPicker))
{
selectedColorPicker.pointer.GetComponent<Image>().color = Color.white;
Image colorPickerPointer = selectedColorPicker.pointer.GetComponent<Image>();

if (colorPickerPointer.color != Color.white &&
GameInput.GetPrimaryDevice() == GameInput.Device.Controller)
{
colorPickerPreview.OnPointerUp(null);
}
colorPickerPointer.color = Color.white;
}
else if (selectedItem.TryGetComponentInChildren(out uGUI_BasicColorSwap colorSwap))
{
Expand Down
197 changes: 113 additions & 84 deletions NitroxClient/Unity/Helper/RendererHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,105 +1,134 @@
using NitroxClient.GameLogic.PlayerLogic.PlayerModel.ColorSwap;
using System.Collections;
using NitroxClient.GameLogic.PlayerLogic.PlayerModel.ColorSwap;
using UnityEngine;
using UnityEngine.UI;

namespace NitroxClient.Unity.Helper
namespace NitroxClient.Unity.Helper;

public static class RendererHelpers
{
public static class RendererHelpers
//This entire method is necessary in order to deal with the fact that UWE compiles Subnautica in a mode
//that prevents us from accessing the pixel map of the 2D textures they apply to their materials.
public static Texture2D Clone(this Texture2D sourceTexture)
{
//This entire method is necessary in order to deal with the fact that UWE compiles Subnautica in a mode
//that prevents us from accessing the pixel map of the 2D textures they apply to their materials.
public static Texture2D Clone(this Texture2D sourceTexture)
{
// Create a temporary RenderTexture of the same size as the texture
RenderTexture tmp = RenderTexture.GetTemporary(
sourceTexture.width,
sourceTexture.height,
0,
RenderTextureFormat.Default,
RenderTextureReadWrite.Linear);
// Create a temporary RenderTexture of the same size as the texture
RenderTexture tmp = RenderTexture.GetTemporary(
sourceTexture.width,
sourceTexture.height,
0,
RenderTextureFormat.Default,
RenderTextureReadWrite.Linear);

// Blit the pixels on texture to the RenderTexture
Graphics.Blit(sourceTexture, tmp);
// Backup the currently set RenderTexture
RenderTexture previous = RenderTexture.active;
// Set the current RenderTexture to the temporary one we created
RenderTexture.active = tmp;
// Create a new readable Texture2D to copy the pixels to it
Texture2D clonedTexture = new Texture2D(sourceTexture.width, sourceTexture.height);
// Copy the pixels from the RenderTexture to the new Texture
clonedTexture.ReadPixels(new Rect(0, 0, tmp.width, tmp.height), 0, 0);
clonedTexture.Apply();
// Reset the active RenderTexture
RenderTexture.active = previous;
// Release the temporary RenderTexture
RenderTexture.ReleaseTemporary(tmp);
// Blit the pixels on texture to the RenderTexture
Graphics.Blit(sourceTexture, tmp);
// Backup the currently set RenderTexture
RenderTexture previous = RenderTexture.active;
// Set the current RenderTexture to the temporary one we created
RenderTexture.active = tmp;
// Create a new readable Texture2D to copy the pixels to it
Texture2D clonedTexture = new(sourceTexture.width, sourceTexture.height);
// Copy the pixels from the RenderTexture to the new Texture
clonedTexture.ReadPixels(new Rect(0, 0, tmp.width, tmp.height), 0, 0);
clonedTexture.Apply();
// Reset the active RenderTexture
RenderTexture.active = previous;
// Release the temporary RenderTexture
RenderTexture.ReleaseTemporary(tmp);

return clonedTexture;
// "clonedTexture" now has the same pixels from "texture" and it's readable.
}
return clonedTexture;
// "clonedTexture" now has the same pixels from "texture" and it's readable.
}

//This applies a color filter to a specific region of a 2D texture.
public static void SwapTextureColors(
this Texture2D texture,
HsvSwapper filter,
TextureBlock textureBlock)
{
Color[] pixels = texture.GetPixels(textureBlock.X, textureBlock.Y, textureBlock.BlockWidth, textureBlock.BlockHeight);
//This applies a color filter to a specific region of a 2D texture.
public static void SwapTextureColors(
this Texture2D texture,
HsvSwapper filter,
TextureBlock textureBlock)
{
Color[] pixels = texture.GetPixels(textureBlock.X, textureBlock.Y, textureBlock.BlockWidth, textureBlock.BlockHeight);

filter.SwapColors(pixels);
filter.SwapColors(pixels);

texture.SetPixels(textureBlock.X, textureBlock.Y, textureBlock.BlockWidth, textureBlock.BlockHeight, pixels);
texture.Apply();
}
texture.SetPixels(textureBlock.X, textureBlock.Y, textureBlock.BlockWidth, textureBlock.BlockHeight, pixels);
texture.Apply();
}

public static void UpdateMainTextureColors(this Material material, Color[] pixels)
{
Texture2D mainTexture = (Texture2D)material.mainTexture;
mainTexture.SetPixels(pixels);
mainTexture.Apply();
}
public static void UpdateMainTextureColors(this Material material, Color[] pixels)
{
Texture2D mainTexture = (Texture2D)material.mainTexture;
mainTexture.SetPixels(pixels);
mainTexture.Apply();
}

//This applies a color filter to a specific region of a 2D texture.
public static void UpdateMainTextureColors(
this Material material,
Color[] pixels,
//IColorSwapStrategy colorSwapStrategy,
TextureBlock textureBlock)
{
Texture2D mainTexture = (Texture2D)material.mainTexture;
//Color[] pixels = mainTexture.GetPixels(textureBlock.X, textureBlock.Y, textureBlock.BlockWidth, textureBlock.BlockHeight);
//pixelIndexes.ForEach(pixelIndex => pixels[pixelIndex] = colorSwapStrategy.SwapColor(pixels[pixelIndex]));
mainTexture.SetPixels(textureBlock.X, textureBlock.Y, textureBlock.BlockWidth, textureBlock.BlockHeight, pixels);
mainTexture.Apply();
}
//This applies a color filter to a specific region of a 2D texture.
public static void UpdateMainTextureColors(
this Material material,
Color[] pixels,
//IColorSwapStrategy colorSwapStrategy,
TextureBlock textureBlock)
{
Texture2D mainTexture = (Texture2D)material.mainTexture;
//Color[] pixels = mainTexture.GetPixels(textureBlock.X, textureBlock.Y, textureBlock.BlockWidth, textureBlock.BlockHeight);
//pixelIndexes.ForEach(pixelIndex => pixels[pixelIndex] = colorSwapStrategy.SwapColor(pixels[pixelIndex]));
mainTexture.SetPixels(textureBlock.X, textureBlock.Y, textureBlock.BlockWidth, textureBlock.BlockHeight, pixels);
mainTexture.Apply();
}

public static void ApplyClonedTexture(this Material material)
{
Texture2D mainTexture = (Texture2D)material.mainTexture;
Texture2D clonedTexture = mainTexture.Clone();
material.mainTexture = clonedTexture;
}
public static void ApplyClonedTexture(this Material material)
{
Texture2D mainTexture = (Texture2D)material.mainTexture;
Texture2D clonedTexture = mainTexture.Clone();
material.mainTexture = clonedTexture;
}

public static SkinnedMeshRenderer GetRenderer(this GameObject playerModel, string equipmentGameObjectName)
{
return playerModel
.transform
.Find(equipmentGameObjectName)
.gameObject
.GetComponent<SkinnedMeshRenderer>();
}

public static Color[] GetMainTexturePixels(this Material material)
{
Texture2D mainTexture = (Texture2D)material.mainTexture;
return mainTexture.GetPixels();
}

public static Color[] GetMainTexturePixelBlock(
this Material material,
TextureBlock textureBlock)
{
Texture2D mainTexture = (Texture2D)material.mainTexture;
return mainTexture.GetPixels(textureBlock.X, textureBlock.Y, textureBlock.BlockWidth, textureBlock.BlockHeight);
}

public static SkinnedMeshRenderer GetRenderer(this GameObject playerModel, string equipmentGameObjectName)
/// Copied from MainMenuLoadButton.ShiftAlpha()
public static IEnumerator ShiftAlpha(
this CanvasGroup cg,
float targetAlpha,
float animTime,
float power,
bool toActive,
Selectable buttonToSelect = null)
{
float start = Time.time;
while (Time.time - start < animTime)
{
return playerModel
.transform
.Find(equipmentGameObjectName)
.gameObject
.GetComponent<SkinnedMeshRenderer>();
cg.alpha = Mathf.Lerp(cg.alpha, targetAlpha, Mathf.Pow(Mathf.Clamp01((Time.time - start) / animTime), power));
yield return null;
}

public static Color[] GetMainTexturePixels(this Material material)
cg.alpha = targetAlpha;
if (toActive)
{
Texture2D mainTexture = (Texture2D)material.mainTexture;
return mainTexture.GetPixels();
cg.interactable = true;
cg.blocksRaycasts = true;
}

public static Color[] GetMainTexturePixelBlock(
this Material material,
TextureBlock textureBlock)
else
{
Texture2D mainTexture = (Texture2D)material.mainTexture;
return mainTexture.GetPixels(textureBlock.X, textureBlock.Y, textureBlock.BlockWidth, textureBlock.BlockHeight);
cg.interactable = false;
cg.blocksRaycasts = false;
}
}
}

0 comments on commit 52d7ec2

Please sign in to comment.