Clip texture before rendering.
This commit is contained in:
parent
8af4e432e7
commit
a1e507ef12
1 changed files with 101 additions and 5 deletions
106
src/texture.cpp
106
src/texture.cpp
|
@ -65,11 +65,48 @@ namespace cloonel {
|
|||
GraphicFormat enumvalue;
|
||||
};
|
||||
|
||||
struct RectFloat {
|
||||
float2 from;
|
||||
float2 to;
|
||||
|
||||
RectFloat ( void ) = default;
|
||||
RectFloat ( const RectFloat& parOther ) :
|
||||
from(parOther.from),
|
||||
to(parOther.to)
|
||||
{
|
||||
assert(IsValid());
|
||||
}
|
||||
|
||||
RectFloat ( const SDL_Rect& parRect ) :
|
||||
from(static_cast<float>(parRect.x), static_cast<float>(parRect.y)),
|
||||
to(static_cast<float>(parRect.x + parRect.w), static_cast<float>(parRect.y + parRect.h))
|
||||
{
|
||||
assert(IsValid());
|
||||
}
|
||||
|
||||
RectFloat ( const float2& parFrom, const float2& parTo ) :
|
||||
from(parFrom),
|
||||
to(parTo)
|
||||
{
|
||||
assert(IsValid());
|
||||
}
|
||||
|
||||
~RectFloat ( void ) noexcept = default;
|
||||
|
||||
operator SDL_Rect ( void ) const noexcept { return { static_cast<int>(from.x()), static_cast<int>(from.y()), static_cast<int>(Width()), static_cast<int>(Height()) }; }
|
||||
|
||||
float Width ( void ) const noexcept { return to.x() - from.x(); }
|
||||
float Height ( void ) const noexcept { return to.y() - from.y(); }
|
||||
float2 WidthHeight ( void ) const noexcept { return float2(Width(), Height()); }
|
||||
bool IsValid ( void ) const noexcept { return from <= to; }
|
||||
};
|
||||
|
||||
const GraphicFormatItem g_graphicFormatItems[] = {
|
||||
{".png", 4, GraphicFormat_Png}
|
||||
};
|
||||
|
||||
GraphicFormat GuessGraphicFormatFromName (const std::string& parPath) __attribute__((pure));
|
||||
bool ClipRect ( RectFloat& parSrc, RectFloat& parDest, const RectFloat& parClip );
|
||||
|
||||
///----------------------------------------------------------------------
|
||||
///----------------------------------------------------------------------
|
||||
|
@ -210,6 +247,47 @@ namespace cloonel {
|
|||
|
||||
return retSurf;
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------
|
||||
///Adjustes parSrc and parDest so that parDest will fit into parClip and
|
||||
///parSrc to be the relevant part of the source texture to be drawn.
|
||||
///Returns true if such operation was possible and parSrc and parDest
|
||||
///got set to a valid value, otherwise false.
|
||||
///----------------------------------------------------------------------
|
||||
bool ClipRect (RectFloat& parSrc, RectFloat& parDest, const RectFloat& parClip) {
|
||||
assert(parSrc.IsValid());
|
||||
assert(parDest.IsValid());
|
||||
|
||||
//If the dest rect is completely out of the clipping region, there
|
||||
//is nothing to do at all.
|
||||
if (parDest.to <= parClip.from or parDest.from >= parClip.to)
|
||||
return false;
|
||||
|
||||
{
|
||||
const RectFloat clip(float2(0.0f), float2(1.0f));
|
||||
const float2 srcWidthHeight(parSrc.WidthHeight());
|
||||
const float2 scaledOffs((parDest.from - parClip.from) / parClip.WidthHeight());
|
||||
parSrc.from -= float2(std::min(0.0f, scaledOffs.x() * srcWidthHeight.x()), std::min(0.0f, scaledOffs.y() * srcWidthHeight.y()));
|
||||
const float2 scaledCrop((parClip.to - parDest.to) / parClip.WidthHeight());
|
||||
parSrc.to += float2(std::min(0.0f, scaledCrop.x() * srcWidthHeight.x()), std::min(0.0f, scaledCrop.y() * srcWidthHeight.y()));
|
||||
assert(parSrc.IsValid());
|
||||
}
|
||||
|
||||
RectFloat dst(parDest.from - parClip.from, parDest.to - parClip.from);
|
||||
dst.from.x() = std::max(dst.from.x(), parClip.from.x());
|
||||
dst.from.y() = std::max(dst.from.y(), parClip.from.y());
|
||||
dst.to.x() = std::min(dst.to.x(), parClip.to.x());
|
||||
dst.to.y() = std::min(dst.to.y(), parClip.to.y());
|
||||
|
||||
if (not dst.IsValid())
|
||||
return false;
|
||||
|
||||
parDest.from += parClip.from;
|
||||
parDest.to += parClip.from;
|
||||
|
||||
assert(parDest.IsValid());
|
||||
return true;
|
||||
}
|
||||
} //unnamed namespace
|
||||
|
||||
///--------------------------------------------------------------------------
|
||||
|
@ -271,10 +349,28 @@ namespace cloonel {
|
|||
///--------------------------------------------------------------------------
|
||||
void Texture::Render (const float2& parPos, const float2& parSize, const float2& parScaling) const {
|
||||
assert(IsLoaded());
|
||||
const ushort2 pos(static_cast<ushort2>(parPos * parScaling + 0.5f));
|
||||
const ushort2 siz(static_cast<ushort2>(parSize * parScaling + 0.5f));
|
||||
const int screenHeight = m_sdlmain->WidthHeight().y();
|
||||
const SDL_Rect dest = { pos.x(), screenHeight - pos.y() - siz.y(), siz.x(), siz.y() };
|
||||
SDL_RenderCopy(m_sdlmain->GetRenderer(), m_texture, nullptr, &dest);
|
||||
|
||||
const float2 pos(parPos * parScaling);
|
||||
const float2 siz(parSize * parScaling);
|
||||
RectFloat dest(pos, pos + siz);
|
||||
RectFloat src(float2(0.0f), m_size);
|
||||
|
||||
const RectFloat clip(float2(0.0f), static_cast<float2>(m_sdlmain->WidthHeight()));
|
||||
const bool visible = ClipRect(src, dest, clip);
|
||||
if (not visible)
|
||||
return;
|
||||
|
||||
const SDL_Rect sdlsrc(src);
|
||||
//std::cout << "src = " << src.from << " - " << src.to << ", size is " << m_size << "\n";
|
||||
SDL_Rect sdldst(dest);
|
||||
sdldst.y = m_sdlmain->WidthHeight().y() - sdldst.y - sdldst.h;
|
||||
|
||||
//By here everything is nice and clean
|
||||
assert(sdlsrc.x >= 0 and sdlsrc.y >= 0);
|
||||
assert(sdlsrc.w >= 0 and sdlsrc.w <= static_cast<int>(m_size.x()));
|
||||
assert(sdlsrc.h >= 0 and sdlsrc.h <= static_cast<int>(m_size.y()));
|
||||
assert(sdlsrc.x + sdlsrc.w <= m_sdlmain->WidthHeight().x());
|
||||
assert(sdlsrc.y + sdlsrc.h <= m_sdlmain->WidthHeight().y());
|
||||
SDL_RenderCopy(m_sdlmain->GetRenderer(), m_texture, &sdlsrc, &sdldst);
|
||||
}
|
||||
} //namespace cloonel
|
||||
|
|
Loading…
Reference in a new issue