mirror of
https://github.com/ppy/osu.git
synced 2024-11-19 03:52:55 +08:00
245 lines
9.5 KiB
C#
245 lines
9.5 KiB
C#
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
// See the LICENCE file in the repository root for full licence text.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using NUnit.Framework;
|
|
using osu.Framework.Graphics.Containers;
|
|
using osu.Framework.Graphics.Shapes;
|
|
using osu.Framework.Graphics;
|
|
using osu.Framework.Utils;
|
|
using osu.Game.Graphics.Containers;
|
|
using osu.Game.Graphics.Sprites;
|
|
using osu.Game.Graphics;
|
|
using osuTK.Graphics;
|
|
using osuTK;
|
|
|
|
namespace osu.Game.Tests.Visual.UserInterface
|
|
{
|
|
public class TestSceneUprightAspectMaintainingContainer : OsuGridTestScene
|
|
{
|
|
private const int rows = 3;
|
|
private const int columns = 4;
|
|
|
|
private readonly ScaleMode[] scaleModeValues = { ScaleMode.NoScaling, ScaleMode.Horizontal, ScaleMode.Vertical };
|
|
private readonly float[] scalingFactorValues = { 1.0f / 3, 1.0f / 2, 1.0f, 1.5f };
|
|
|
|
private readonly List<List<Container>> parentContainers = new List<List<Container>>(rows);
|
|
private readonly List<List<UprightAspectMaintainingContainer>> childContainers = new List<List<UprightAspectMaintainingContainer>>(rows);
|
|
|
|
// Preferably should be set to (4 * 2^n)
|
|
private const int rotation_step_count = 3;
|
|
|
|
private readonly List<int> flipStates = new List<int>();
|
|
private readonly List<float> rotationSteps = new List<float>();
|
|
private readonly List<float> scaleSteps = new List<float>();
|
|
|
|
public TestSceneUprightAspectMaintainingContainer()
|
|
: base(rows, columns)
|
|
{
|
|
for (int i = 0; i < rows; i++)
|
|
{
|
|
parentContainers.Add(new List<Container>());
|
|
childContainers.Add(new List<UprightAspectMaintainingContainer>());
|
|
|
|
for (int j = 0; j < columns; j++)
|
|
{
|
|
UprightAspectMaintainingContainer child;
|
|
Container parent = new Container
|
|
{
|
|
Anchor = Anchor.Centre,
|
|
Origin = Anchor.Centre,
|
|
Height = 80,
|
|
Width = 80,
|
|
Children = new Drawable[]
|
|
{
|
|
new Box
|
|
{
|
|
RelativeSizeAxes = Axes.Both,
|
|
Colour = new Color4(255, 0, 0, 160),
|
|
},
|
|
new OsuSpriteText
|
|
{
|
|
Text = "Parent",
|
|
},
|
|
child = new UprightAspectMaintainingContainer
|
|
{
|
|
Origin = Anchor.Centre,
|
|
Anchor = Anchor.Centre,
|
|
AutoSizeAxes = Axes.Both,
|
|
|
|
// These are the parameters being Tested
|
|
Scaling = scaleModeValues[i],
|
|
ScalingFactor = scalingFactorValues[j],
|
|
|
|
Children = new Drawable[]
|
|
{
|
|
new Box
|
|
{
|
|
RelativeSizeAxes = Axes.Both,
|
|
Colour = new Color4(0, 0, 255, 160),
|
|
},
|
|
new OsuSpriteText
|
|
{
|
|
Text = "Text",
|
|
Font = OsuFont.Numeric,
|
|
Origin = Anchor.Centre,
|
|
Anchor = Anchor.Centre,
|
|
Padding = new MarginPadding
|
|
{
|
|
Horizontal = 4,
|
|
Vertical = 4,
|
|
}
|
|
},
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
Container cellInfo = new Container
|
|
{
|
|
Children = new Drawable[]
|
|
{
|
|
new OsuSpriteText
|
|
{
|
|
Text = "Scaling: " + scaleModeValues[i].ToString(),
|
|
},
|
|
new OsuSpriteText
|
|
{
|
|
Text = "ScalingFactor: " + scalingFactorValues[j].ToString("0.00"),
|
|
Margin = new MarginPadding
|
|
{
|
|
Top = 15,
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
Cell(i * columns + j).Add(cellInfo);
|
|
Cell(i * columns + j).Add(parent);
|
|
parentContainers[i].Add(parent);
|
|
childContainers[i].Add(child);
|
|
}
|
|
}
|
|
|
|
flipStates.AddRange(new[] { 1, -1 });
|
|
rotationSteps.AddRange(Enumerable.Range(0, rotation_step_count).Select(x => 360f * ((float)x / rotation_step_count)));
|
|
scaleSteps.AddRange(new[] { 1, 0.3f, 1.5f });
|
|
}
|
|
|
|
[Test]
|
|
public void ExplicitlySizedParent()
|
|
{
|
|
var parentStates = from xFlip in flipStates
|
|
from yFlip in flipStates
|
|
from xScale in scaleSteps
|
|
from yScale in scaleSteps
|
|
from rotation in rotationSteps
|
|
select new { xFlip, yFlip, xScale, yScale, rotation };
|
|
|
|
foreach (var state in parentStates)
|
|
{
|
|
Vector2 parentScale = new Vector2(state.xFlip * state.xScale, state.yFlip * state.yScale);
|
|
float parentRotation = state.rotation;
|
|
|
|
AddStep("S: (" + parentScale.X.ToString("0.00") + ", " + parentScale.Y.ToString("0.00") + "), R: " + parentRotation.ToString("0.00"), () =>
|
|
{
|
|
foreach (List<Container> list in parentContainers)
|
|
{
|
|
foreach (Container container in list)
|
|
{
|
|
container.Scale = parentScale;
|
|
container.Rotation = parentRotation;
|
|
}
|
|
}
|
|
});
|
|
|
|
AddAssert("Check if state is valid", () =>
|
|
{
|
|
foreach (int i in Enumerable.Range(0, parentContainers.Count))
|
|
{
|
|
foreach (int j in Enumerable.Range(0, parentContainers[i].Count))
|
|
{
|
|
if (!uprightAspectMaintainingContainerStateIsValid(parentContainers[i][j], childContainers[i][j]))
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
});
|
|
}
|
|
}
|
|
|
|
private bool uprightAspectMaintainingContainerStateIsValid(Container parent, UprightAspectMaintainingContainer child)
|
|
{
|
|
Matrix3 parentMatrix = parent.DrawInfo.Matrix;
|
|
Matrix3 childMatrix = child.DrawInfo.Matrix;
|
|
Vector3 childScale = childMatrix.ExtractScale();
|
|
Vector3 parentScale = parentMatrix.ExtractScale();
|
|
|
|
// Orientation check
|
|
if (!(isNearlyZero(MathF.Abs(childMatrix.M21)) && isNearlyZero(MathF.Abs(childMatrix.M12))))
|
|
return false;
|
|
|
|
// flip check
|
|
if (!(childMatrix.M11 * childMatrix.M22 > 0))
|
|
return false;
|
|
|
|
// Aspect ratio check
|
|
if (!isNearlyZero(childScale.X - childScale.Y))
|
|
return false;
|
|
|
|
// ScalingMode check
|
|
switch (child.Scaling)
|
|
{
|
|
case ScaleMode.NoScaling:
|
|
if (!(isNearlyZero(childMatrix.M11 - 1.0f) && isNearlyZero(childMatrix.M22 - 1.0f)))
|
|
return false;
|
|
|
|
break;
|
|
|
|
case ScaleMode.Vertical:
|
|
if (!(checkScaling(child.ScalingFactor, parentScale.Y, childScale.Y)))
|
|
return false;
|
|
|
|
break;
|
|
|
|
case ScaleMode.Horizontal:
|
|
if (!(checkScaling(child.ScalingFactor, parentScale.X, childScale.X)))
|
|
return false;
|
|
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private bool checkScaling(float scalingFactor, float parentScale, float childScale)
|
|
{
|
|
if (scalingFactor <= 1.0f)
|
|
{
|
|
if (!isNearlyZero(1.0f + (parentScale - 1.0f) * scalingFactor - childScale))
|
|
return false;
|
|
}
|
|
else if (scalingFactor > 1.0f)
|
|
{
|
|
if (parentScale < 1.0f)
|
|
{
|
|
if (!isNearlyZero((parentScale * (1.0f / scalingFactor)) - childScale))
|
|
return false;
|
|
}
|
|
else if (!isNearlyZero(parentScale * scalingFactor - childScale))
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private bool isNearlyZero(float f, float epsilon = Precision.FLOAT_EPSILON)
|
|
{
|
|
return f < epsilon;
|
|
}
|
|
}
|
|
}
|