test(huoshan): 添加Log释放演出编辑器测试
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b9ae118461543bda553c3a38e369dde
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,226 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using AibisDream.MiniGame.Language;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AibisDream.EditorTests.Huoshan
|
||||
{
|
||||
public sealed class LogReleasePresentationTests
|
||||
{
|
||||
[Test]
|
||||
public void LineClip_RejectsOutsideSegment()
|
||||
{
|
||||
Bounds bounds = new Bounds(Vector3.zero, new Vector3(2f, 2f, 0f));
|
||||
bool visible = ConnectionRenderer.TryClipLineToBounds(
|
||||
new Vector3(-3f, 2f),
|
||||
new Vector3(3f, 2f),
|
||||
bounds,
|
||||
out _,
|
||||
out _);
|
||||
|
||||
Assert.That(visible, Is.False);
|
||||
}
|
||||
|
||||
[TestCase(-0.5f, 0f, 0.5f, 0f, -0.5f, 0f, 0.5f, 0f)]
|
||||
[TestCase(-2f, 0f, 2f, 0f, -1f, 0f, 1f, 0f)]
|
||||
[TestCase(0f, -2f, 0f, 0.5f, 0f, -1f, 0f, 0.5f)]
|
||||
[TestCase(-2f, -2f, 2f, 2f, -1f, -1f, 1f, 1f)]
|
||||
public void LineClip_ReturnsExpectedInteriorSegment(
|
||||
float ax,
|
||||
float ay,
|
||||
float bx,
|
||||
float by,
|
||||
float expectedAx,
|
||||
float expectedAy,
|
||||
float expectedBx,
|
||||
float expectedBy)
|
||||
{
|
||||
Bounds bounds = new Bounds(Vector3.zero, new Vector3(2f, 2f, 0f));
|
||||
bool visible = ConnectionRenderer.TryClipLineToBounds(
|
||||
new Vector3(ax, ay),
|
||||
new Vector3(bx, by),
|
||||
bounds,
|
||||
out Vector3 clippedA,
|
||||
out Vector3 clippedB);
|
||||
|
||||
Assert.That(visible, Is.True);
|
||||
Assert.That(clippedA.x, Is.EqualTo(expectedAx).Within(0.0001f));
|
||||
Assert.That(clippedA.y, Is.EqualTo(expectedAy).Within(0.0001f));
|
||||
Assert.That(clippedB.x, Is.EqualTo(expectedBx).Within(0.0001f));
|
||||
Assert.That(clippedB.y, Is.EqualTo(expectedBy).Within(0.0001f));
|
||||
}
|
||||
|
||||
[TestCase(CompletionPhase.None, false)]
|
||||
[TestCase(CompletionPhase.Completed, false)]
|
||||
[TestCase(CompletionPhase.Focusing, true)]
|
||||
[TestCase(CompletionPhase.FocusHolding, true)]
|
||||
[TestCase(CompletionPhase.Finished, true)]
|
||||
public void ConnectionClipping_OnlyStartsAfterOutput(
|
||||
CompletionPhase phase,
|
||||
bool expected)
|
||||
{
|
||||
Assert.That(LanguageParticleManager.ShouldClipConnections(phase), Is.EqualTo(expected));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LieEdgePosition_LandsOnScreenPerimeterAndStaysInside()
|
||||
{
|
||||
Bounds bounds = new Bounds(Vector3.zero, new Vector3(6f, 4f, 0f));
|
||||
const float inset = 0.1f;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
Vector3 position = LanguageParticleManager.CalculateScreenEdgePosition(
|
||||
bounds,
|
||||
i,
|
||||
8,
|
||||
inset);
|
||||
|
||||
Assert.That(position.x, Is.InRange(bounds.min.x, bounds.max.x));
|
||||
Assert.That(position.y, Is.InRange(bounds.min.y, bounds.max.y));
|
||||
bool touchesVerticalEdge =
|
||||
Mathf.Abs(Mathf.Abs(position.x) - (bounds.extents.x - inset)) < 0.0001f;
|
||||
bool touchesHorizontalEdge =
|
||||
Mathf.Abs(Mathf.Abs(position.y) - (bounds.extents.y - inset)) < 0.0001f;
|
||||
Assert.That(touchesVerticalEdge || touchesHorizontalEdge, Is.True);
|
||||
}
|
||||
}
|
||||
|
||||
[TestCase(6, 0.70f)]
|
||||
[TestCase(6, 0.90f)]
|
||||
[TestCase(6, 1.10f)]
|
||||
public void ResolveTiming_LastCharacterCompletesWithinPreset(int characterCount, float totalDuration)
|
||||
{
|
||||
LanguageParticleManager.CalculateResolveTiming(
|
||||
characterCount,
|
||||
totalDuration,
|
||||
3.5f,
|
||||
0.4f,
|
||||
out float characterDuration,
|
||||
out float stagger);
|
||||
|
||||
float lastCompletion = characterDuration + stagger * (characterCount - 1);
|
||||
Assert.That(lastCompletion, Is.LessThanOrEqualTo(totalDuration + 0.0001f));
|
||||
Assert.That(lastCompletion, Is.EqualTo(totalDuration).Within(0.0001f));
|
||||
}
|
||||
|
||||
[TestCase("LightPreset", 0.10f, 0.35f, 0.25f, 0.25f, 0.70f, 0.15f)]
|
||||
[TestCase("MediumPreset", 0.20f, 0.55f, 0.50f, 0.35f, 0.90f, 0.30f)]
|
||||
[TestCase("HeavyPreset", 0.35f, 0.80f, 0.85f, 0.50f, 1.10f, 0.50f)]
|
||||
public void PresentationPreset_UsesApprovedValues(
|
||||
string presetFieldName,
|
||||
float baseDistortion,
|
||||
float liePause,
|
||||
float breakPeak,
|
||||
float breakDuration,
|
||||
float truthDuration,
|
||||
float truthPeripheral)
|
||||
{
|
||||
const BindingFlags flags = BindingFlags.Static | BindingFlags.NonPublic;
|
||||
FieldInfo presetField = typeof(LogReleasePresentationController).GetField(presetFieldName, flags);
|
||||
Assert.That(presetField, Is.Not.Null);
|
||||
object preset = presetField.GetValue(null);
|
||||
Type presetType = preset.GetType();
|
||||
|
||||
AssertPresetField(presetType, preset, "BaseDistortion", baseDistortion);
|
||||
AssertPresetField(presetType, preset, "LiePause", liePause);
|
||||
AssertPresetField(presetType, preset, "BreakPeak", breakPeak);
|
||||
AssertPresetField(presetType, preset, "BreakDuration", breakDuration);
|
||||
AssertPresetField(presetType, preset, "TruthDuration", truthDuration);
|
||||
AssertPresetField(presetType, preset, "TruthPeripheral", truthPeripheral);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TmpClipRect_ConvertsWorldCornersIntoTextLocalSpace()
|
||||
{
|
||||
GameObject rectObject = new GameObject("ScreenRect", typeof(RectTransform));
|
||||
GameObject textObject = new GameObject("TextTransform");
|
||||
try
|
||||
{
|
||||
RectTransform rect = rectObject.GetComponent<RectTransform>();
|
||||
rect.sizeDelta = new Vector2(4f, 2f);
|
||||
rect.position = new Vector3(2f, -1f, 0f);
|
||||
rect.rotation = Quaternion.Euler(0f, 0f, 17f);
|
||||
rect.localScale = new Vector3(1.2f, 0.8f, 1f);
|
||||
|
||||
textObject.transform.position = new Vector3(-0.5f, 0.75f, 0f);
|
||||
textObject.transform.rotation = Quaternion.Euler(0f, 0f, -11f);
|
||||
textObject.transform.localScale = new Vector3(1.4f, 0.65f, 1f);
|
||||
|
||||
Vector4 actual = TMPRectClipper.CalculateLocalClipRect(textObject.transform, rect);
|
||||
Vector3[] corners = new Vector3[4];
|
||||
rect.GetWorldCorners(corners);
|
||||
Vector3 first = textObject.transform.InverseTransformPoint(corners[0]);
|
||||
float minX = first.x;
|
||||
float minY = first.y;
|
||||
float maxX = first.x;
|
||||
float maxY = first.y;
|
||||
for (int i = 1; i < corners.Length; i++)
|
||||
{
|
||||
Vector3 local = textObject.transform.InverseTransformPoint(corners[i]);
|
||||
minX = Mathf.Min(minX, local.x);
|
||||
minY = Mathf.Min(minY, local.y);
|
||||
maxX = Mathf.Max(maxX, local.x);
|
||||
maxY = Mathf.Max(maxY, local.y);
|
||||
}
|
||||
|
||||
Assert.That(actual.x, Is.EqualTo(minX).Within(0.0001f));
|
||||
Assert.That(actual.y, Is.EqualTo(minY).Within(0.0001f));
|
||||
Assert.That(actual.z, Is.EqualTo(maxX).Within(0.0001f));
|
||||
Assert.That(actual.w, Is.EqualTo(maxY).Within(0.0001f));
|
||||
}
|
||||
finally
|
||||
{
|
||||
UnityEngine.Object.DestroyImmediate(rectObject);
|
||||
UnityEngine.Object.DestroyImmediate(textObject);
|
||||
}
|
||||
}
|
||||
|
||||
[TestCase(null, null)]
|
||||
[TestCase("", null)]
|
||||
[TestCase(" | ", null)]
|
||||
[TestCase("没问题|冇", "没问题冇")]
|
||||
[TestCase("没 问 题", "没问题")]
|
||||
public void SlotMachinePool_StripsSeparatorsAndWhitespace(string input, string expected)
|
||||
{
|
||||
Assert.That(LanguageParticleManager.SanitizeSlotMachinePool(input), Is.EqualTo(expected));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ActorPhraseList_PreservesWordsAndDropsEmptyEntries()
|
||||
{
|
||||
string[] phrases = LogReleasePresentationController.ParseActorPhrases(
|
||||
" 没问题 | | 冇问题|帽问题 ");
|
||||
|
||||
Assert.That(phrases, Is.EqualTo(new[] { "没问题", "冇问题", "帽问题" }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ActorFlash_OutsideMemoryState_CompletesImmediatelyWithoutStateChange()
|
||||
{
|
||||
GameObject host = new GameObject("PresentationHost");
|
||||
try
|
||||
{
|
||||
var controller = host.AddComponent<LogReleasePresentationController>();
|
||||
IEnumerator routine = controller.FlashActorLie("没问题", 0.6f);
|
||||
|
||||
Assert.That(routine.MoveNext(), Is.False);
|
||||
Assert.That(
|
||||
controller.State,
|
||||
Is.EqualTo(LogReleasePresentationController.PresentationState.Idle));
|
||||
}
|
||||
finally
|
||||
{
|
||||
UnityEngine.Object.DestroyImmediate(host);
|
||||
}
|
||||
}
|
||||
|
||||
private static void AssertPresetField(Type presetType, object preset, string name, float expected)
|
||||
{
|
||||
FieldInfo field = presetType.GetField(name, BindingFlags.Instance | BindingFlags.Public);
|
||||
Assert.That(field, Is.Not.Null);
|
||||
Assert.That((float)field.GetValue(preset), Is.EqualTo(expected).Within(0.0001f));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f75b14634314395a3a67721065f86bd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user