嘟嘟哒嘟嘟哒

Signed-off-by: TRAfoer <lhf190@outlook.com>
This commit is contained in:
2025-07-27 13:35:26 +08:00
parent cfb95a3a7c
commit 8da603c702
10 changed files with 3461 additions and 68 deletions

4
.gitignore vendored
View File

@@ -46,6 +46,7 @@ ExportedObj/
*.mdb
*.opendb
*.VC.db
*.DS_Store
# Unity3D generated meta files
*.pidb.meta
@@ -61,7 +62,8 @@ sysinfo.txt
*.unitypackage
*.unitypackage.meta
*.app
/[Aa]ssets/FR2_Cache.asset
#这玩意好大
# Crashlytics generated file
crashlytics-build.properties

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 6dbdd314784e80440b48088e6357c1ef
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -2020,6 +2020,7 @@ MonoBehaviour:
isEmission: 0
emissionObj: {fileID: 0}
emissionInput: {fileID: 0}
baseColorPicker: {fileID: 0}
--- !u!225 &1119795976362648617
CanvasGroup:
m_ObjectHideFlags: 0

View File

@@ -2989,7 +2989,7 @@ RectTransform:
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 47}
m_SizeDelta: {x: 500, y: 394}
m_SizeDelta: {x: 100, y: 394}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &7396740820777350136
MonoBehaviour:

View File

@@ -5,6 +5,7 @@ using Ichni.RhythmGame;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.UI;
namespace Ichni.Editor
@@ -71,14 +72,17 @@ namespace Ichni.Editor
inputFieldBaseA.text = sliderA.value.ToString();
ApplyParameters();
}
public void SliderChangeWithoutNofication(Color color)
public void SliderChangeWithoutNotification(Color color)
{
// 仅更新UI不触发事件
sliderR.SetValueWithoutNotify(color.r);
sliderG.SetValueWithoutNotify(color.g);
sliderB.SetValueWithoutNotify(color.b);
sliderA.SetValueWithoutNotify(color.a);
inputFieldBaseR.SetTextWithoutNotify(color.r.ToString());
inputFieldBaseG.SetTextWithoutNotify(color.g.ToString());
inputFieldBaseB.SetTextWithoutNotify(color.b.ToString());
inputFieldBaseA.SetTextWithoutNotify(color.a.ToString());
// 不调用ApplyParameters以避免重复更新
colorPreview.color = new Color(sliderR.value, sliderG.value, sliderB.value, sliderA.value);
}
@@ -97,5 +101,36 @@ namespace Ichni.Editor
return this;
}
private void Update()
{
if (RectTransformUtility.RectangleContainsScreenPoint(colorPreview.rectTransform, Mouse.current.position.ReadValue())
|| RectTransformUtility.RectangleContainsScreenPoint(hsvDrawer?.previewImage.rectTransform, Mouse.current.position.ReadValue()))
{
if (Mouse.current.leftButton.wasPressedThisFrame)//快速复制粘贴颜色
{
// 复制颜色到剪贴板
GUIUtility.systemCopyBuffer = ColorUtility.ToHtmlStringRGBA(new Color(sliderR.value, sliderG.value, sliderB.value, sliderA.value));
LogWindow.Log("Color copied to clipboard: " + GUIUtility.systemCopyBuffer);
}
else if (Mouse.current.rightButton.wasPressedThisFrame)
{
if (GUIUtility.systemCopyBuffer != null && GUIUtility.systemCopyBuffer != "")
{
// 从剪贴板粘贴颜色
Color pastedColor;
if (ColorUtility.TryParseHtmlString("#" + GUIUtility.systemCopyBuffer, out pastedColor))
{
SliderChangeWithoutNotification(pastedColor);
ApplyParameters();
LogWindow.Log("Color pasted from clipboard: " + pastedColor);
}
else
{
Debug.Log("Failed to parse color from clipboard: " + GUIUtility.systemCopyBuffer);
}
}
}
}
}
}
}

View File

@@ -4,6 +4,7 @@ using Ichni.RhythmGame;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.Serialization;
using UnityEngine.UI;
@@ -13,7 +14,7 @@ namespace Ichni.Editor
{
private string emissionEnabledName, colorParameterName, emissionIntensityName;
private bool canDisableEmission;
public Toggle toggleEnableEmission;
public TMP_InputField inputFieldEmissionR;
public TMP_InputField inputFieldEmissionG;
@@ -22,21 +23,21 @@ namespace Ichni.Editor
public Slider sliderR;
public Slider sliderG;
public Slider sliderB;
public Image colorPreview;
public void Initialize(IBaseElement baseElement, string title,
public void Initialize(IBaseElement baseElement, string title,
string emissionEnabledName, string colorParameterName, string emissionIntensityName)
{
base.Initialize(baseElement, title, colorParameterName);
canDisableEmission = emissionEnabledName != "NULL"; //如果对应的EmissionColor强制开启那么其enabledName为"NULL"不需要显示Toggle
this.emissionEnabledName = emissionEnabledName;
this.colorParameterName = colorParameterName;
this.emissionIntensityName = emissionIntensityName;
if(canDisableEmission)
if (canDisableEmission)
{
bool enableEmission = (bool)connectedBaseElement.GetType().GetField(emissionEnabledName).GetValue(connectedBaseElement);
toggleEnableEmission.isOn = enableEmission;
@@ -49,24 +50,24 @@ namespace Ichni.Editor
Color emissionColor = (Color)connectedBaseElement.GetType().GetField(colorParameterName).GetValue(connectedBaseElement);
float emissionIntensity = (float)connectedBaseElement.GetType().GetField(emissionIntensityName).GetValue(connectedBaseElement);
inputFieldEmissionR.text = emissionColor.r.ToString();
inputFieldEmissionG.text = emissionColor.g.ToString();
inputFieldEmissionB.text = emissionColor.b.ToString();
inputFieldEmissionI.text = emissionIntensity.ToString();
sliderR.value=emissionColor.r;
sliderG.value=emissionColor.g;
sliderB.value=emissionColor.b;
sliderR.value = emissionColor.r;
sliderG.value = emissionColor.g;
sliderB.value = emissionColor.b;
sliderR.onValueChanged.AddListener(SliderChange);
sliderG.onValueChanged.AddListener(SliderChange);
sliderB.onValueChanged.AddListener(SliderChange);
inputFieldEmissionR.onEndEdit.AddListener(_ => ApplyParameters());
inputFieldEmissionG.onEndEdit.AddListener(_ => ApplyParameters());
inputFieldEmissionB.onEndEdit.AddListener(_ => ApplyParameters());
inputFieldEmissionI.onEndEdit.AddListener(_ => ApplyParameters());
colorPreview.color = emissionColor;
}
@@ -111,8 +112,50 @@ namespace Ichni.Editor
sliderR.onValueChanged.AddListener(_ => action());
sliderG.onValueChanged.AddListener(_ => action());
sliderB.onValueChanged.AddListener(_ => action());
return this;
}
public void SliderChangeWithoutNotification(Color color)
{
sliderR.SetValueWithoutNotify(color.r);
sliderG.SetValueWithoutNotify(color.g);
sliderB.SetValueWithoutNotify(color.b);
inputFieldEmissionI.SetTextWithoutNotify(color.a.ToString());
inputFieldEmissionB.SetTextWithoutNotify(color.b.ToString());
inputFieldEmissionG.SetTextWithoutNotify(color.g.ToString());
inputFieldEmissionR.SetTextWithoutNotify(color.r.ToString());
// 不调用ApplyParameters以避免重复更新
}
private void Update()
{
if (RectTransformUtility.RectangleContainsScreenPoint(colorPreview.rectTransform, Mouse.current.position.ReadValue())
)
{
if (Mouse.current.leftButton.wasPressedThisFrame)//快速复制粘贴颜色
{
// 复制颜色到剪贴板
GUIUtility.systemCopyBuffer = ColorUtility.ToHtmlStringRGBA(new Color(sliderR.value, sliderG.value, sliderB.value, inputFieldEmissionI.text != "" ? float.Parse(inputFieldEmissionI.text) : 1f));
LogWindow.Log("Color copied to clipboard: " + GUIUtility.systemCopyBuffer);
}
else if (Mouse.current.rightButton.wasPressedThisFrame)
{
if (GUIUtility.systemCopyBuffer != null && GUIUtility.systemCopyBuffer != "")
{
// 从剪贴板粘贴颜色
Color pastedColor;
if (ColorUtility.TryParseHtmlString("#" + GUIUtility.systemCopyBuffer, out pastedColor))
{
SliderChangeWithoutNotification(pastedColor);
ApplyParameters();
LogWindow.Log("Color pasted from clipboard: " + pastedColor);
}
else
{
Debug.Log("Failed to parse color from clipboard: " + GUIUtility.systemCopyBuffer);
}
}
}
}
}
}
}

View File

@@ -37,7 +37,7 @@ namespace Ichni.RhythmGame
this.zWrite = zWrite;
this.uvScale = uvScale;
this.uvOffset = uvOffset;
if (!HaveSameSubmodule)
{
this.track.trackRendererSubmodule = this;
@@ -65,10 +65,10 @@ namespace Ichni.RhythmGame
SetEmissionIntensity();
SetUV();
if (track.trackTimeSubmodule is TrackTimeSubmoduleMovable)
if (track.trackTimeSubmodule is TrackTimeSubmoduleMovable trackTimeSubmoduleMovable)
{
meshGenerator.clipFrom = 0;
meshGenerator.clipTo = 0;
meshGenerator.clipFrom = trackTimeSubmoduleMovable.tailPercent;
meshGenerator.clipTo = trackTimeSubmoduleMovable.headPercent;
}
else
{
@@ -98,7 +98,7 @@ namespace Ichni.RhythmGame
var container = inspector.GenerateContainer("Track Renderer " + submoduleName[submoduleNameIndex]);
var zWriteSettings = container.GenerateSubcontainer(3);
var zWriteToggle =
inspector.GenerateToggle(this, zWriteSettings, "Enable ZWrite", nameof(zWrite))
.AddListenerFunction(SetEnableZWrite);
@@ -109,7 +109,7 @@ namespace Ichni.RhythmGame
var emissionIntensityInputField =
inspector.GenerateInputField(this, emissionSettings, "Emission Intensity", nameof(emissionIntensity))
.AddListenerFunction(SetEmissionIntensity);
var uvSettings = container.GenerateSubcontainer(1);
var uvScaleInputField =
inspector.GenerateVector2InputField(this, uvSettings, "UV Scale", nameof(uvScale))
@@ -193,7 +193,7 @@ namespace Ichni.RhythmGame
this.splineRenderer.doubleSided = true;
this.splineRenderer.clipFrom = 0;
this.splineRenderer.clipTo = 1;
this.splineRenderer.updateMethod = SplineUser.UpdateMethod.LateUpdate;
this.splineRenderer.updateMethod = SplineUser.UpdateMethod.Update;
this.meshRenderer.material = renderMaterial;
this.splineRenderer.color = Color.white;
this.splineRenderer.uvRotation = 90;
@@ -240,7 +240,7 @@ namespace Ichni.RhythmGame
{
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
Track track = attachedElement as Track;
track.trackRendererSubmodule =
track.trackRendererSubmodule =
new TrackRendererSubmoduleAutoOrient(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset);
if (materialName.Trim() != String.Empty)
{
@@ -251,7 +251,7 @@ namespace Ichni.RhythmGame
public override void DuplicateBM(GameElement attached)
{
Track track = attached as Track;
track.trackRendererSubmodule =
track.trackRendererSubmodule =
new TrackRendererSubmoduleAutoOrient(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset);
if (materialName.Trim() != String.Empty)
{
@@ -269,7 +269,7 @@ namespace Ichni.RhythmGame
{
public PathGenerator pathGenerator;
public TrackRendererSubmodulePathGenerator(Track track, bool enableEmission, float emissionIntensity, bool zWrite,
public TrackRendererSubmodulePathGenerator(Track track, bool enableEmission, float emissionIntensity, bool zWrite,
Vector2 uvScale, Vector2 uvOffset, Material material = null) :
base(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset)
{
@@ -281,7 +281,7 @@ namespace Ichni.RhythmGame
this.pathGenerator.doubleSided = true;
this.pathGenerator.clipFrom = 0;
this.pathGenerator.clipTo = 1;
this.pathGenerator.updateMethod = SplineUser.UpdateMethod.LateUpdate;
this.pathGenerator.updateMethod = SplineUser.UpdateMethod.Update;
this.meshRenderer.material = renderMaterial;
this.pathGenerator.color = Color.white;
this.pathGenerator.uvRotation = 90;
@@ -328,7 +328,7 @@ namespace Ichni.RhythmGame
{
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
Track track = attachedElement as Track;
track.trackRendererSubmodule =
track.trackRendererSubmodule =
new TrackRendererSubmodulePathGenerator(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset);
if (materialName.Trim() != String.Empty)
{
@@ -339,7 +339,7 @@ namespace Ichni.RhythmGame
public override void DuplicateBM(GameElement attached)
{
Track track = attached as Track;
track.trackRendererSubmodule =
track.trackRendererSubmodule =
new TrackRendererSubmodulePathGenerator(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset);
if (materialName.Trim() != String.Empty)
{
@@ -372,7 +372,7 @@ namespace Ichni.RhythmGame
this.tubeGenerator.doubleSided = true;
this.tubeGenerator.clipFrom = 0;
this.tubeGenerator.clipTo = 1;
this.tubeGenerator.updateMethod = SplineUser.UpdateMethod.LateUpdate;
this.tubeGenerator.updateMethod = SplineUser.UpdateMethod.Update;
this.meshRenderer.material = renderMaterial;
this.tubeGenerator.color = Color.white;
this.tubeGenerator.uvRotation = 90;
@@ -411,7 +411,7 @@ namespace Ichni.RhythmGame
public bool enableEmission;
public float emissionIntensity;
public bool zWrite; // 新增
public int sideCount;
public int sideCount;
public Vector2 uvScale = Vector2.one;
public Vector2 uvOffset = Vector2.zero;
@@ -437,7 +437,7 @@ namespace Ichni.RhythmGame
{
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
Track track = attachedElement as Track;
track.trackRendererSubmodule =
track.trackRendererSubmodule =
new TrackRendererSubmoduleTubeGenerator(track, enableEmission, emissionIntensity, zWrite, sideCount, uvScale, uvOffset);
if (materialName.Trim() != String.Empty)
{
@@ -448,7 +448,7 @@ namespace Ichni.RhythmGame
public override void DuplicateBM(GameElement attached)
{
Track track = attached as Track;
track.trackRendererSubmodule =
track.trackRendererSubmodule =
new TrackRendererSubmoduleTubeGenerator(track, enableEmission, emissionIntensity, zWrite, sideCount, uvScale, uvOffset);
if (materialName.Trim() != String.Empty)
{
@@ -466,7 +466,7 @@ namespace Ichni.RhythmGame
{
public SurfaceGenerator surface;
public TrackRendererSubmoduleSurface(Track track, bool enableEmission, float emissionIntensity, bool zWrite,
public TrackRendererSubmoduleSurface(Track track, bool enableEmission, float emissionIntensity, bool zWrite,
Vector2 uvScale, Vector2 uvOffset, Material material = null) :
base(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset)
{
@@ -525,7 +525,7 @@ namespace Ichni.RhythmGame
{
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
Track track = attachedElement as Track;
track.trackRendererSubmodule =
track.trackRendererSubmodule =
new TrackRendererSubmoduleSurface(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset);
if (materialName.Trim() != String.Empty)
{
@@ -536,7 +536,7 @@ namespace Ichni.RhythmGame
public override void DuplicateBM(GameElement attached)
{
Track track = attached as Track;
track.trackRendererSubmodule =
track.trackRendererSubmodule =
new TrackRendererSubmoduleSurface(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset);
if (materialName.Trim() != String.Empty)
{

View File

@@ -57,16 +57,61 @@ public partial class HsvDrawer
}
}
private Coroutine valueSliderCoroutine;
private float pendingValue = -1f;
// 新增:高低分辨率参数
public int highResTextureSize = 256;
public int lowResTextureSize = 64;
private bool isLowRes = false;
void OnValueSliderChanged(float newValue)
{
value = newValue;
CreateColorWheelTexture();
ApplyTextureToRawImage();
pendingValue = newValue;
// 切换到低分辨率
if (!isLowRes)
{
isLowRes = true;
CreateColorWheelTexture(true);
ApplyTextureToRawImage();
}
if (valueSliderCoroutine != null)
StopCoroutine(valueSliderCoroutine);
valueSliderCoroutine = StartCoroutine(DelayedRedrawColorWheel());
// 刷新当前颜色
if (pickerIndicator != null)
UpdateCurrentColor(pickerIndicator.localPosition);
}
IEnumerator DelayedRedrawColorWheel()
{
float waitTime = 0.01f;
float timer = 0f;
while (timer < waitTime)
{
yield return null;
timer += Time.unscaledDeltaTime;
}
// 恢复高分辨率
if (isLowRes)
{
isLowRes = false;
CreateColorWheelTexture(false);
ApplyTextureToRawImage();
}
else
{
CreateColorWheelTexture(false);
ApplyTextureToRawImage();
}
valueSliderCoroutine = null;
}
void OnAlphaSliderChanged(float newAlpha)
{
// 只更新透明度
@@ -82,6 +127,7 @@ public partial class HsvDrawer
{
StartCoroutine(DraggingColorPicker());
}
}
IEnumerator DraggingColorPicker()
{
@@ -112,47 +158,44 @@ public partial class HsvDrawer
yield return null; // 等待下一帧
}
}
void CreateColorWheelTexture()
// 整合分辨率逻辑到此方法
void CreateColorWheelTexture(bool useLowRes = false)
{
// 创建方形纹理
_texture = new Texture2D(textureSize, textureSize, TextureFormat.RGBA32, false);
int targetSize = useLowRes ? lowResTextureSize : highResTextureSize;
textureSize = targetSize;
if (_texture == null || _texture.width != textureSize || _texture.height != textureSize)
_texture = new Texture2D(textureSize, textureSize, TextureFormat.RGBA32, false);
_texture.wrapMode = TextureWrapMode.Clamp;
Vector2 center = new Vector2(textureSize / 2f, textureSize / 2f);
float maxRadius = textureSize / 2f;
Vector2 center = new Vector2(textureSize * 0.5f, textureSize * 0.5f);
float maxRadius = textureSize * 0.5f;
Color[] pixels = new Color[textureSize * textureSize];
// 遍历所有像素
for (int y = 0; y < textureSize; y++)
{
for (int x = 0; x < textureSize; x++)
{
Vector2 pixelPos = new Vector2(x, y);
Vector2 offset = pixelPos - center;
Vector2 offset = new Vector2(x + 0.5f, y + 0.5f) - center;
float distance = offset.magnitude;
int idx = y * textureSize + x;
// 在圆形区域内绘制
if (distance <= maxRadius)
{
// 计算角度0-360°
float angle = Mathf.Atan2(offset.y, offset.x) * Mathf.Rad2Deg;
if (angle < 0) angle += 360;
// 计算饱和度(基于半径比例)
if (angle < 0) angle += 360f;
float sat = Mathf.Clamp01(distance / maxRadius) * saturation;
// HSV转RGB
Color color = Color.HSVToRGB(angle / 360f, sat, value);
_texture.SetPixel(x, y, color);
pixels[idx] = Color.HSVToRGB(angle / 360f, sat, value);
}
else
{
// 圆形外透明
_texture.SetPixel(x, y, Color.clear);
pixels[idx] = Color.clear;
}
}
}
_texture.Apply(); // 应用像素更改
_texture.SetPixels(pixels);
_texture.Apply();
}
void ApplyTextureToRawImage()
@@ -207,7 +250,7 @@ public partial class HsvDrawer
if (baseColorPicker != null)
{
// 同步到BaseColorPicker
baseColorPicker.SliderChangeWithoutNofication(currentColor);
baseColorPicker.SliderChangeWithoutNotification(currentColor);
}
ApplyParameters();
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff