215 lines
6.1 KiB
C++
215 lines
6.1 KiB
C++
#include "Sprite.h"
|
||
#include "EngineCore/Game.h"
|
||
#include "Text.h"
|
||
#include "EngineFrame/Render/RenderManager.h"
|
||
|
||
void Sprite::Init()
|
||
{
|
||
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();
|
||
m_texture->Init(imgPath, Index);
|
||
Init();
|
||
CalcRenderInfoLogic(); // 第一次计算
|
||
}
|
||
|
||
Sprite::Sprite(std::string PngPath)
|
||
{
|
||
m_texture = new Texture();
|
||
m_texture->Init(PngPath);
|
||
Init();
|
||
CalcRenderInfoLogic(); // 第一次计算
|
||
}
|
||
|
||
Sprite::~Sprite()
|
||
{
|
||
}
|
||
|
||
RefPtr<Texture> Sprite::GetTexture()
|
||
{
|
||
return m_texture;
|
||
}
|
||
|
||
GlMatrix Sprite::matrix3x2ToGLMatrix(const Matrix3x2 &mat)
|
||
{
|
||
return {
|
||
// 列0:x轴线性变换
|
||
mat._11, // [0][0]
|
||
mat._12, // [1][0]
|
||
0.0f, // [2][0]
|
||
0.0f, // [3][0]
|
||
|
||
// 列1:y轴线性变换
|
||
mat._21, // [0][1]
|
||
mat._22, // [1][1]
|
||
0.0f, // [2][1]
|
||
0.0f, // [3][1]
|
||
|
||
// 列2:z轴(固定)
|
||
0.0f, // [0][2]
|
||
0.0f, // [1][2]
|
||
1.0f, // [2][2]
|
||
0.0f, // [3][2]
|
||
|
||
// 列3:平移
|
||
mat._31, // [0][3](x平移)
|
||
mat._32, // [1][3](y平移)
|
||
0.0f, // [2][3]
|
||
1.0f // [3][3]
|
||
};
|
||
}
|
||
|
||
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;
|
||
|
||
// X轴和Y轴上是否翻转的标志
|
||
bool flipX = scaleX < 0;
|
||
bool flipY = scaleY < 0;
|
||
|
||
_RenderGuidanceInfo.flip = SDL_FLIP_NONE;
|
||
// 更新翻转状态
|
||
if (flipX)
|
||
_RenderGuidanceInfo.flip = static_cast<SDL_RendererFlip>(SDL_FLIP_HORIZONTAL | _RenderGuidanceInfo.flip);
|
||
if (flipY)
|
||
_RenderGuidanceInfo.flip = static_cast<SDL_RendererFlip>(SDL_FLIP_VERTICAL | _RenderGuidanceInfo.flip);
|
||
|
||
// 纹理数据里带的偏移数据 有这个偏移才能保证动画播放时视觉中心点在一个点上
|
||
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;
|
||
float RealPosY = transform.position.y + texturePosY;
|
||
|
||
// 计算在世界中的位置
|
||
float baseX = transformIter.position.x + RealPosX;
|
||
float baseY = transformIter.position.y + RealPosY;
|
||
|
||
// 获取当前帧的原始尺寸
|
||
int frameWidth = Size.width;
|
||
int frameHeight = Size.height;
|
||
|
||
// 原始锚点偏移(基于帧尺寸)
|
||
float origAnchorOffsetX = int(frameWidth * Anchor.x);
|
||
float origAnchorOffsetY = int(frameHeight * Anchor.y);
|
||
|
||
// 缩放的绝对值
|
||
float absScaleX = SDL_fabs(scaleX);
|
||
float absScaleY = SDL_fabs(scaleY);
|
||
// 缩放后的尺寸
|
||
float scaledWidth = frameWidth * absScaleX;
|
||
float scaledHeight = frameHeight * absScaleY;
|
||
// 缩放后的锚点偏移
|
||
float scaledAnchorOffsetX = int(origAnchorOffsetX * absScaleX);
|
||
float scaledAnchorOffsetY = int(origAnchorOffsetY * absScaleY);
|
||
|
||
// 计算缩放后的锚点偏移与原锚点偏移的差值
|
||
float scaleOffsetX = scaledAnchorOffsetX - origAnchorOffsetX;
|
||
float scaleOffsetY = scaledAnchorOffsetY - origAnchorOffsetY;
|
||
|
||
// 最终位置计算:世界位置 + 缩放锚点差值 - 缩放后的锚点偏移 + 纹理数据里带的偏移数据 (计算出绘制点的左上角)
|
||
float Xpos = baseX - scaleOffsetX;
|
||
float Ypos = baseY - scaleOffsetY;
|
||
|
||
Xpos = (int)Xpos; // 强制转换为整数
|
||
Ypos = (int)Ypos; // 强制转换为整数
|
||
|
||
// 更新渲染信息
|
||
_RenderGuidanceInfo.rect = {Xpos, Ypos, scaledWidth, scaledHeight};
|
||
_RenderGuidanceInfo.AnchorPos = {scaledAnchorOffsetX, scaledAnchorOffsetY};
|
||
// 设置纹理透明度
|
||
m_texture->setAlpha(this->Alpha);
|
||
|
||
// 屏幕内检测
|
||
int screenWidth = Game::GetInstance().Screen_W;
|
||
int screenHeight = Game::GetInstance().Screen_H;
|
||
bool isInScreen = (Xpos + scaledWidth >= 0 && Xpos <= screenWidth && Ypos + scaledHeight >= 0 && Ypos <= screenHeight);
|
||
_RenderGuidanceInfo.IsInScreen = isInScreen;
|
||
|
||
// this->Size = {scaledWidth, scaledHeight};
|
||
_RenderGuidanceInfo.rotation = transformIter.rotation + transform.rotation;
|
||
|
||
CalcRenderInfoFlag = false;
|
||
}
|
||
|
||
void Sprite::PreRender()
|
||
{
|
||
if (CalcRenderInfoFlag && Visible)
|
||
CalcRenderInfoLogic();
|
||
}
|
||
|
||
void Sprite::Render()
|
||
{
|
||
if (!Visible)
|
||
return;
|
||
if (!m_texture)
|
||
return;
|
||
|
||
RenderManager *renderer = Game::GetInstance().GetRenderer();
|
||
|
||
if (_RenderGuidanceInfo.IsInScreen && _RenderGuidanceInfo.Visible)
|
||
{
|
||
SDL_FPoint AnchorPos;
|
||
AnchorPos.x = _RenderGuidanceInfo.AnchorPos.x;
|
||
AnchorPos.y = _RenderGuidanceInfo.AnchorPos.y;
|
||
|
||
// 混合
|
||
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);
|
||
}
|
||
}
|
||
|
||
void Sprite::Clear()
|
||
{
|
||
}
|
||
|
||
|
||
|
||
void Sprite::Blend()
|
||
{
|
||
switch (this->_BlendMode)
|
||
{
|
||
case LINEARDODGE:
|
||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
|
||
break;
|
||
}
|
||
}
|