Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions TombEngine/Game/effects/DisplaySprite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,30 @@ namespace TEN::Effects::DisplaySprite
{
std::vector<DisplaySprite> DisplaySprites = {};

static bool g_hasActiveDisplayScissor = false;
static TEN::Renderer::Structures::RendererRectangle g_activeDisplayScissorRect = {};

void SetActiveDisplayScissor(const TEN::Renderer::Structures::RendererRectangle& rect)
{
g_hasActiveDisplayScissor = true;
g_activeDisplayScissorRect = rect;
}

void ClearActiveDisplayScissor()
{
g_hasActiveDisplayScissor = false;
}

bool HasActiveDisplayScissor()
{
return g_hasActiveDisplayScissor;
}

const TEN::Renderer::Structures::RendererRectangle& GetActiveDisplayScissor()
{
return g_activeDisplayScissorRect;
}

void AddDisplaySprite(GAME_OBJECT_ID objectID, int spriteID, const Vector2& pos, short orient, const Vector2& scale, const Vector4& color,
int priority, DisplaySpriteAlignMode alignMode, DisplaySpriteScaleMode scaleMode,
BlendMode blendMode, DisplaySpritePhase source)
Expand All @@ -29,6 +53,8 @@ namespace TEN::Effects::DisplaySprite
displaySprite.ScaleMode = scaleMode;
displaySprite.BlendMode = blendMode;
displaySprite.Source = source;
displaySprite.HasScissor = g_hasActiveDisplayScissor;
displaySprite.ScissorRect = g_activeDisplayScissorRect;

DisplaySprites.push_back(displaySprite);
}
Expand Down
9 changes: 9 additions & 0 deletions TombEngine/Game/effects/DisplaySprite.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "Math/Math.h"
#include "Objects/game_object_ids.h"
#include "Renderer/RendererEnums.h"
#include "Renderer/Structures/RendererRectangle.h"

namespace TEN::Effects::DisplaySprite
{
Expand Down Expand Up @@ -47,6 +48,9 @@ namespace TEN::Effects::DisplaySprite
BlendMode BlendMode = BlendMode::AlphaBlend;

DisplaySpritePhase Source = DisplaySpritePhase::Control;

bool HasScissor = false;
TEN::Renderer::Structures::RendererRectangle ScissorRect = {};
};

// Result of display sprite layout calculation.
Expand All @@ -65,6 +69,11 @@ namespace TEN::Effects::DisplaySprite
void ClearAllDisplaySprites();
void ClearDrawPhaseDisplaySprites();

void SetActiveDisplayScissor(const TEN::Renderer::Structures::RendererRectangle& rect);
void ClearActiveDisplayScissor();
bool HasActiveDisplayScissor();
const TEN::Renderer::Structures::RendererRectangle& GetActiveDisplayScissor();

// Calculate complete layout data for a display sprite.
//
// NOTE: This function is defined inline in the header for performance reasons.
Expand Down
3 changes: 3 additions & 0 deletions TombEngine/Renderer/Renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ namespace TEN::Renderer
void InitializeGameBars();
void InitializeMenuBars(int y);
void InitializeSky();
void AddStringInternal(const std::string& string, const Vector2& pos, const Vector2& prevPos, const Vector2& area, const Color& color, const Vector2& scale, float rotation, int flags, int priority, BlendMode blendMode);
void DrawAllStrings();
void PrepareDynamicLight(RendererLight& light);
void PrepareLaserBarriers(RenderView& view);
Expand Down Expand Up @@ -741,6 +742,8 @@ namespace TEN::Renderer
void AddString(const std::string& string, const Vector2& pos, const Color& color, float scale, int flags);
void AddString(const std::string& string, const Vector2& pos, const Vector2& area, const Color& color, float scale, int flags);
void AddString(const std::string& string, const Vector2& currentPos, const Vector2& prevPos, const Vector2& area, const Color& color, float scale, int flags);
void AddString(const std::string& string, const Vector2& pos, const Vector2& prevPos, const Vector2& area, const Color& color, const Vector2& scale, float rotation, int flags, int priority, BlendMode blendMode);
Vector2 GetDisplayStringSize(const std::string& text, const Vector2& scale = Vector2::One) const;
void AddDebugString(const std::string& string, const Vector2& pos, const Color& color, float scale, RendererDebugPage page = RendererDebugPage::None);
void FreeRendererData();
void AddDynamicPointLight(const Vector3& pos, float radius, const Color& color, bool castShadows, int hash = 0);
Expand Down
119 changes: 106 additions & 13 deletions TombEngine/Renderer/RendererString.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
#include "framework.h"
#include "Renderer/Renderer.h"

#include <algorithm>

#include "Game/effects/DisplaySprite.h"
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
#include "Specific/trutils.h"

using namespace TEN::Effects::DisplaySprite;
using namespace TEN::Utils;

namespace TEN::Renderer
{
void Renderer::AddDebugString(const std::string& string, const Vector2& pos, const Color& color, float scale, RendererDebugPage page)
Expand All @@ -24,6 +30,26 @@ namespace TEN::Renderer
AddString(string, Vector2(x, y), Color(color), 1.0f, flags);
}

Vector2 Renderer::GetDisplayStringSize(const std::string& text, const Vector2& scale) const
{
if (text.empty() || _gameFont == nullptr)
return Vector2::Zero;

auto screenRes = GetScreenResolution();
auto factor = Vector2((float)screenRes.x / DISPLAY_SPACE_RES.x, (float)screenRes.y / DISPLAY_SPACE_RES.y);
float uiScale = (screenRes.x > screenRes.y) ? factor.y : factor.x;
float fontSpacing = _gameFont->GetLineSpacing();
float fontScale = REFERENCE_FONT_SIZE / fontSpacing;
auto stringScale = Vector2(uiScale * fontScale) * scale;
float baseScale = stringScale.y;

auto wtext = TEN::Utils::ToWString(text);
auto measured = Vector2(_gameFont->MeasureString(wtext.c_str())) * baseScale;

// Convert pixel size back to display space (800x600 units).
return Vector2(measured.x / factor.x, measured.y / factor.y);
}

void Renderer::AddString(const std::string& string, const Vector2& pos, const Color& color, float scale, int flags)
{
AddString(string, pos, Vector2::Zero, Color(color), scale, flags);
Expand All @@ -34,7 +60,21 @@ namespace TEN::Renderer
AddString(string, pos, pos, area, color, scale, flags);
}

void Renderer::AddString(const std::string& string, const Vector2& pos, const Vector2& prevPos, const Vector2& area,
const Color& color, const Vector2& scale, float rotation, int flags,
int priority, BlendMode blendMode)
{
AddStringInternal(string, pos, prevPos, area, color, scale, rotation, flags, priority, blendMode);
}

void Renderer::AddString(const std::string& string, const Vector2& pos, const Vector2& prevPos, const Vector2& area, const Color& color, float scale, int flags)
{
AddStringInternal(string, pos, prevPos, area, color, Vector2(scale), 0.0f, flags, 0, BlendMode::AlphaBlend);
}

void Renderer::AddStringInternal(const std::string& string, const Vector2& pos, const Vector2& prevPos, const Vector2& area,
const Color& color, const Vector2& scale, float rotation, int flags,
int priority, BlendMode blendMode)
{
if (_isLocked)
return;
Expand All @@ -49,8 +89,9 @@ namespace TEN::Renderer
float uiScale = (screenRes.x > screenRes.y) ? factor.y : factor.x;
float fontSpacing = _gameFont->GetLineSpacing();
float fontScale = REFERENCE_FONT_SIZE / fontSpacing;
float stringScale = (uiScale * fontScale) * scale;
float spaceWidth = Vector3(_gameFont->MeasureString(L" ")).x * stringScale;
auto stringScale = Vector2(uiScale * fontScale) * scale;
float baseScale = stringScale.y;
float spaceWidth = Vector3(_gameFont->MeasureString(L" ")).x * baseScale;

std::vector<std::wstring> stringLines;

Expand All @@ -74,7 +115,7 @@ namespace TEN::Renderer

for (const auto& word : words)
{
float wordWidth = Vector3(_gameFont->MeasureString(word.c_str())).x * stringScale;
float wordWidth = Vector3(_gameFont->MeasureString(word.c_str())).x * baseScale;

if (!currentLine.empty() && (currentLineWidth + wordWidth + spaceWidth > area.x * factor.x))
{
Expand Down Expand Up @@ -107,9 +148,9 @@ namespace TEN::Renderer
for (const auto& line : stringLines)
{
if (line.empty())
totalHeight += fontSpacing * stringScale;
totalHeight += fontSpacing * baseScale;
else
totalHeight += Vector2(_gameFont->MeasureString(line.c_str())).y * stringScale;
totalHeight += Vector2(_gameFont->MeasureString(line.c_str())).y * stringScale.y;
}

// Calculate maximum textbox height.
Expand Down Expand Up @@ -142,9 +183,15 @@ namespace TEN::Renderer
rString.Position = Vector2::Zero;
rString.Color = color;
rString.Scale = stringScale;
rString.Rotation = rotation;
rString.Priority = priority;
rString.Blend = blendMode;
rString.HasScissor = HasActiveDisplayScissor();
if (rString.HasScissor)
rString.ScissorRect = GetActiveDisplayScissor();

// Measure string.
auto stringSize = line.empty() ? Vector2(0, fontSpacing * rString.Scale) : Vector2(_gameFont->MeasureString(line.c_str())) * rString.Scale;
auto stringSize = line.empty() ? Vector2(0, fontSpacing * rString.Scale.y) : Vector2(_gameFont->MeasureString(line.c_str())) * rString.Scale.y;

// If height clipping enabled, stop drawing when exceeding maxHeight.
if (maxHeight > 0.0f && (yOffset + stringSize.y) > maxHeight)
Expand All @@ -164,7 +211,7 @@ namespace TEN::Renderer
else
{
// Calculate indentation to account for string scaling.
auto indent = line.empty() ? 0 : _gameFont->FindGlyph(line.at(0))->XAdvance * rString.Scale;
auto indent = line.empty() ? 0 : _gameFont->FindGlyph(line.at(0))->XAdvance * rString.Scale.y;

rString.Position.x = pos.x * factor.x + indent;
rString.PrevPosition.x = prevPos.x * factor.x + indent;
Expand Down Expand Up @@ -194,35 +241,81 @@ namespace TEN::Renderer
if (_stringsToDraw.empty())
return;

SetBlendMode(BlendMode::AlphaBlend);
// Sort by priority (lower priority draws first, i.e. behind higher).
std::stable_sort(_stringsToDraw.begin(), _stringsToDraw.end(),
[](const auto& a, const auto& b) { return a.Priority < b.Priority; });

float shadowOffset = 1.5f / (REFERENCE_FONT_SIZE / _gameFont->GetLineSpacing());
auto shadowColor = (Vector4)g_GameFlow->GetSettings()->UI.ShadowTextColor;

_spriteBatch->Begin();
ResetScissor();
_spriteBatch->Begin(SpriteSortMode_Deferred, nullptr, nullptr, nullptr, _cullNoneRasterizerState.Get());

auto currentBlend = BlendMode::AlphaBlend;
SetBlendMode(currentBlend);

bool currentHasScissor = false;
auto currentScissor = RendererRectangle{};

for (const auto& rString : _stringsToDraw)
{
// Switch blend mode per string if needed.
if (rString.Blend != currentBlend)
{
_spriteBatch->End();
currentBlend = rString.Blend;
SetBlendMode(currentBlend);
_spriteBatch->Begin(SpriteSortMode_Deferred, nullptr, nullptr, nullptr, _cullNoneRasterizerState.Get());
}

// Handle scissor rect changes.
bool scissorChanged = (rString.HasScissor != currentHasScissor) ||
(rString.HasScissor &&
(rString.ScissorRect.Left != currentScissor.Left ||
rString.ScissorRect.Top != currentScissor.Top ||
rString.ScissorRect.Right != currentScissor.Right ||
rString.ScissorRect.Bottom != currentScissor.Bottom));

if (scissorChanged)
{
_spriteBatch->End();

if (rString.HasScissor)
SetScissor(rString.ScissorRect);
else
ResetScissor();

currentHasScissor = rString.HasScissor;
currentScissor = rString.ScissorRect;
_spriteBatch->Begin(SpriteSortMode_Deferred, nullptr, nullptr, nullptr, _cullNoneRasterizerState.Get());
}

auto drawPos = Vector2::Lerp(rString.PrevPosition, rString.Position, GetInterpolationFactor());

// Draw shadow.
if (rString.Flags & (int)PrintStringFlags::Outline)
{
auto shadowPos = Vector2(drawPos.x + shadowOffset * rString.Scale.y, drawPos.y + shadowOffset * rString.Scale.y);

_gameFont->DrawString(
_spriteBatch.get(), rString.String.c_str(),
Vector2(drawPos.x + shadowOffset * rString.Scale, drawPos.y + shadowOffset * rString.Scale),
shadowPos,
(shadowColor * rString.Color.w * shadowColor.w) * ScreenFadeCurrent,
0.0f, Vector4::Zero, rString.Scale);
rString.Rotation, Vector2::Zero, rString.Scale);
}

// Draw string.
_gameFont->DrawString(
_spriteBatch.get(), rString.String.c_str(),
Vector2(drawPos.x, drawPos.y),
drawPos,
(rString.Color * rString.Color.w) * ScreenFadeCurrent,
0.0f, Vector4::Zero, rString.Scale);
rString.Rotation, Vector2::Zero, rString.Scale);
}

_spriteBatch->End();

// Reset scissor if it was active.
if (currentHasScissor)
ResetScissor();
}
}
4 changes: 4 additions & 0 deletions TombEngine/Renderer/Structures/RendererSprite2D.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "Renderer/Structures/RendererSprite.h"
#include "Renderer/RendererEnums.h"
#include "Renderer/Structures/RendererRectangle.h"

namespace TEN::Renderer::Structures
{
Expand All @@ -18,5 +19,8 @@ namespace TEN::Renderer::Structures
BlendMode BlendMode = BlendMode::AlphaBlend;

Vector2 AspectCorrection = Vector2::One;

bool HasScissor = false;
RendererRectangle ScissorRect = {};
};
}
11 changes: 10 additions & 1 deletion TombEngine/Renderer/Structures/RendererStringToDraw.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#pragma once
#include <SimpleMath.h>

#include "Renderer/RendererEnums.h"
#include "Renderer/Structures/RendererRectangle.h"

namespace TEN::Renderer::Structures
{
using namespace DirectX::SimpleMath;
Expand All @@ -12,6 +15,12 @@ namespace TEN::Renderer::Structures
int Flags;
std::wstring String;
Vector4 Color;
float Scale;
Vector2 Scale;
float Rotation = 0.0f;
int Priority = 0;
BlendMode Blend = BlendMode::AlphaBlend;

bool HasScissor = false;
RendererRectangle ScissorRect = {};
};
}
Loading