修改底层渲染为OpenGL
This commit is contained in:
@@ -67,20 +67,20 @@ void Animation::Init(std::string AniPath)
|
||||
// TODO 染色
|
||||
|
||||
// 判断是否有Als
|
||||
// if (Asset_Script::GetInstance().GetFileInfo(AniPath + ".als"))
|
||||
// {
|
||||
// AniScriptParser::AlsInfo Info = AssetManager::GetInstance().StructAlsInfo(AniPath + ".als");
|
||||
// if (Info.AniList.size() > 0)
|
||||
// {
|
||||
// std::string Dir = AniPath.substr(0, AniPath.find_last_of("/") + 1);
|
||||
// for (auto &Ani : Info.AniList)
|
||||
// {
|
||||
// RefPtr<Animation> AlsAniObj = new Animation(Dir + Ani.second.path);
|
||||
// AlsAniObj->SetRenderZOrder(Ani.second.layer[1]);
|
||||
// AddChild(AlsAniObj);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if (Asset_Script::GetInstance().GetFileInfo(AniPath + ".als"))
|
||||
{
|
||||
AniScriptParser::AlsInfo Info = AssetManager::GetInstance().StructAlsInfo(AniPath + ".als");
|
||||
if (Info.AniList.size() > 0)
|
||||
{
|
||||
std::string Dir = AniPath.substr(0, AniPath.find_last_of("/") + 1);
|
||||
for (auto &Ani : Info.AniList)
|
||||
{
|
||||
RefPtr<Animation> AlsAniObj = new Animation(Dir + Ani.second.path);
|
||||
AlsAniObj->SetRenderZOrder(Ani.second.layer[1]);
|
||||
AddChild(AlsAniObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
FlushFrame(0);
|
||||
}
|
||||
|
||||
@@ -133,20 +133,7 @@ void Animation::Update(float deltaTime)
|
||||
|
||||
void Animation::Render()
|
||||
{
|
||||
if (!Visible)
|
||||
return;
|
||||
// 是否裁切
|
||||
if (CropFlag)
|
||||
{
|
||||
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
|
||||
SDL_RenderSetClipRect(renderer, &CropRect);
|
||||
Actor::Render();
|
||||
SDL_RenderSetClipRect(renderer, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
Actor::Render();
|
||||
}
|
||||
Actor::Render();
|
||||
}
|
||||
|
||||
void Animation::OnAdded(BaseNode *node)
|
||||
@@ -210,7 +197,7 @@ void Animation::FlushFrame(int Index)
|
||||
// 线性减淡
|
||||
if (FlagBuf.count("GRAPHIC_EFFECT_LINEARDODGE"))
|
||||
{
|
||||
CurrentFrame->SetBlendMode(SDL_BLENDMODE_ADD);
|
||||
CurrentFrame->SetBlendMode(LINEARDODGE);
|
||||
}
|
||||
// 旋转
|
||||
if (FlagBuf.count("IMAGE_ROTATE"))
|
||||
@@ -328,22 +315,3 @@ void Animation::InterpolationLogic()
|
||||
CurrentFrame->SetRotation(OldAngleData + (NewAngleData - OldAngleData) * InterRate);
|
||||
}
|
||||
}
|
||||
|
||||
void Animation::SetClipRect(SDL_Rect clipRect)
|
||||
{
|
||||
CropFlag = true;
|
||||
CropRect = clipRect;
|
||||
}
|
||||
|
||||
void Animation::UnsetClipRect()
|
||||
{
|
||||
CropFlag = false;
|
||||
}
|
||||
|
||||
void Animation::SetShadow()
|
||||
{
|
||||
for (auto &Sp : SpriteArr)
|
||||
{
|
||||
Sp->SetShadow();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,13 +43,6 @@ public:
|
||||
// TODO SetDye
|
||||
// TODO SetCrop
|
||||
|
||||
// 设置裁切区域
|
||||
void SetClipRect(SDL_Rect clipRect);
|
||||
// 取消裁切区域
|
||||
void UnsetClipRect();
|
||||
// 设置阴影
|
||||
void SetShadow();
|
||||
|
||||
public:
|
||||
// Ani是否可用
|
||||
bool IsUsability = true;
|
||||
@@ -95,10 +88,6 @@ public:
|
||||
// DyeFrameList = null;
|
||||
// // 整体染色
|
||||
// DyeAllFlag = false;
|
||||
// // 裁切数据
|
||||
SDL_Rect CropRect = {0, 0, 0, 0};
|
||||
// 裁切Flag
|
||||
bool CropFlag = false;
|
||||
|
||||
// 附加选项
|
||||
std::function<std::string(std::string, Animation::ReplaceData)> AdditionalOptions;
|
||||
|
||||
@@ -3,13 +3,6 @@
|
||||
|
||||
AnimationManager::AnimationManager()
|
||||
{
|
||||
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
|
||||
m_Texture = SDL_CreateTexture(
|
||||
renderer,
|
||||
SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_TEXTUREACCESS_TARGET,
|
||||
Game::GetInstance().Screen_W,
|
||||
Game::GetInstance().Screen_H);
|
||||
}
|
||||
|
||||
void AnimationManager::PreRender()
|
||||
@@ -65,35 +58,7 @@ void AnimationManager::PreRender()
|
||||
|
||||
void AnimationManager::Render()
|
||||
{
|
||||
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
|
||||
// 设定渲染目标为纹理
|
||||
SDL_SetRenderTarget(renderer, m_Texture);
|
||||
|
||||
SDL_RenderClear(renderer);
|
||||
// 渲染所有子对象
|
||||
Actor::Render();
|
||||
// 恢复渲染目标为默认窗口
|
||||
SDL_SetRenderTarget(renderer, nullptr);
|
||||
|
||||
SDL_Rect srcRect = {
|
||||
static_cast<int>(m_RenderRect.x), // 子对象包围盒左上角X(纹理中的位置)
|
||||
static_cast<int>(m_RenderRect.y), // 子对象包围盒左上角Y(纹理中的位置)
|
||||
static_cast<int>(m_RenderRect.w), // 包围盒宽度(有效区域宽度)
|
||||
static_cast<int>(m_RenderRect.h) // 包围盒高度(有效区域高度)
|
||||
};
|
||||
|
||||
// SDL_FRect renderToWindow = {
|
||||
// m_RenderRect.x, // 窗口上的X位置(可自定义)
|
||||
// m_RenderRect.y, // 窗口上的Y位置(可自定义)
|
||||
// m_RenderRect.w, // 渲染到窗口的宽度(与源区域等大)
|
||||
// m_RenderRect.h // 渲染到窗口的高度(与源区域等大)
|
||||
// };
|
||||
SDL_FRect renderToWindow = {
|
||||
0, 0, 1080, 720};
|
||||
|
||||
// SDL_Log("m_Texture rect: %f %f %f %f", renderToWindow.x, renderToWindow.y, renderToWindow.w, renderToWindow.h);
|
||||
// SDL_RenderCopyF(renderer, m_Texture, &srcRect, &renderToWindow);
|
||||
SDL_RenderCopyF(renderer, m_Texture, NULL, &renderToWindow);
|
||||
}
|
||||
|
||||
void AnimationManager::AddAnimation(RefPtr<Animation> ani)
|
||||
|
||||
62
source/EngineFrame/Component/Canvas.cpp
Normal file
62
source/EngineFrame/Component/Canvas.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include "Canvas.h"
|
||||
#include "EngineCore/Game.h"
|
||||
#include "EngineFrame/Render/RenderManager.h"
|
||||
Canvas::Canvas(VecSize size)
|
||||
{
|
||||
m_texture = new Texture();
|
||||
m_texture->Init(size);
|
||||
m_sprite = new Sprite();
|
||||
m_sprite->SetTexture(m_texture);
|
||||
|
||||
Actor::Init();
|
||||
|
||||
glGenFramebuffers(1, &m_fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
||||
// 将目标纹理附加到FBO的颜色附着点
|
||||
glFramebufferTexture2D(
|
||||
GL_FRAMEBUFFER, // 帧缓冲类型
|
||||
GL_COLOR_ATTACHMENT0, // 颜色附着点(可多个,这里用第一个)
|
||||
GL_TEXTURE_2D, // 纹理类型
|
||||
m_texture->getID(), // 目标纹理ID
|
||||
0 // 多级渐远纹理级别
|
||||
);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0); // 解绑FBO
|
||||
}
|
||||
|
||||
void Canvas::PreRender()
|
||||
{
|
||||
if (m_dirty)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); // 绑定FBO
|
||||
// glViewport(0, 0, m_texture->getSize().width, m_texture->getSize().height);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // 全透明黑色
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
Actor::PreRender();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sprite->PreRender();
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::Render()
|
||||
{
|
||||
if (m_dirty)
|
||||
{
|
||||
|
||||
Actor::Render();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0); // 解绑FBO
|
||||
// glViewport(0, 0, Game::GetInstance().Screen_W, Game::GetInstance().Screen_H);
|
||||
m_dirty = false;
|
||||
}
|
||||
RenderManager *renderer = Game::GetInstance().GetRenderer();
|
||||
renderer->SetCurrentShaderProgram("flip_y");
|
||||
m_sprite->Render();
|
||||
renderer->SetCurrentShaderProgram("normal");
|
||||
}
|
||||
|
||||
void Canvas::AddChild(RefPtr<BaseNode> child)
|
||||
{
|
||||
m_dirty = true;
|
||||
Actor::AddChild(child);
|
||||
}
|
||||
23
source/EngineFrame/Component/Canvas.h
Normal file
23
source/EngineFrame/Component/Canvas.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include "EngineFrame/Actor/Actor.h"
|
||||
#include "EngineFrame/Render/Texture.h"
|
||||
#include "EngineFrame/Component/Sprite.h"
|
||||
class Canvas : public Actor
|
||||
{
|
||||
private:
|
||||
/**纹理 */
|
||||
RefPtr<Texture> m_texture = nullptr;
|
||||
/**精灵 */
|
||||
RefPtr<Sprite> m_sprite = nullptr;
|
||||
/**脏标记 */
|
||||
bool m_dirty = true;
|
||||
/**FBO */
|
||||
GLuint m_fbo = 0;
|
||||
|
||||
public:
|
||||
Canvas(VecSize size);
|
||||
|
||||
void PreRender() override;
|
||||
void Render() override;
|
||||
void AddChild(RefPtr<BaseNode> child) override;
|
||||
};
|
||||
@@ -1,25 +1,35 @@
|
||||
#include "Sprite.h"
|
||||
#include "EngineCore/Game.h"
|
||||
#include "Text.h"
|
||||
#include "EngineFrame/Render/RenderManager.h"
|
||||
|
||||
void Sprite::Init()
|
||||
{
|
||||
this->Size = m_texture->TextureSize;
|
||||
this->Size = m_texture->getSize();
|
||||
RenderBase::Init();
|
||||
}
|
||||
|
||||
void Sprite::SetTexture(RefPtr<Texture> texture)
|
||||
{
|
||||
m_texture = texture;
|
||||
Init();
|
||||
CalcRenderInfoLogic(); // 第一次计算
|
||||
}
|
||||
|
||||
Sprite::Sprite(std::string imgPath, int Index)
|
||||
{
|
||||
this->imgPath = imgPath;
|
||||
this->Index = Index;
|
||||
m_texture = new Texture(imgPath, Index);
|
||||
m_texture = new Texture();
|
||||
m_texture->Init(imgPath, Index);
|
||||
Init();
|
||||
CalcRenderInfoLogic(); // 第一次计算
|
||||
}
|
||||
|
||||
Sprite::Sprite(std::string PngPath)
|
||||
{
|
||||
m_texture = new Texture(PngPath);
|
||||
m_texture = new Texture();
|
||||
m_texture->Init(PngPath);
|
||||
Init();
|
||||
CalcRenderInfoLogic(); // 第一次计算
|
||||
}
|
||||
@@ -35,6 +45,19 @@ RefPtr<Texture> Sprite::GetTexture()
|
||||
|
||||
void Sprite::CalcRenderInfoLogic()
|
||||
{
|
||||
// 获取至在最终的父对象检查是否显示
|
||||
BaseNode *parentNode = this->GetParent();
|
||||
while (parentNode != nullptr)
|
||||
{
|
||||
if (parentNode->Visible == false)
|
||||
{
|
||||
_RenderGuidanceInfo.Visible = false;
|
||||
return;
|
||||
}
|
||||
parentNode = parentNode->GetParent();
|
||||
}
|
||||
_RenderGuidanceInfo.Visible = true;
|
||||
|
||||
// 计算缩放因子和翻转状态
|
||||
float scaleX = transformIter.scale.x * transform.scale.x;
|
||||
float scaleY = transformIter.scale.y * transform.scale.y;
|
||||
@@ -51,8 +74,10 @@ void Sprite::CalcRenderInfoLogic()
|
||||
_RenderGuidanceInfo.flip = static_cast<SDL_RendererFlip>(SDL_FLIP_VERTICAL | _RenderGuidanceInfo.flip);
|
||||
|
||||
// 纹理数据里带的偏移数据 有这个偏移才能保证动画播放时视觉中心点在一个点上
|
||||
float texturePosX = flipX ? -(m_texture->TextureSize.width + m_texture->TexturePos.x) + SDL_abs(transform.position.x * 2) : m_texture->TexturePos.x;
|
||||
float texturePosY = flipY ? -(m_texture->TextureSize.height + m_texture->TexturePos.y) + SDL_abs(transform.position.y * 2) : m_texture->TexturePos.y;
|
||||
auto T_Size = m_texture->getSize();
|
||||
auto T_Pos = m_texture->getPos();
|
||||
float texturePosX = flipX ? -(T_Size.width + T_Pos.x) + SDL_abs(transform.position.x * 2) : T_Pos.x;
|
||||
float texturePosY = flipY ? -(T_Size.height + T_Pos.y) + SDL_abs(transform.position.y * 2) : T_Pos.y;
|
||||
|
||||
// 先计算Img坐标与精灵坐标合成后的真实坐标
|
||||
float RealPosX = transform.position.x + texturePosX;
|
||||
@@ -93,13 +118,9 @@ void Sprite::CalcRenderInfoLogic()
|
||||
|
||||
// 更新渲染信息
|
||||
_RenderGuidanceInfo.rect = {Xpos, Ypos, scaledWidth, scaledHeight};
|
||||
|
||||
// 如果有阴影 计算阴影的渲染信息
|
||||
if (ShadowFlag)
|
||||
CalculateShadowData();
|
||||
_RenderGuidanceInfo.AnchorPos = {scaledAnchorOffsetX, scaledAnchorOffsetY};
|
||||
// 设置纹理透明度
|
||||
SDL_SetTextureAlphaMod(m_texture->GetTexture(), this->Alpha * 255);
|
||||
m_texture->setAlpha(this->Alpha);
|
||||
|
||||
// 屏幕内检测
|
||||
int screenWidth = Game::GetInstance().Screen_W;
|
||||
@@ -113,17 +134,6 @@ void Sprite::CalcRenderInfoLogic()
|
||||
CalcRenderInfoFlag = false;
|
||||
}
|
||||
|
||||
void Sprite::SetClipRect(SDL_Rect clipRect)
|
||||
{
|
||||
CropFlag = true;
|
||||
CropRect = clipRect;
|
||||
}
|
||||
|
||||
void Sprite::UnsetClipRect()
|
||||
{
|
||||
CropFlag = false;
|
||||
}
|
||||
|
||||
void Sprite::PreRender()
|
||||
{
|
||||
if (CalcRenderInfoFlag && Visible)
|
||||
@@ -134,32 +144,26 @@ void Sprite::Render()
|
||||
{
|
||||
if (!Visible)
|
||||
return;
|
||||
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
|
||||
if (!m_texture)
|
||||
return;
|
||||
|
||||
RenderManager *renderer = Game::GetInstance().GetRenderer();
|
||||
|
||||
if (_RenderGuidanceInfo.IsInScreen && _RenderGuidanceInfo.Visible)
|
||||
{
|
||||
// 如果有阴影绘制阴影
|
||||
if (ShadowFlag)
|
||||
{
|
||||
std::array<int, 6> indices = {0, 1, 2, 1, 3, 2};
|
||||
SDL_RenderGeometry(renderer, m_texture->GetTexture(), vertices.data(), vertices.size(), indices.data(), indices.size());
|
||||
}
|
||||
SDL_FPoint AnchorPos = _RenderGuidanceInfo.AnchorPos;
|
||||
|
||||
// 混合
|
||||
if (this->_BlendMode != NONE)
|
||||
Blend();
|
||||
|
||||
SDL_Rect srcrect = {0, 0, this->Size.width, this->Size.height};
|
||||
renderer->DrawTexture(m_texture, &srcrect, &_RenderGuidanceInfo.rect, _RenderGuidanceInfo.rotation, &AnchorPos, _RenderGuidanceInfo.flip);
|
||||
|
||||
// 还原混合
|
||||
if (this->_BlendMode != NONE)
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
if (_RenderGuidanceInfo.rotation != 0.f || _RenderGuidanceInfo.flip != SDL_FLIP_NONE)
|
||||
{
|
||||
SDL_FPoint AnchorPos = _RenderGuidanceInfo.AnchorPos;
|
||||
SDL_RenderCopyExF(renderer, m_texture->GetTexture(), NULL, &_RenderGuidanceInfo.rect, _RenderGuidanceInfo.rotation, &AnchorPos, _RenderGuidanceInfo.flip);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_RenderCopyF(renderer, m_texture->GetTexture(), NULL, &_RenderGuidanceInfo.rect);
|
||||
// // 设置绘制颜色
|
||||
// SDL_SetRenderDrawColor(renderer, 255, 0, 0, 128);
|
||||
// // 绘制填充矩形
|
||||
// SDL_RenderFillRectF(renderer, &_RenderGuidanceInfo.rect);
|
||||
}
|
||||
Game::GetInstance().m_RenderCount++;
|
||||
}
|
||||
}
|
||||
@@ -168,72 +172,22 @@ void Sprite::Clear()
|
||||
{
|
||||
}
|
||||
|
||||
void Sprite::SetBlendMode(SDL_BlendMode blendMode)
|
||||
void Sprite::SetBlendMode(LE_BlEND_MODE mode)
|
||||
{
|
||||
if (GetBlendMode() != blendMode)
|
||||
m_texture->SetBlendMode(blendMode);
|
||||
this->_BlendMode = mode;
|
||||
}
|
||||
|
||||
SDL_BlendMode Sprite::GetBlendMode()
|
||||
void Sprite::Blend()
|
||||
{
|
||||
return m_texture->GetBlendMode();
|
||||
}
|
||||
|
||||
void Sprite::SetShadow()
|
||||
{
|
||||
ShadowFlag = true;
|
||||
CalcRenderInfo();
|
||||
}
|
||||
|
||||
void Sprite::CalculateShadowData()
|
||||
{
|
||||
const float shearX = 1.3f;
|
||||
SDL_FRect guidance = _RenderGuidanceInfo.rect;
|
||||
float shadowW = guidance.w; // 影子宽度(建议与角色宽度一致)
|
||||
float shadowH = guidance.h * 0.33; // 影子高度(可根据需求调整,比如角色高度的1/4)
|
||||
|
||||
// 计算角色脚部中点坐标(底部中心,即需要重叠的锚点)
|
||||
float roleFootX = guidance.x + guidance.w / 2.0f + 3; // 角色X中心 + 位置偏移
|
||||
float roleFootY = guidance.y + guidance.h - 5; // 角色底部Y坐标(脚的位置)
|
||||
|
||||
// 计算错切后的顶点(局部坐标)
|
||||
vertices = {
|
||||
// 左上角(局部坐标)
|
||||
SDL_Vertex{{0.0f, 0.0f}, {0, 0, 0, 110}, {0.0f, 0.0f}},
|
||||
// 右上角(局部坐标)
|
||||
SDL_Vertex{{shadowW, 0.0f}, {0, 0, 0, 110}, {1.0f, 0.0f}},
|
||||
// 左下角(局部坐标)
|
||||
SDL_Vertex{{0.0f + shearX * shadowH, shadowH}, {0, 0, 0, 110}, {0.0f, 1.0f}},
|
||||
// 右下角(局部坐标)
|
||||
SDL_Vertex{{shadowW + shearX * shadowH, shadowH}, {0, 0, 0, 110}, {1.0f, 1.0f}}};
|
||||
|
||||
bool flipHorizontal = (_RenderGuidanceInfo.flip & SDL_FLIP_HORIZONTAL) != 0; // 检查水平翻转标志
|
||||
bool flipVertical = (_RenderGuidanceInfo.flip & SDL_FLIP_VERTICAL) != 0; // 检查垂直翻转标志
|
||||
// 应用纹理坐标翻转(核心逻辑)
|
||||
for (auto &v : vertices)
|
||||
switch (this->_BlendMode)
|
||||
{
|
||||
// 水平翻转:反转u坐标(0→1,1→0)
|
||||
if (flipHorizontal)
|
||||
{
|
||||
v.tex_coord.x = 1.0f - v.tex_coord.x;
|
||||
}
|
||||
// 垂直翻转:反转v坐标(0→1,1→0)
|
||||
if (flipVertical)
|
||||
{
|
||||
v.tex_coord.y = 1.0f - v.tex_coord.y;
|
||||
}
|
||||
}
|
||||
|
||||
// 计算影子底部中点并对齐角色脚部(与之前逻辑一致)
|
||||
float shadowFootX = (vertices[2].position.x + vertices[3].position.x) / 2.0f;
|
||||
float shadowFootY = shadowH;
|
||||
float offsetX = roleFootX - shadowFootX;
|
||||
float offsetY = roleFootY - shadowFootY;
|
||||
|
||||
// 应用位置偏移
|
||||
for (auto &v : vertices)
|
||||
{
|
||||
v.position.x += offsetX;
|
||||
v.position.y += offsetY;
|
||||
case LINEARDODGE:
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LE_BlEND_MODE Sprite::GetBlendMode()
|
||||
{
|
||||
return this->_BlendMode;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ class Game;
|
||||
/**
|
||||
* @brief Sprite类,继承自Component类,用于表示游戏中的精灵组件
|
||||
*/
|
||||
class Sprite : public RenderBase
|
||||
class Sprite : public RenderBase
|
||||
{
|
||||
protected:
|
||||
RefPtr<Texture> m_texture = nullptr;
|
||||
@@ -22,36 +22,26 @@ public:
|
||||
void PreRender() override;
|
||||
void Clear() override;
|
||||
void Init() override;
|
||||
void SetTexture(RefPtr<Texture> texture);
|
||||
|
||||
RefPtr<Texture> GetTexture();
|
||||
|
||||
public:
|
||||
// 渲染信息
|
||||
RenderGuidanceInfo _RenderGuidanceInfo;
|
||||
// 裁切数据
|
||||
SDL_Rect CropRect = {0, 0, 0, 0};
|
||||
// 裁切Flag
|
||||
bool CropFlag = false;
|
||||
// 阴影数据
|
||||
std::array<SDL_Vertex, 4> vertices;
|
||||
// 阴影Flag
|
||||
bool ShadowFlag = false;
|
||||
// 混合模式
|
||||
LE_BlEND_MODE _BlendMode = NONE;
|
||||
|
||||
std::string imgPath;
|
||||
int Index;
|
||||
|
||||
public:
|
||||
// 计算渲染信息
|
||||
void CalcRenderInfoLogic();
|
||||
// 设置裁切区域
|
||||
void SetClipRect(SDL_Rect clipRect);
|
||||
// 取消裁切区域
|
||||
void UnsetClipRect();
|
||||
// 设置混合模式
|
||||
void SetBlendMode(SDL_BlendMode blendMode);
|
||||
void SetBlendMode(LE_BlEND_MODE mode);
|
||||
// 混合
|
||||
void Blend();
|
||||
// 获取混合模式
|
||||
SDL_BlendMode GetBlendMode();
|
||||
// 设置阴影
|
||||
void SetShadow();
|
||||
// 计算阴影数据
|
||||
void CalculateShadowData();
|
||||
LE_BlEND_MODE GetBlendMode();
|
||||
};
|
||||
|
||||
@@ -5,200 +5,56 @@ Text::Text()
|
||||
{
|
||||
}
|
||||
|
||||
Text::Text(std::string Str, TTF_Font *font, SDL_Color color)
|
||||
{
|
||||
m_text = Str;
|
||||
m_font = font;
|
||||
m_text_color = color;
|
||||
Init(Str, font, color);
|
||||
}
|
||||
|
||||
Text::Text(std::string Str, TTF_Font *font, SDL_Color textColor, SDL_Color strokeColor, int strokeSize)
|
||||
{
|
||||
m_text = Str;
|
||||
m_font = font;
|
||||
m_text_color = textColor;
|
||||
m_stroke_color = strokeColor;
|
||||
m_stroke_size = strokeSize;
|
||||
Init(Str, font, textColor, strokeColor, strokeSize);
|
||||
}
|
||||
|
||||
Text::~Text()
|
||||
{
|
||||
}
|
||||
|
||||
void Text::Init(std::string Str, TTF_Font *font, SDL_Color color)
|
||||
{
|
||||
// 标记该组件需要渲染和更新
|
||||
addTag(Tag::RENDER);
|
||||
addTag(Tag::UPDATE);
|
||||
|
||||
// TTF_SetFontOutline(font, 1);
|
||||
if (!m_texture)
|
||||
{
|
||||
this->m_font = font;
|
||||
this->m_color = color;
|
||||
}
|
||||
// 先渲染为表面
|
||||
SDL_Surface *textSurface = TTF_RenderUTF8_Blended(font, Str.c_str(), color);
|
||||
if (!textSurface)
|
||||
{
|
||||
SDL_LogError(0, "文字渲染为表面失败!TTF_Error:%s", TTF_GetError());
|
||||
}
|
||||
// 转换为RGBA8888格式(与OpenGL的GL_RGBA匹配)
|
||||
SDL_Surface *rgbaSurface = SDL_ConvertSurfaceFormat(
|
||||
textSurface,
|
||||
SDL_PIXELFORMAT_ABGR8888,
|
||||
0);
|
||||
|
||||
SDL_FreeSurface(textSurface);
|
||||
// 再将表面转换为纹理
|
||||
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
|
||||
m_texture = SDL_CreateTextureFromSurface(renderer, textSurface);
|
||||
if (!m_texture)
|
||||
{
|
||||
SDL_LogError(0, "表面转换为纹理失败!SDL_Error:%s", SDL_GetError());
|
||||
}
|
||||
// 设置纹理过滤模式为最近邻,避免缩放模糊
|
||||
SDL_SetTextureScaleMode(m_texture, SDL_ScaleModeNearest);
|
||||
Size.x = textSurface->w;
|
||||
Size.y = textSurface->h;
|
||||
TextureSize.x = textSurface->w;
|
||||
TextureSize.y = textSurface->h;
|
||||
|
||||
RenderManager *renderer = Game::GetInstance().GetRenderer();
|
||||
m_texture = new Texture;
|
||||
m_texture->Init(rgbaSurface);
|
||||
// 释放表面
|
||||
SDL_FreeSurface(textSurface);
|
||||
}
|
||||
|
||||
void Text::Init(std::string Str, TTF_Font *font, SDL_Color textColor, SDL_Color strokeColor, int strokeSize)
|
||||
{
|
||||
// 先保存原始字体的轮廓设置
|
||||
int originalOutline = TTF_GetFontOutline(font);
|
||||
|
||||
// 设置字体轮廓大小(描边宽度)
|
||||
TTF_SetFontOutline(font, strokeSize);
|
||||
|
||||
// 渲染描边(使用描边颜色)
|
||||
SDL_Surface *strokeSurface = TTF_RenderUTF8_Blended(font, Str.c_str(), strokeColor);
|
||||
if (!strokeSurface)
|
||||
{
|
||||
SDL_LogError(0, "描边渲染为表面失败!TTF_Error:%s", TTF_GetError());
|
||||
TTF_SetFontOutline(font, originalOutline); // 恢复原始设置
|
||||
return;
|
||||
}
|
||||
|
||||
// 恢复字体轮廓设置,用于渲染文字本身
|
||||
TTF_SetFontOutline(font, 0);
|
||||
|
||||
// 渲染文字本身(使用文字颜色)
|
||||
SDL_Surface *textSurface = TTF_RenderUTF8_Blended(font, Str.c_str(), textColor);
|
||||
if (!textSurface)
|
||||
{
|
||||
SDL_LogError(0, "文字渲染为表面失败!TTF_Error:%s", TTF_GetError());
|
||||
SDL_FreeSurface(strokeSurface);
|
||||
TTF_SetFontOutline(font, originalOutline); // 恢复原始设置
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建一个合并描边和文字的表面
|
||||
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
|
||||
|
||||
// 计算最终纹理大小(描边会增加额外尺寸)
|
||||
int finalWidth = strokeSurface->w;
|
||||
int finalHeight = strokeSurface->h;
|
||||
|
||||
// 创建一个临时表面用于合并描边和文字
|
||||
SDL_Surface *finalSurface = SDL_CreateRGBSurfaceWithFormat(
|
||||
0, finalWidth, finalHeight, 32, SDL_PIXELFORMAT_RGBA32);
|
||||
if (!finalSurface)
|
||||
{
|
||||
SDL_LogError(0, "创建最终表面失败!SDL_Error:%s", SDL_GetError());
|
||||
SDL_FreeSurface(textSurface);
|
||||
SDL_FreeSurface(strokeSurface);
|
||||
TTF_SetFontOutline(font, originalOutline);
|
||||
return;
|
||||
}
|
||||
|
||||
// 将描边绘制到最终表面
|
||||
SDL_Rect strokeRect = {0, 0, strokeSurface->w, strokeSurface->h};
|
||||
SDL_BlitSurface(strokeSurface, nullptr, finalSurface, &strokeRect);
|
||||
|
||||
// 计算文字在描边中间的位置
|
||||
SDL_Rect textRect = {
|
||||
strokeSize, // X偏移(描边宽度)
|
||||
strokeSize, // Y偏移(描边宽度)
|
||||
textSurface->w,
|
||||
textSurface->h};
|
||||
SDL_BlitSurface(textSurface, nullptr, finalSurface, &textRect);
|
||||
|
||||
// 将合并后的表面转换为纹理
|
||||
m_texture = SDL_CreateTextureFromSurface(renderer, finalSurface);
|
||||
if (!m_texture)
|
||||
{
|
||||
SDL_LogError(0, "表面转换为纹理失败!SDL_Error:%s", SDL_GetError());
|
||||
}
|
||||
|
||||
// 设置尺寸信息
|
||||
Size.x = finalSurface->w;
|
||||
Size.y = finalSurface->h;
|
||||
TextureSize.x = finalSurface->w;
|
||||
TextureSize.y = finalSurface->h;
|
||||
|
||||
// 释放所有临时表面
|
||||
SDL_FreeSurface(textSurface);
|
||||
SDL_FreeSurface(strokeSurface);
|
||||
SDL_FreeSurface(finalSurface);
|
||||
|
||||
// 恢复字体原始轮廓设置
|
||||
TTF_SetFontOutline(font, originalOutline);
|
||||
}
|
||||
|
||||
void Text::HandleEvents(SDL_Event *e)
|
||||
{
|
||||
}
|
||||
|
||||
void Text::Update(float deltaTime)
|
||||
{
|
||||
SDL_FreeSurface(rgbaSurface);
|
||||
Sprite::Init();
|
||||
}
|
||||
|
||||
void Text::Render()
|
||||
{
|
||||
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
|
||||
if (!renderer || !m_texture)
|
||||
return;
|
||||
SDL_Rect dstrect = {Pos.x, Pos.y, Size.x, Size.y};
|
||||
|
||||
SDL_RenderCopy(renderer, m_texture, NULL, &dstrect);
|
||||
}
|
||||
|
||||
void Text::Clear()
|
||||
{
|
||||
}
|
||||
|
||||
void Text::SetPos(SDL_Point pos)
|
||||
{
|
||||
Pos = pos;
|
||||
}
|
||||
|
||||
SDL_Point Text::GetPos()
|
||||
{
|
||||
return Pos;
|
||||
Sprite::Render();
|
||||
}
|
||||
|
||||
void Text::SetText(std::string Str)
|
||||
{
|
||||
if (Str == m_text)
|
||||
return;
|
||||
if (!m_font)
|
||||
{
|
||||
SDL_LogError(0, "SetText失败:字体指针为空!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果有原纹理先删除原纹理
|
||||
if (m_texture)
|
||||
{
|
||||
SDL_DestroyTexture(m_texture);
|
||||
m_texture = nullptr; // 置空指针
|
||||
}
|
||||
m_text = Str;
|
||||
// 根据是否有描边选择对应的Init方法
|
||||
if (m_stroke_size > 0)
|
||||
{
|
||||
Init(Str, m_font, m_text_color, m_stroke_color, m_stroke_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
Init(Str, m_font, m_text_color);
|
||||
}
|
||||
Init(Str, m_font, m_color);
|
||||
}
|
||||
|
||||
std::string Text::GetText()
|
||||
|
||||
@@ -1,59 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
#include "EngineFrame/Component/Component.h"
|
||||
class Game;
|
||||
#include "EngineFrame/Component/Sprite.h"
|
||||
|
||||
class Text : public Component
|
||||
class Text : public Sprite
|
||||
{
|
||||
private:
|
||||
/* data */
|
||||
SDL_Texture *m_texture = nullptr;
|
||||
|
||||
public:
|
||||
Text(/* args */);
|
||||
Text(std::string Str, TTF_Font *font, SDL_Color color);
|
||||
Text(std::string Str, TTF_Font *font, SDL_Color textColor, SDL_Color strokeColor, int strokeSize);
|
||||
~Text();
|
||||
|
||||
// 显式引入基类的Init方法,避免隐藏
|
||||
using Component::Init;
|
||||
void Init(std::string Str, TTF_Font *font, SDL_Color color);
|
||||
void Init(std::string Str, TTF_Font *font, SDL_Color textColor, SDL_Color strokeColor, int strokeSize);
|
||||
void HandleEvents(SDL_Event *e) override;
|
||||
void Update(float deltaTime) override;
|
||||
void Render() override;
|
||||
void Clear() override;
|
||||
|
||||
SDL_Texture *GetTexture();
|
||||
|
||||
public:
|
||||
// 组件标签
|
||||
Tag m_tag = Tag::RENDER | Tag::UPDATE; // 标记该组件需要渲染和更新
|
||||
|
||||
/** 文本内容 */
|
||||
std::string m_text;
|
||||
/** 字体 */
|
||||
TTF_Font *m_font;
|
||||
SDL_Color m_text_color;
|
||||
SDL_Color m_stroke_color;
|
||||
int m_stroke_size = 0;
|
||||
|
||||
SDL_Point Pos = {0, 0}; // 位置坐标
|
||||
SDL_Point TextureSize = {0, 0}; // 纹理大小
|
||||
SDL_Point Size = {0, 0}; // 大小
|
||||
SDL_Point Anchor = {0, 0}; // 中心点
|
||||
float Angle = 0.0f; // 旋转角度
|
||||
SDL_RendererFlip flip = SDL_FLIP_NONE; // 翻转
|
||||
/** 字体颜色 */
|
||||
SDL_Color m_color;
|
||||
|
||||
public:
|
||||
// 设置坐标
|
||||
void SetPos(SDL_Point pos);
|
||||
// 设置文本
|
||||
void SetText(std::string Str);
|
||||
|
||||
// 获取坐标
|
||||
SDL_Point GetPos();
|
||||
// 获取文本
|
||||
std::string GetText();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user