Added scaling and clamp support

This commit is contained in:
Pasalc 2023-11-13 19:25:17 +03:00
parent 4212095335
commit 11666abf32
13 changed files with 371 additions and 109 deletions

View File

@ -200,6 +200,8 @@ add_executable(
src/WallpaperEngine/Render/CWallpaper.h
src/WallpaperEngine/Render/CWallpaper.cpp
src/WallpaperEngine/Render/CWallpaperState.h
src/WallpaperEngine/Render/CWallpaperState.cpp
src/WallpaperEngine/Render/CScene.h
src/WallpaperEngine/Render/CScene.cpp
src/WallpaperEngine/Render/CVideo.h

View File

@ -28,10 +28,29 @@ struct option long_options[] = {
{ "noautomute", no_argument, nullptr, 'm' },
{ "no-fullscreen-pause", no_argument, nullptr, 'n' },
{ "disable-mouse", no_argument, nullptr, 'e' },
{ "clamp-strategy", required_argument, nullptr, 't' },
{ "scaling", required_argument, nullptr, 't' },
{ "clamping", required_argument, nullptr, 't' },
{ nullptr, 0, nullptr, 0 }
};
/* std::hash::operator() isn't constexpr, so it can't be used to get hash values as compile-time constants
* So here is customHash. It skips all spaces, so hashes for " find " and "fi nd" are the same
* Basicly got it from here: https://stackoverflow.com/questions/8317508/hash-function-for-a-string
*/
constexpr size_t customHash(const char* str) {
constexpr size_t A = 54059; /* a prime */
constexpr size_t B = 76963; /* another prime */
constexpr size_t C = 86969; /* yet another prime */
constexpr size_t FIRSTH = 37; /* also prime */
size_t hash = FIRSTH;
while (*str) {
if(*str != ' ') // Skip spaces
hash = (hash * A) ^ (*str * B);
++str;
}
return hash % C;
}
std::string stringPathFixes (const std::string& s)
{
if (s.empty ())
@ -66,7 +85,8 @@ CApplicationContext::CApplicationContext (int argc, char* argv[])
.mode = NORMAL_WINDOW,
.maximumFPS = 30,
.pauseOnFullscreen = true,
.window = { .geometry = {}, .clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs, .scaleToFit=false },
.window = { .geometry = {}, .clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs,
.scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::DefaultUVs, },
},
.audio =
{
@ -105,6 +125,7 @@ CApplicationContext::CApplicationContext (int argc, char* argv[])
// no need to check for previous screen being in the list, as it's the only way for this variable
// to have any value
this->settings.general.screenBackgrounds[lastScreen] = translateBackground (optarg);
this->settings.general.screenScalings[lastScreen] = this->settings.render.window.scalingMode;
break;
case 'o':
@ -133,6 +154,7 @@ CApplicationContext::CApplicationContext (int argc, char* argv[])
this->settings.render.mode = DESKTOP_BACKGROUND;
lastScreen = optarg;
this->settings.general.screenBackgrounds[lastScreen] = "";
this->settings.general.screenScalings[lastScreen] = this->settings.render.window.scalingMode;
break;
case 'w':
@ -196,25 +218,38 @@ CApplicationContext::CApplicationContext (int argc, char* argv[])
break;
case 't':
{
char opt = optarg[0];
switch (opt)
{
case 's':/* stretch*/
this->settings.render.window.scaleToFit=true;
break;
case 'b':/* clamp border (crop black)*/
this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVsBorder;//clampStrategy(optarg);
break;
case 'c':/* clamp*/
this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs;
break;
case 'r':
this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::NoFlags;
break;
default:
sLog.error("Wrong argument provided for clamp-strategy");
break;
{
size_t hash = customHash(optarg);
// Use a switch statement with the hash
switch (hash) {
// --scale options
case customHash("stretch"):
this->settings.render.window.scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::StretchUVs;
break;
case customHash("fit"):
this->settings.render.window.scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::ZoomFitUVs;
break;
case customHash("fill"):
this->settings.render.window.scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::ZoomFillUVs;
break;
case customHash("default"):
this->settings.render.window.scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::DefaultUVs;
break;
// --clamp options
case customHash("clamp"):
this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs;
break;
case customHash("border"):
this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVsBorder;
break;
case customHash("repeat"):
this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::NoFlags;
break;
default:
sLog.error("Wrong argument:");
sLog.error(optarg);
sLog.exception("Wrong argument provided for --scale or --clamp option.");
break;
}
}
break;
@ -314,5 +349,8 @@ void CApplicationContext::printHelp (const char* route)
sLog.out ("\t--set-property <name=value>\tOverrides the default value of the given property");
sLog.out ("\t--no-fullscreen-pause\tPrevents the background pausing when an app is fullscreen");
sLog.out ("\t--disable-mouse\tDisables mouse interactions");
sLog.out ("\t--clamp-strategy <strategy>\t Clamp strategy if wallpaper doesn't fit screen. Can be stretch, border, repeat, clamp. Can be shortend to s, b, r, c. Default is clamp");
sLog.out ("\t--scaling <mode>\t Scaling mode for wallpaper. Can be stretch, fit, fill, default. Must be used before wallpaper provided.\n\
\t\t For default wallpaper last specified value will be used.\n\
\t\t Example: ./wallengine --scaling stretch --screen-root eDP-1 --bg 2667198601 --scaling fill --screen-root eDP-2 2667198602");
sLog.out ("\t--clamping <mode>\t Clamping mode for all wallpapers. Can be clamp, border, repeat. Enables GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, GL_REPEAT accordingly. Default is clamp.");
}

View File

@ -12,6 +12,7 @@
#include "CApplicationState.h"
#include "WallpaperEngine/Assets/ITexture.h"
#include "WallpaperEngine/Render/CWallpaperState.h"
namespace WallpaperEngine::Application
{
@ -52,6 +53,8 @@ namespace WallpaperEngine::Application
std::map <std::string, std::filesystem::path> screenBackgrounds;
/** Properties to change values for */
std::map <std::string, std::string> properties;
/** The scaling mode for different screens */
std::map <std::string, WallpaperEngine::Render::CWallpaperState::TextureUVsScaling> screenScalings;
} general;
/**
@ -71,7 +74,7 @@ namespace WallpaperEngine::Application
/** The window size used in explicit window */
glm::ivec4 geometry;
WallpaperEngine::Assets::ITexture::TextureFlags clamp;
bool scaleToFit;
WallpaperEngine::Render::CWallpaperState::TextureUVsScaling scalingMode;
} window;
} render;

View File

@ -322,13 +322,13 @@ namespace WallpaperEngine::Application
for (const auto& it : this->m_backgrounds)
context->setWallpaper (
it.first,
WallpaperEngine::Render::CWallpaper::fromWallpaper (it.second->getWallpaper (), *context, *audioContext)
WallpaperEngine::Render::CWallpaper::fromWallpaper (it.second->getWallpaper (), *context, *audioContext, this->m_context.settings.general.screenScalings[it.first])
);
// set the default rendering wallpaper if available
if (this->m_defaultBackground != nullptr)
context->setDefaultWallpaper (WallpaperEngine::Render::CWallpaper::fromWallpaper (
this->m_defaultBackground->getWallpaper (), *context, *audioContext
this->m_defaultBackground->getWallpaper (), *context, *audioContext, this->m_context.settings.render.window.scalingMode
));
static time_t seconds;

View File

@ -36,9 +36,9 @@ namespace WallpaperEngine::Render
// render the background
if (ref != this->m_wallpapers.end ())
ref->second->render (viewport->viewport, this->getOutput ().renderVFlip (), this->getApp().getContext().settings.render.window.scaleToFit);
ref->second->render (viewport->viewport, this->getOutput ().renderVFlip ());
else
this->m_defaultWallpaper->render (viewport->viewport, this->getOutput ().renderVFlip (), this->getApp().getContext().settings.render.window.scaleToFit);
this->m_defaultWallpaper->render (viewport->viewport, this->getOutput ().renderVFlip ());
#if !NDEBUG
glPopDebugGroup ();

View File

@ -6,6 +6,8 @@
#include "WallpaperEngine/Render/Objects/CImage.h"
#include "WallpaperEngine/Render/Objects/CSound.h"
#include "WallpaperEngine/Render/CWallpaperState.h"
#include "CScene.h"
extern float g_Time;
@ -14,8 +16,8 @@ extern float g_TimeLast;
using namespace WallpaperEngine;
using namespace WallpaperEngine::Render;
CScene::CScene (Core::CScene* scene, CRenderContext& context, CAudioContext& audioContext) :
CWallpaper (scene, Type, context, audioContext),
CScene::CScene (Core::CScene* scene, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode) :
CWallpaper (scene, Type, context, audioContext, scalingMode),
m_mousePosition (),
m_mousePositionLast (),
m_parallaxDisplacement ()

View File

@ -15,7 +15,7 @@ namespace WallpaperEngine::Render
class CScene : public CWallpaper
{
public:
CScene (Core::CScene* scene, CRenderContext& context, CAudioContext& audioContext);
CScene (Core::CScene* scene, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode);
CCamera* getCamera () const;

View File

@ -11,8 +11,8 @@ void* get_proc_address (void* ctx, const char* name)
return static_cast<CVideo*> (ctx)->getContext ().getDriver ().getProcAddress (name);
}
CVideo::CVideo (Core::CVideo* video, CRenderContext& context, CAudioContext& audioContext) :
CWallpaper (video, Type, context, audioContext),
CVideo::CVideo (Core::CVideo* video, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode) :
CWallpaper (video, Type, context, audioContext, scalingMode),
m_width (16),
m_height (16),
m_mpvGl (nullptr)

View File

@ -12,7 +12,7 @@ namespace WallpaperEngine::Render
class CVideo : public CWallpaper
{
public:
CVideo (Core::CVideo* video, CRenderContext& context, CAudioContext& audioContext);
CVideo (Core::CVideo* video, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode);
Core::CVideo* getVideo ();

View File

@ -9,7 +9,7 @@
using namespace WallpaperEngine::Render;
CWallpaper::CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRenderContext& context, CAudioContext& audioContext) :
CWallpaper::CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode) :
CContextAware (context),
m_wallpaperData (wallpaperData),
m_type (std::move(type)),
@ -22,7 +22,8 @@ CWallpaper::CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRend
a_Position (GL_NONE),
a_TexCoord (GL_NONE),
m_vaoBuffer (GL_NONE),
m_audioContext (audioContext)
m_audioContext (audioContext),
m_state(scalingMode)
{
// generate the VAO to stop opengl from complaining
glGenVertexArrays (1, &this->m_vaoBuffer);
@ -201,78 +202,26 @@ void CWallpaper::setupShaders ()
this->a_TexCoord = glGetAttribLocation (this->m_shader, "a_TexCoord");
}
void CWallpaper::updateTexCoord (GLfloat* texCoords, GLsizeiptr size) const
{
glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
glBufferData (GL_ARRAY_BUFFER, size, texCoords, GL_STATIC_DRAW);
}
void CWallpaper::setDestinationFramebuffer (GLuint framebuffer)
{
this->m_destFramebuffer = framebuffer;
}
void CWallpaper::setTextureUVs(const glm::ivec4& viewport, const bool vflip, const bool scale,
float& ustart, float& uend, float& vstart, float& vend){
ustart = 0.0f;
uend = 1.0f;
vstart = 1.0f;
vend = 0.0f;
if (vflip){
vstart = 0.0f;
vend = 1.0f;
}
if(!scale){
uint32_t projectionWidth = this->getWidth ();
uint32_t projectionHeight = this->getHeight ();
const float m1 = float(viewport.z) / projectionWidth;
const float m2 = float(viewport.w) / projectionHeight;
const float m = std::max(m1,m2);
projectionWidth*=m;
projectionHeight*=m;
if (projectionWidth!=viewport.z)
{
int newWidth = viewport.w / (float) projectionHeight * projectionWidth;
float newCenter = newWidth / 2.0f;
float viewportCenter = viewport.z / 2.0;
float left = newCenter - viewportCenter;
float right = newCenter + viewportCenter;
ustart = left / newWidth;
uend = right / newWidth;
}
if (projectionHeight!=viewport.w)
{
int newHeight = viewport.z / (float) projectionWidth * projectionHeight;
float newCenter = newHeight / 2.0f;
float viewportCenter = viewport.w / 2.0;
float down = newCenter - viewportCenter;
float up = newCenter + viewportCenter;
if (vflip)
{
vstart = down / newHeight;
vend = up / newHeight;
}
else
{
vstart = up / newHeight;
vend = down / newHeight;
}
}
void CWallpaper::updateUVs(const glm::ivec4& viewport, const bool vflip){
//update UVs if something has changed, otherwise use old values
if(this->m_state.hasChanged(viewport, vflip, this->getWidth(), this->getHeight())){
// Update wallpaper state
this->m_state.updateState(viewport, vflip, this->getWidth(), this->getHeight());
}
}
void CWallpaper::render (glm::ivec4 viewport, bool vflip, bool scale)
void CWallpaper::render (glm::ivec4 viewport, bool vflip)
{
this->renderFrame (viewport);
//Update UVs coordinates according to scaling mode of this wallpaper
updateUVs(viewport,vflip);
auto [ ustart, uend, vstart, vend ] = this->m_state.getTextureUVs();
float ustart,uend,vstart,vend;
setTextureUVs(viewport, vflip, scale, ustart, uend, vstart, vend);
GLfloat texCoords [] = {
ustart, vstart,
uend, vstart,
@ -363,12 +312,12 @@ CFBO* CWallpaper::getFBO () const
return this->m_sceneFBO;
}
CWallpaper* CWallpaper::fromWallpaper (Core::CWallpaper* wallpaper, CRenderContext& context, CAudioContext& audioContext)
CWallpaper* CWallpaper::fromWallpaper (Core::CWallpaper* wallpaper, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode)
{
if (wallpaper->is <Core::CScene> ())
return new WallpaperEngine::Render::CScene (wallpaper->as <Core::CScene> (), context, audioContext);
return new WallpaperEngine::Render::CScene (wallpaper->as <Core::CScene> (), context, audioContext, scalingMode);
else if (wallpaper->is <Core::CVideo> ())
return new WallpaperEngine::Render::CVideo (wallpaper->as <Core::CVideo> (), context, audioContext);
return new WallpaperEngine::Render::CVideo (wallpaper->as <Core::CVideo> (), context, audioContext, scalingMode);
else
sLog.exception ("Unsupported wallpaper type");
}

View File

@ -14,6 +14,8 @@
#include "WallpaperEngine/Render/CFBO.h"
#include "WallpaperEngine/Render/Helpers/CContextAware.h"
#include "CWallpaperState.h"
using namespace WallpaperEngine::Assets;
using namespace WallpaperEngine::Audio;
@ -34,15 +36,10 @@ namespace WallpaperEngine::Render
~CWallpaper ();
/**
* Get texture UV coordinates for render
*/
void setTextureUVs(const glm::ivec4& viewport, const bool vflip, const bool scale,
float& ustart, float& uend, float& vstart, float& vend);
/**
* Performs a render pass of the wallpaper
*/
void render (glm::ivec4 viewport, bool vflip, bool scale);
void render (glm::ivec4 viewport, bool vflip);
/**
* @return The container to resolve files for this wallpaper
@ -88,9 +85,9 @@ namespace WallpaperEngine::Render
[[nodiscard]] CFBO* getFBO () const;
/**
* Updates the texcoord used for drawing to the used framebuffer
* Updates the UVs coordinates if window/screen/vflip/projection has changed
*/
void updateTexCoord (GLfloat* texCoords, GLsizeiptr size) const;
void updateUVs (const glm::ivec4& viewport, const bool vflip);
/**
* Updates the destination framebuffer for this wallpaper
@ -116,10 +113,10 @@ namespace WallpaperEngine::Render
*
* @return
*/
static CWallpaper* fromWallpaper (Core::CWallpaper* wallpaper, CRenderContext& context, CAudioContext& audioContext);
static CWallpaper* fromWallpaper (Core::CWallpaper* wallpaper, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode);
protected:
CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRenderContext& context, CAudioContext& audioContext);
CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode);
/**
* Renders a frame of the wallpaper
@ -158,5 +155,7 @@ namespace WallpaperEngine::Render
std::map<std::string, CFBO*> m_fbos;
/** Audio context that is using this wallpaper */
CAudioContext& m_audioContext;
/** Current Wallpaper state */
CWallpaperState m_state;
};
}

View File

@ -0,0 +1,170 @@
#include "CWallpaperState.h"
#include <algorithm>
#include "WallpaperEngine/Logging/CLog.h"
using namespace WallpaperEngine::Render;
// Reset UVs to 0/1 values
void CWallpaperState::resetUVs(){
this->UVs.ustart=0;
this->UVs.uend=1;
if (vflip){
this->UVs.vstart = 0.0f;
this->UVs.vend = 1.0f;
}
else{
this->UVs.vstart=1.0f;
this->UVs.vend=0.0f;
}
}
// Update Us coordinates for current viewport and projection
void CWallpaperState::updateUs(const int& projectionWidth, const int& projectionHeight){
const float viewportWidth = this->getViewportWidth();
const float viewportHeight = this->getViewportHeight();
int newWidth = viewportHeight / projectionHeight * projectionWidth;
float newCenter = newWidth / 2.0f;
float viewportCenter = viewportWidth / 2.0;
float left = newCenter - viewportCenter;
float right = newCenter + viewportCenter;
this->UVs.ustart = left / newWidth;
this->UVs.uend = right / newWidth;
}
// Update Vs coordinates for current viewport and projection
void CWallpaperState::updateVs(const int& projectionWidth, const int& projectionHeight){
const float viewportWidth = this->getViewportWidth();
const float viewportHeight = this->getViewportHeight();
int newHeight = viewportWidth / projectionWidth * projectionHeight;
float newCenter = newHeight / 2.0f;
float viewportCenter = viewportHeight / 2.0;
float down = newCenter - viewportCenter;
float up = newCenter + viewportCenter;
if (vflip)
{
this->UVs.vstart = down / newHeight;
this->UVs.vend = up / newHeight;
}
else
{
this->UVs.vstart = up / newHeight;
this->UVs.vend = down / newHeight;
}
}
template<> void CWallpaperState::updateTextureUVs<CWallpaperState::TextureUVsScaling::StretchUVs>(){
this->resetUVs();
}
template<> void CWallpaperState::updateTextureUVs<CWallpaperState::TextureUVsScaling::ZoomFillUVs>(){
this->resetUVs();
const int viewportWidth = this->getViewportWidth();
const int viewportHeight = this->getViewportHeight();
uint32_t projectionWidth = this->getProjectionWidth();
uint32_t projectionHeight = this->getProjectionHeight();
const float m1 = static_cast<float>(viewportWidth) / projectionWidth;
const float m2 = static_cast<float>(viewportHeight) / projectionHeight;
const float m = std::max(m1,m2);
projectionWidth*=m;
projectionHeight*=m;
if (projectionWidth!=viewportWidth)
{
this->updateUs(projectionWidth,projectionHeight);
}
else if (projectionHeight!=viewportHeight)
{
this->updateVs(projectionWidth,projectionHeight);
}
}
template<> void CWallpaperState::updateTextureUVs<CWallpaperState::TextureUVsScaling::ZoomFitUVs>(){
this->resetUVs();
const int viewportWidth = this->getViewportWidth();
const int viewportHeight = this->getViewportHeight();
uint32_t projectionWidth = this->getProjectionWidth();
uint32_t projectionHeight = this->getProjectionHeight();
const float m1 = static_cast<float>(viewportWidth) / projectionWidth;
const float m2 = static_cast<float>(viewportHeight) / projectionHeight;
const float m = std::min(m1,m2);
projectionWidth*=m;
projectionHeight*=m;
if (projectionWidth!=viewportWidth)
{
this->updateUs(projectionWidth,projectionHeight);
}
else if (projectionHeight!=viewportHeight)
{
this->updateVs(projectionWidth,projectionHeight);
}
}
template<> void CWallpaperState::updateTextureUVs<CWallpaperState::TextureUVsScaling::DefaultUVs>(){
this->resetUVs();
const int viewportWidth = this->getViewportWidth();
const int viewportHeight = this->getViewportHeight();
uint32_t projectionWidth = this->getProjectionWidth();
uint32_t projectionHeight = this->getProjectionHeight();
if (
(viewportHeight > viewportWidth && projectionWidth >= projectionHeight) ||
(viewportWidth > viewportHeight && projectionHeight > projectionWidth)
)
{
updateUs(projectionWidth,projectionHeight);
}
if (
(viewportWidth > viewportHeight && projectionWidth >= projectionHeight) ||
(viewportHeight > viewportWidth && projectionHeight > projectionWidth)
)
{
updateVs(projectionWidth,projectionHeight);
}
}
template<CWallpaperState::TextureUVsScaling T> void CWallpaperState::updateTextureUVs(){
sLog.exception("Using generic template for scaling is not allowed. Write specialization template for your scaling mode.\
This message is for developers, if you are just user it's a bug.");
}
void CWallpaperState::updateState(const glm::ivec4& viewport, const bool& vflip, const int& projectionWidth, const int& projectionHeight){
this->viewport.width = viewport.z;
this->viewport.height = viewport.w;
this->vflip = vflip;
this->projection.width = projectionWidth;
this->projection.height = projectionHeight;
//Set texture UVs according to choosen scaling mode for this wallpaper
switch (this->getTextureUVsScaling())
{
case CWallpaperState::TextureUVsScaling::StretchUVs :
this->updateTextureUVs<CWallpaperState::TextureUVsScaling::StretchUVs>();
break;
case CWallpaperState::TextureUVsScaling::ZoomFillUVs :
this->updateTextureUVs<CWallpaperState::TextureUVsScaling::ZoomFillUVs>();
break;
case CWallpaperState::TextureUVsScaling::ZoomFitUVs :
this->updateTextureUVs<CWallpaperState::TextureUVsScaling::ZoomFitUVs>();
break;
case CWallpaperState::TextureUVsScaling::DefaultUVs :
this->updateTextureUVs<CWallpaperState::TextureUVsScaling::DefaultUVs>();
break;
default:
sLog.exception("Switch case for specified scaling mode doesn't exist. Add your realisation in switch statement.\
This message is for developers, if you are just user it's a bug.");
break;
}
}

View File

@ -0,0 +1,99 @@
#pragma once
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/vec4.hpp>
namespace WallpaperEngine::Render
{
/**
* Represents current wallpaper state
*/
class CWallpaperState
{
public:
// Scaling modes. Defines how UVs coordinates are calculated.
enum class TextureUVsScaling : uint8_t
{
DefaultUVs,
ZoomFitUVs,
ZoomFillUVs,
StretchUVs,
};
CWallpaperState(const TextureUVsScaling& textureUVsMode) : m_textureUVsMode(textureUVsMode)
{};
// Compares saved state values with passed arguments
bool hasChanged(const glm::ivec4& viewport, const bool& vflip, const int& projectionWidth, const int& projectionHeight) const{
return this->viewport.width != viewport.z || this->viewport.height != viewport.w ||
this->projection.width != projectionWidth || this->projection.height != projectionHeight || this->vflip != vflip;
}
// Reset UVs to 0/1 values
void resetUVs();
// Update Us coordinates for current viewport and projection
void updateUs(const int& projectionWidth, const int& projectionHeight);
// Update Vs coordinates for current viewport and projection
void updateVs(const int& projectionWidth, const int& projectionHeight);
// Get texture UV coordinates
auto getTextureUVs() const {return UVs;};
// Set texture UV coordinates according to texture scaling mode
template<CWallpaperState::TextureUVsScaling> void updateTextureUVs();
// Updates state with provided values
void updateState(const glm::ivec4& viewport, const bool& vflip, const int& projectionWidth, const int& projectionHeight);
// @return The texture scaling mode
TextureUVsScaling getTextureUVsScaling () const { return m_textureUVsMode; };
// Set texture scaling mode
void setTextureUVsStrategy(const TextureUVsScaling strategy) { m_textureUVsMode=strategy; } ;
// @return The width of viewport
int getViewportWidth () const { return viewport.width;};
// @return The height of viewport
int getViewportHeight () const { return viewport.height;};
// @return The width of viewport
uint32_t getProjectionWidth () const { return projection.width;};
// @return The height of viewport
uint32_t getProjectionHeight () const { return projection.height;};
private:
// Cached UVs value for texture coordinates. No need to recalculate if viewport and projection haven't changed.
struct
{
float ustart;
float uend;
float vstart;
float vend;
} UVs;
// Viewport for which UVs were calculated
struct
{
int width;
int height;
} viewport{};
// Wallpaper dimensions
struct
{
uint32_t width;
uint32_t height;
} projection{};
// Are Vs coordinates fliped
bool vflip = false;
// Texture scaling mode
TextureUVsScaling m_textureUVsMode = TextureUVsScaling::DefaultUVs;
};
}