Merge remote-tracking branch 'origin/master' into 1.9

# Conflicts:
#	Source/Engine/UI/GUI/Common/Button.cs
This commit is contained in:
Wojtek Figat
2024-09-23 14:11:05 +02:00
59 changed files with 675 additions and 319 deletions

View File

@@ -339,11 +339,10 @@ int32 Font::HitTestText(const StringView& text, const Float2& location, const Te
float baseLinesDistance = static_cast<float>(_height) * layout.BaseLinesGapScale * scale;
// Offset position to match lines origin space
Float2 rootOffset = layout.Bounds.Location + lines.First().Location;
Float2 testPoint = location - rootOffset;
Float2 testPoint = location - layout.Bounds.Location;
// Get line which may intersect with the position (it's possible because lines have fixed height)
int32 lineIndex = Math::Clamp(Math::FloorToInt(testPoint.Y / baseLinesDistance), 0, lines.Count() - 1);
int32 lineIndex = Math::Clamp(Math::FloorToInt((testPoint.Y - lines.First().Location.Y) / baseLinesDistance), 0, lines.Count() - 1);
const FontLineCache& line = lines[lineIndex];
float x = line.Location.X;
@@ -411,7 +410,6 @@ Float2 Font::GetCharPosition(const StringView& text, int32 index, const TextLayo
ASSERT(lines.HasItems());
float scale = layout.Scale / FontManager::FontScale;
float baseLinesDistance = static_cast<float>(_height) * layout.BaseLinesGapScale * scale;
Float2 rootOffset = layout.Bounds.Location + lines.First().Location;
// Find line with that position
FontCharacterEntry previous;
@@ -423,7 +421,7 @@ Float2 Font::GetCharPosition(const StringView& text, int32 index, const TextLayo
// Check if desire position is somewhere inside characters in line range
if (Math::IsInRange(index, line.FirstCharIndex, line.LastCharIndex))
{
float x = line.Location.X;
Float2 charPos = line.Location;
// Check all characters in the line
for (int32 currentIndex = line.FirstCharIndex; currentIndex < index; currentIndex++)
@@ -436,21 +434,21 @@ Float2 Font::GetCharPosition(const StringView& text, int32 index, const TextLayo
// Apply kerning
if (!isWhitespace && previous.IsValid)
{
x += entry.Font->GetKerning(previous.Character, entry.Character);
charPos.X += entry.Font->GetKerning(previous.Character, entry.Character);
}
previous = entry;
// Move
x += entry.AdvanceX * scale;
charPos.X += entry.AdvanceX * scale;
}
// Upper left corner of the character
return rootOffset + Float2(x, static_cast<float>(lineIndex * baseLinesDistance));
return layout.Bounds.Location + charPos;
}
}
// Position after last character in the last line
return rootOffset + Float2(lines.Last().Size.X, static_cast<float>((lines.Count() - 1) * baseLinesDistance));
return layout.Bounds.Location + lines.Last().Location + Float2(lines.Last().Size.X, 0.0f);
}
void Font::FlushFaceSize() const

View File

@@ -90,7 +90,7 @@ namespace FlaxEngine
/// <summary>
/// The size of the font characters.
/// </summary>
[EditorOrder(10), Limit(1, 500, 0.1f), Tooltip("The size of the font characters.")]
[EditorOrder(10), Limit(1, 500, 0.5f), Tooltip("The size of the font characters.")]
public float Size
{
get => _size;

View File

@@ -841,10 +841,11 @@ void Render2D::PushClip(const Rectangle& clipRect)
{
RENDER2D_CHECK_RENDERING_STATE;
const auto& mask = ClipLayersStack.Peek();
RotatedRectangle clipRectTransformed;
ApplyTransform(clipRect, clipRectTransformed);
const Rectangle bounds = Rectangle::Shared(clipRectTransformed.ToBoundingRect(), ClipLayersStack.Peek().Bounds);
ClipLayersStack.Push({ clipRectTransformed, bounds });
const Rectangle bounds = Rectangle::Shared(clipRectTransformed.ToBoundingRect(), mask.Bounds);
ClipLayersStack.Push({ RotatedRectangle::Shared(clipRectTransformed, mask.Bounds), bounds });
OnClipScissors();
}

View File

@@ -10,7 +10,6 @@
struct RotatedRectangle
{
public:
/// <summary>
/// The transformed top left corner.
/// </summary>
@@ -27,7 +26,6 @@ public:
Float2 ExtentY;
public:
/// <summary>
/// Initializes a new instance of the <see cref="RotatedRectangle"/> struct.
/// </summary>
@@ -60,7 +58,6 @@ public:
}
public:
/// <summary>
/// Convert rotated rectangle to the axis-aligned rectangle that builds rotated rectangle bounding box.
/// </summary>
@@ -95,8 +92,24 @@ public:
return false;
}
public:
/// <summary>
/// Calculates a rectangle that contains the shared part of both rectangles.
/// </summary>
/// <param name="a">The first rectangle.</param>
/// <param name="b">The second rectangle.</param>
/// <returns>Rectangle that contains shared part of a and b rectangles.</returns>
static RotatedRectangle Shared(const RotatedRectangle& a, const Rectangle& b)
{
// Clip the rotated rectangle bounds within the given AABB
RotatedRectangle result = a;
result.TopLeft = Float2::Max(a.TopLeft, b.GetTopLeft());
// TODO: do a little better math below (in case of actually rotated rectangle)
result.ExtentX.X = Math::Min(result.TopLeft.X + result.ExtentX.X, b.GetRight()) - result.TopLeft.X;
result.ExtentY.Y = Math::Min(result.TopLeft.Y + result.ExtentY.Y, b.GetBottom()) - result.TopLeft.Y;
return result;
}
public:
bool operator ==(const RotatedRectangle& other) const
{
return

View File

@@ -1,10 +1,11 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System;
using System.Runtime.CompilerServices;
namespace FlaxEngine
{
partial struct SpriteHandle
partial struct SpriteHandle : IEquatable<SpriteHandle>
{
/// <summary>
/// Invalid sprite handle.
@@ -107,5 +108,53 @@ namespace FlaxEngine
Atlas.SetSprite(Index, ref sprite);
}
}
/// <summary>
/// Tests for equality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name="left" /> has the same value as <paramref name="right" />; otherwise, <c>false</c>.</returns>
public static bool operator ==(SpriteHandle left, SpriteHandle right)
{
return left.Index == right.Index && left.Atlas == right.Atlas;
}
/// <summary>
/// Tests for inequality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name="left" /> has a different value than <paramref name="right" />; otherwise, <c>false</c>.</returns>
public static bool operator !=(SpriteHandle left, SpriteHandle right)
{
return left.Index != right.Index || left.Atlas != right.Atlas;
}
/// <inheritdoc />
public bool Equals(SpriteHandle other)
{
return Index == other.Index && Atlas == other.Atlas;
}
/// <inheritdoc />
public override bool Equals(object obj)
{
return obj is SpriteHandle other && Equals(other);
}
/// <inheritdoc />
public override int GetHashCode()
{
return HashCode.Combine(Atlas, Index);
}
/// <inheritdoc />
public override string ToString()
{
if (Atlas)
return $"{System.IO.Path.GetFileNameWithoutExtension(Atlas.Path)}[{Index}]";
return "Invalid";
}
}
}