修复了一些bug(包含窗口预制体中的错误与{}列表解析存在死循环的错误)

This commit is contained in:
2025-10-04 23:09:46 +08:00
parent 1ecb1b0ba4
commit 84e31fe63a
16 changed files with 2590 additions and 832 deletions

View File

@@ -78,9 +78,11 @@ namespace Demo.Editor
[Content, SerializeField] private List<BPMLine> BPMLineEntries = new();
[Content] public int BPMFraction = 4;
[Content] public float BPMOffset = 0;
[Content] public float SongOffset = 0;
[Content] public float BPM = 60;
private float onebarDeltaTime;
private void InjectSetSongCurrentTime(float time)
{
// 秒,可见长度,以下相同,注意并非百分比
@@ -170,8 +172,9 @@ namespace Demo.Editor
// BPM
BPM = (float)MainGameController.MainConfig.FindItem(nameof(BPM), BPM);
onebarDeltaTime = 60.0f / (BPM * BPMFraction);
BPMFraction = (int)MainGameController.MainConfig.FindItem(nameof(BPMFraction), BPMFraction);
BPMOffset = (float)MainGameController.MainConfig.FindItem(nameof(BPMOffset), BPMOffset);
SongOffset = (float)MainGameController.MainConfig.FindItem(nameof(SongOffset), SongOffset);
// 绘制时频
var texturePath = (string)MainGameController.MainConfig.FindItem(nameof(SpectrumRenderTexture), null);
@@ -492,7 +495,6 @@ namespace Demo.Editor
var time = MainGameController.CurrentTime;
float onebarDeltaTime = 60.0f / (BPM * BPMFraction);
int BPMLineEntriesIndex = 0;
float farAplha = (1 - SpectrumSeeline.currentPercent) * 0.5f + 0.5f;
float foucs = Mathf.CeilToInt((time + leftClipFrom ) / onebarDeltaTime) * onebarDeltaTime;

View File

@@ -33,12 +33,12 @@ namespace Demo.Editor
{
if (name == nameof(ScriptableObject.LoadSubScript))
{
stream.WriteLine("#define __build_in_pragma #");
stream.WriteLine("#define __build_in_to_text(x) #x");
// stream.WriteLine("#define __build_in_pragma #");
// stream.WriteLine("#define __build_in_to_text(x) #x");
stream.Write("/*\n" + description + "\n*/\n");
stream.Write($"#define {name}({string.Join(',', paramList)}) __build_in_pragma include __build_in_to_text(./##{paramList.First()})\n\n");
//stream.Write($"#define {name}({string.Join(',', paramList)})\n\n");
// stream.Write("/*\n" + description + "\n*/\n");
// stream.Write($"#define {name}({string.Join(',', paramList)}) __build_in_pragma include __build_in_to_text(./##{paramList.First()})\n\n");
stream.Write($"#define {name}({string.Join(',', paramList)})\n\n");
}
else
{

View File

@@ -39,8 +39,8 @@ namespace Demo.Game
public string WhichOpenProject { get; private set; } = null;
public ProjectDefaultFileStyle CurrentProjectDefaultFileStyle = default;
public float SongOffset;
public float CurrentTime => MainAudio.CurrentTime - SongOffset;
public float SongOffset = 0;
public float CurrentTime = 0;
public Transform MainCameraTransform => MainCamera.transform;
@@ -122,10 +122,10 @@ namespace Demo.Game
{
ScriptableObject.FastScriptableObjectTypen = content.ScriptableObjectTypen;
ScriptableObject.IsAutoPlay = content.IsAutoPlay;
ScriptableObject.OneBarTime = (float)MainConfig.FindItem(nameof(Editor.EditorController.BPM), Editor.EditorController.instance.BPM);
ScriptableObject.OneBarTime = 60.0f / (float)MainConfig.FindItem(nameof(Editor.EditorController.BPM), Editor.EditorController.instance.BPM);
SongOffset = (float)MainConfig.FindItem(nameof(SongOffset), SongOffset);
SetupSongDuration = GameContent.instance.SetupSongDuration;
SetSongCurrentTime = GameContent.instance.SetSongCurrentTime;
SongOffset = GameContent.instance.SongOffset;
// Open Project
WhichOpenProject = (string)MainConfig.FindItem(nameof(WhichOpenProject), WhichOpenProject);
if (string.IsNullOrEmpty(WhichOpenProject) == false)
@@ -159,7 +159,7 @@ namespace Demo.Game
string defaultRootPath = "root" + CurrentProjectDefaultFileStyle switch
{
ProjectDefaultFileStyle.PY => ".py",
_ => ".h"
_ => ".cpp"
};
if (content.IsCreateNewProject)
{
@@ -207,7 +207,7 @@ namespace Demo.Game
yield return null;
IsEnableUpdate = true;
yield return new WaitUntil(() => MainObject != null);
MainObject.ScriptUpdate(0, Time.deltaTime, ScriptableObject.TickType.Reset);
MainObject.ScriptUpdate(SongOffset, Time.deltaTime, ScriptableObject.TickType.Reset);
}
@@ -216,9 +216,9 @@ namespace Demo.Game
MainAudio.Stop();
if (IsMain)
{
SetSongCurrentTime(-SongOffset);
SetSongCurrentTime(SongOffset);
}
MainObject.ScriptUpdate(-SongOffset, Time.deltaTime, ScriptableObject.TickType.Reset);
MainObject.ScriptUpdate(SongOffset, Time.deltaTime, ScriptableObject.TickType.Reset);
}
public void Pause()
@@ -255,6 +255,7 @@ namespace Demo.Game
private void Update()
{
CurrentTime = MainAudio.CurrentTime + SongOffset;
float deltaTime = Time.deltaTime;
var currentClip = MainAudio.CurrentClip;

View File

@@ -24,7 +24,7 @@ namespace Demo.Game
}
finally
{
ScriptUpdate(0, 0.01f, TickType.Start);
ScriptUpdate(RootGameController.SongOffset, 0.01f, TickType.Start);
if (RootGameController.IsMain)
{
Keyboard.current.onTextInput += InputCatchChar;

View File

@@ -35,8 +35,7 @@ namespace Demo
public static (string functionName, string[] arguments) ParseFunctionCall(string input)
{
// 匹配函数名和参数部分
string pattern = @"^(\w+)\s*\(\s*(.*?)\s*\)\s*;?$";
Match match = Regex.Match(input, pattern);
Match match = Regex.Match(input, @"^(\w+)\s*\(\s*(.*?)\s*\)\s*;?$");
if (!match.Success)
return (null, new string[0]);
@@ -56,14 +55,84 @@ namespace Demo
if (string.IsNullOrWhiteSpace(argumentsString))
return new string[0];
// 处理字符串字面量和普通参数的正则表达式
string argPattern = @"""(?:[^""\\]|\\.)*""|[^,]+";
var arguments = new List<string>();
int i = 0;
while (i < argumentsString.Length)
{
// 跳过空白字符
while (i < argumentsString.Length && char.IsWhiteSpace(argumentsString[i]))
i++;
// 越界检查
if (i >= argumentsString.Length)
break;
string argument = ExtractArgument(argumentsString, ref i);
if (!string.IsNullOrEmpty(argument))
arguments.Add(argument.Trim());
return Regex.Matches(argumentsString, argPattern)
.Cast<Match>()
.Select(m => m.Value.Trim())
.Where(arg => !string.IsNullOrEmpty(arg))
.ToArray();
// 跳过空白字符
while (i < argumentsString.Length && char.IsWhiteSpace(argumentsString[i]))
i++;
// 越界检查
if (i >= argumentsString.Length)
break;
// 必定是逗号, 否则异常情况
if (argumentsString[i] != ',')
throw new InvalidOperationException("Parser is invalid logic");
i++;
}
return arguments.ToArray();
}
// 提取单个参数的方法,支持花括号和字符串字面量
private static string ExtractArgument(string input, ref int index)
{
int start = index;
if (input[index] == '"')
{
// 处理字符串字面量
index++; // 跳过开始的引号
while (index < input.Length)
{
if (input[index] == '"' && (index == 0 || input[index - 1] != '\\'))
{
index++; // 跳过结束的引号
break;
}
index++;
}
}
else if (input[index] == '{')
{
// 处理花括号内的内容
int braceCount = 0;
while (index < input.Length)
{
if (input[index] == '{')
braceCount++;
else if (input[index] == '}')
braceCount--;
index++;
if (braceCount == 0)
break;
}
}
else
{
// 处理普通参数(直到遇到逗号)
while (index < input.Length && input[index] != ',')
index++;
}
return input[start..index];
}
}
@@ -396,6 +465,28 @@ namespace Demo
}
}
public partial class ScriptableObject
{
[Content] public int UpdatePerFrame = 1;
/// <summary>
/// 指定多少个<see cref="TickType.Update"/>状态的<see cref="UpdateTicks(float, float, TickType)"/>执行一次更新,不会影响到子物体
/// 属于性能优化的高级选项
/// </summary>
/// <param name="frame">间隔帧数, 小于等于1的值代表无论如何都会更新</param>
[ScriptableCall(@"
<summary>
指定多少个Update状态的UpdateTicks执行一次更新,不会影响到子物体
属于性能优化的高级选项
</summary>
<param name=""frame"">间隔帧数, 小于等于1的值代表无论如何都会更新</param>
")]
public void SetUpdatePerFrame(string frame)
{
UpdatePerFrame = Mathf.Max(1, int.Parse(frame));
}
}
/// <summary>
/// <para>使用<see cref="ScriptableCallAttribute"/>标记可编辑脚本所能够调用的函数,并附加注释</para>
/// <para>使用<see cref="DefaultScriptAttribute"/>标记派生类,并附加默认模板</para>
@@ -800,6 +891,7 @@ namespace Demo
//LateUpdate
}
[Content, SerializeField] private int ScriptUpdateCounter = 0;
public void ScriptUpdate(float currentTime, float deltaTime, TickType tickType)
{
if (IsEnableUpdate == false)
@@ -809,7 +901,13 @@ namespace Demo
#if UNITY_EDITOR
s_PreparePerfMarker.Begin(this);
#endif
UpdateTicks(currentTime, deltaTime, tickType);
// UpdateTicks
{
if (ScriptUpdateCounter % UpdatePerFrame == 0)
UpdateTicks(currentTime, deltaTime, tickType);
ScriptUpdateCounter += tickType == TickType.Update ? 1 : 0;
}
// Childs UpdateTicks
foreach (var child in Childs)
{
child.ScriptUpdate(currentTime, deltaTime, tickType);

View File

@@ -224,10 +224,12 @@ namespace Demo.Game
public static Dictionary<string, Func<ScriptableObject>> GetScriptableObjectInstantiate()
{
return new Dictionary<string, Func<ScriptableObject>>(GameObjectInstantiate.Union(TickUpdatementInstantiate)
.Union(MaterialUpdatementInstantiate)
.Union(SplineInstantiate)
.Union(JudgementInstantiate));
return new Dictionary<string, Func<ScriptableObject>>(GameObjectInstantiate
.Union(DDTInstantiate)
.Union(TickUpdatementInstantiate)
.Union(MaterialUpdatementInstantiate)
.Union(SplineInstantiate)
.Union(JudgementInstantiate));
}
}
}