Cleanup of code:

- use of auto in some places (more of this to come)
 - use for loops instead of iterators for most of the loops
 - extracted glfw/glew code into it's own class
 - make usage of std::filesystem instead of checking things with old C libraries

Signed-off-by: Alexis Maiquez <almamu@almamu.com>
This commit is contained in:
Alexis Maiquez 2023-02-03 18:41:51 +01:00
parent d370e028ff
commit a24b1923f6
33 changed files with 727 additions and 916 deletions

View File

@ -37,6 +37,9 @@ add_executable(
linux-wallpaperengine
main.cpp
src/Steam/FileSystem/FileSystem.h
src/Steam/FileSystem/FileSystem.cpp
src/WallpaperEngine/Logging/CLog.cpp
src/WallpaperEngine/Logging/CLog.h
@ -83,6 +86,10 @@ add_executable(
src/WallpaperEngine/Render/Shaders/Compiler.h
src/WallpaperEngine/Render/Shaders/Compiler.cpp
src/WallpaperEngine/Render/Drivers/COpenGLDriver.h
src/WallpaperEngine/Render/Drivers/COpenGLDriver.cpp
src/WallpaperEngine/Render/Drivers/CVideoDriver.h
src/WallpaperEngine/Render/Drivers/CVideoDriver.cpp
src/WallpaperEngine/Render/CRenderContext.h
src/WallpaperEngine/Render/CRenderContext.cpp
src/WallpaperEngine/Render/CTextureCache.h

307
main.cpp
View File

@ -1,15 +1,16 @@
#include <iostream>
#include <getopt.h>
#include <stdlib.h>
#include <unistd.h>
#include <SDL_mixer.h>
#include <SDL.h>
#include <FreeImage.h>
#include <sys/stat.h>
#include <GL/glew.h>
#include <csignal>
#include <GLFW/glfw3.h>
#include <SDL.h>
#include <SDL_mixer.h>
#include <csignal>
#include <filesystem>
#include <getopt.h>
#include <iostream>
#include <libgen.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include "WallpaperEngine/Core/CProject.h"
#include "WallpaperEngine/Render/CRenderContext.h"
@ -22,25 +23,18 @@
#include "WallpaperEngine/Assets/CCombinedContainer.h"
#include "WallpaperEngine/Assets/CPackageLoadException.h"
#include "WallpaperEngine/Render/Drivers/COpenGLDriver.h"
#include "Steam/FileSystem/FileSystem.h"
#include "common.h"
#define WORKSHOP_APP_ID 431960
#define APP_DIRECTORY "wallpaper_engine"
float g_Time;
float g_TimeLast;
bool g_KeepRunning = true;
int g_AudioVolume = 15;
const char* assets_default_paths [] = {
".steam/steam/steamapps/common/wallpaper_engine/assets",
".local/share/Steam/steamapps/common/wallpaper_engine/assets",
nullptr
};
const char* backgrounds_default_paths [] = {
".local/share/Steam/steamapps/workshop/content/431960",
".steam/steam/steamapps/workshop/content/431960",
nullptr
};
void print_help (const char* route)
{
sLog.out ("Usage: ", route, " [options] background_path/background_id");
@ -81,86 +75,11 @@ void signalhandler(int sig)
g_KeepRunning = false;
}
int handleValidatePath (const char* path, std::string& final)
{
char finalPath [PATH_MAX];
char* pointer = realpath (path, finalPath);
if (pointer == nullptr)
return errno;
// ensure the path points to a folder
struct stat pathinfo;
if (stat (finalPath, &pathinfo) != 0)
return errno;
if (!S_ISDIR (pathinfo.st_mode))
return ENOTDIR;
final = finalPath;
return 0;
}
void validatePath(const char* path, std::string& final)
{
int error = handleValidatePath (path, final);
switch (error)
{
case ENOTDIR:
sLog.exception ("Invalid directory, ", path, " is not a folder");
break;
case ENAMETOOLONG:
sLog.exception ("Path ", path, " too long");
break;
case 0:
return;
default:
sLog.exception ("Cannot find the specified folder");
break;
}
}
std::string getHomePath ()
{
char* home = getenv ("HOME");
if (home == nullptr)
sLog.exception ("Cannot find home directory for the current user");
std::string homepath;
validatePath (home, homepath);
return homepath;
}
void initGLFW ()
{
// first of all, initialize the window
if (glfwInit () == GLFW_FALSE)
sLog.exception ("Failed to initialize GLFW");
// initialize freeimage
FreeImage_Initialise (TRUE);
// set some window hints (opengl version to be used)
glfwWindowHint (GLFW_SAMPLES, 4);
glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
if (DEBUG)
glfwWindowHint (GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
}
void addPkg (CCombinedContainer* containers, const std::string& path, std::string pkgfile)
void addPkg (CCombinedContainer* containers, const std::filesystem::path& path, std::string pkgfile)
{
try
{
std::string scene_path = path + pkgfile;
auto scene_path = std::filesystem::path (path) / pkgfile;
// add the package to the list
containers->add (new WallpaperEngine::Assets::CPackage (scene_path));
@ -278,7 +197,7 @@ CVirtualContainer* buildVirtualContainer ()
return container;
}
void takeScreenshot (WallpaperEngine::Render::CWallpaper* wp, const std::string& filename, FREE_IMAGE_FORMAT format)
void takeScreenshot (WallpaperEngine::Render::CWallpaper* wp, const std::filesystem::path& filename, FREE_IMAGE_FORMAT format)
{
GLint width, height;
@ -344,8 +263,8 @@ int main (int argc, char* argv[])
bool shouldListPropertiesAndStop = false;
FREE_IMAGE_FORMAT screenshotFormat = FIF_UNKNOWN;
std::string path;
std::string assetsDir;
std::string screenshotPath;
std::filesystem::path assetsPath;
std::filesystem::path screenshotPath;
static struct option long_options [] = {
{"screen-root", required_argument, 0, 'r'},
@ -413,8 +332,7 @@ int main (int argc, char* argv[])
maximumFPS = atoi (optarg);
break;
case 'a':
assetsDir = optarg;
case 'a': assetsPath = optarg;
break;
case 'v':
@ -444,103 +362,60 @@ int main (int argc, char* argv[])
// validate screenshot file just to make sure
if (shouldTakeScreenshot == true)
{
// ensure the file is one of the supported formats
std::string extension = screenshotPath.substr (screenshotPath.find_last_of (".") + 1);
if (screenshotPath.has_extension () == false)
sLog.exception ("Cannot determine screenshot format");
if (extension == "bmp")
std::string extension = screenshotPath.extension ();
if (extension == ".bmp")
screenshotFormat = FIF_BMP;
else if (extension == "png")
else if (extension == ".png")
screenshotFormat = FIF_PNG;
else if (extension == "jpg" || extension == "jpeg")
else if (extension == ".jpg" || extension == ".jpeg")
screenshotFormat = FIF_JPEG;
else
sLog.exception ("Unsupported screenshot format ", extension);
sLog.exception ("Cannot determine screenshot format, unknown extension ", extension);
}
std::string homepath = getHomePath ();
auto containers = new WallpaperEngine::Assets::CCombinedContainer ();
// check if the background might be an ID and try to find the right path in the steam installation folder
if (path.find ('/') == std::string::npos)
{
for (const char** current = backgrounds_default_paths; *current != nullptr; current ++)
{
std::string tmppath = homepath + "/" + *current + "/" + path;
int error = handleValidatePath (tmppath.c_str (), tmppath);
if (error != 0)
continue;
path = tmppath;
}
}
validatePath (path.c_str (), path);
// add a trailing slash to the path so the right file can be found
path += "/";
path = Steam::FileSystem::workshopDirectory (WORKSHOP_APP_ID, path);
WallpaperEngine::Assets::CCombinedContainer containers;
// the background's path is required to load project.json regardless of the type of background we're using
containers->add (new WallpaperEngine::Assets::CDirectory (path));
containers.add (new WallpaperEngine::Assets::CDirectory (path));
// add the virtual container for mocked up files
containers->add (buildVirtualContainer ());
containers.add (buildVirtualContainer ());
// try to add the common packages
addPkg (containers, path, "scene.pkg");
addPkg (containers, path, "gifscene.pkg");
addPkg (&containers, path, "scene.pkg");
addPkg (&containers, path, "gifscene.pkg");
if (assetsDir.empty () == true)
if (assetsPath.empty () == true)
{
for (const char** current = assets_default_paths; *current != nullptr; current ++)
try
{
std::string tmppath = homepath + "/" + *current;
int error = handleValidatePath (tmppath.c_str (), tmppath);
if (error != 0)
continue;
assetsDir = tmppath;
sLog.out ("Found wallpaper engine's assets at ", assetsDir);
break;
assetsPath = Steam::FileSystem::appDirectory (APP_DIRECTORY, "assets");
}
if (assetsDir.empty () == true)
catch (std::runtime_error)
{
unsigned long len = strlen (argv [0]) + 1;
char* copy = new char[len];
strncpy (copy, argv [0], len);
// path still not found, try one last thing on the current binary's folder
std::string exepath = dirname (copy);
exepath += "/assets";
int error = handleValidatePath (exepath.c_str (), exepath);
if (error == 0)
{
assetsDir = exepath;
sLog.out ("Found assets folder alongside the binary: ", assetsDir);
}
delete[] copy;
// set current path as assets' folder
std::filesystem::path directory = std::filesystem::canonical ("/proc/self/exe")
.parent_path () / "assets";
}
}
else
{
validatePath (assetsDir.c_str (), assetsDir);
sLog.out ("Found wallpaper engine's assets at ", assetsDir, " based on --assets-dir parameter");
sLog.out ("Found wallpaper engine's assets at ", assetsPath, " based on --assets-dir parameter");
}
if (assetsDir.empty () == true)
if (assetsPath.empty () == true)
sLog.exception ("Cannot determine a valid path for the wallpaper engine assets");
// add containers to the list
containers->add (new WallpaperEngine::Assets::CDirectory (assetsDir + "/"));
containers.add (new WallpaperEngine::Assets::CDirectory (assetsPath));
// parse the project.json file
auto project = WallpaperEngine::Core::CProject::fromFile ("project.json", containers);
auto project = WallpaperEngine::Core::CProject::fromFile ("project.json", &containers);
// go to the right folder so the videos will play
if (project->getWallpaper ()->is <WallpaperEngine::Core::CVideo> () == true)
chdir (path.c_str ());
@ -570,98 +445,49 @@ int main (int argc, char* argv[])
std::signal(SIGINT, signalhandler);
std::signal(SIGTERM, signalhandler);
// initialize glfw
initGLFW ();
// auto projection = project->getWallpaper ()->as <WallpaperEngine::Core::CScene> ()->getOrthogonalProjection ();
// create the window!
// TODO: DO WE NEED TO PASS MONITOR HERE OR ANYTHING?
// TODO: FIGURE OUT HOW TO PUT THIS WINDOW IN THE BACKGROUND
GLFWwindow* window = glfwCreateWindow (1920, 1080, "WallpaperEngine", NULL, NULL);
if (window == nullptr)
{
sLog.error ("GLFW", "Failed to open a GLFW window");
glfwTerminate ();
return 2;
}
glfwMakeContextCurrent (window);
// TODO: FIGURE THESE OUT BASED ON THE SCREEN
int windowWidth = 1920;
int windowHeight = 1080;
// get the real framebuffer size
glfwGetFramebufferSize (window, &windowWidth, &windowHeight);
GLenum glewInitResult = glewInit ();
// initialize glew
if (glewInitResult != GLEW_OK)
{
sLog.error ("GLEW", "Failed to initialize GLEW: ", glewGetErrorString (glewInitResult));
glfwTerminate ();
return 3;
}
if (shouldEnableAudio == true && SDL_Init (SDL_INIT_AUDIO) < 0)
{
sLog.error ("SDL", "Cannot initialize SDL audio system, SDL_GetError: ", SDL_GetError());
sLog.error ("SDL", "Continuing without audio support");
sLog.error ("Cannot initialize SDL audio system, SDL_GetError: ", SDL_GetError());
sLog.error ("Continuing without audio support");
}
// initialize OpenGL driver
WallpaperEngine::Render::Drivers::COpenGLDriver videoDriver ("Wallpaper Engine");
// initialize custom context class
WallpaperEngine::Render::CRenderContext* context = new WallpaperEngine::Render::CRenderContext (screens, window, containers);
WallpaperEngine::Render::CRenderContext context (screens, videoDriver, &containers);
// initialize mouse support
context->setMouse (new CMouseInput (window));
// set the default viewport
context->setDefaultViewport ({0, 0, windowWidth, windowHeight});
context.setMouse (new CMouseInput (videoDriver.getWindow ()));
// ensure the context knows what wallpaper to render
context->setWallpaper (
WallpaperEngine::Render::CWallpaper::fromWallpaper (project->getWallpaper (), context)
context.setWallpaper (
WallpaperEngine::Render::CWallpaper::fromWallpaper (project->getWallpaper (), &context)
);
// update maximum FPS if it's a video
if (context->getWallpaper ()->is <WallpaperEngine::Render::CVideo> () == true)
maximumFPS = context->getWallpaper ()->as <WallpaperEngine::Render::CVideo> ()->getFPS ();
if (context.getWallpaper ()->is <WallpaperEngine::Render::CVideo> () == true)
maximumFPS = context.getWallpaper ()->as <WallpaperEngine::Render::CVideo> ()->getFPS ();
// TODO: FIGURE OUT THE REQUIRED INPUT MODE, AS SOME WALLPAPERS USE THINGS LIKE MOUSE POSITION
// glfwSetInputMode (window, GLFW_STICKY_KEYS, GL_TRUE);
float startTime, endTime, minimumTime = 1.0f / maximumFPS;
double startTime, endTime, minimumTime = 1.0 / maximumFPS;
uint32_t frameCounter = 0;
while (glfwWindowShouldClose (window) == 0 && g_KeepRunning == true)
while (videoDriver.closeRequested () == false && g_KeepRunning == true)
{
// get the real framebuffer size
glfwGetFramebufferSize (window, &windowWidth, &windowHeight);
// set the default viewport
context->setDefaultViewport ({0, 0, windowWidth, windowHeight});
// keep track of the previous frame's time
g_TimeLast = g_Time;
// calculate the current time value
g_Time = (float) glfwGetTime ();
g_Time = videoDriver.getRenderTime ();
// get the start time of the frame
startTime = glfwGetTime ();
startTime = g_Time;
// render the scene
context->render ();
// do buffer swapping
glfwSwapBuffers (window);
// poll for events (like closing the window)
glfwPollEvents ();
context.render ();
// get the end time of the frame
endTime = glfwGetTime ();
endTime = videoDriver.getRenderTime ();
// ensure the frame time is correct to not overrun FPS
if ((endTime - startTime) < minimumTime)
usleep ((minimumTime - (endTime - startTime)) * CLOCKS_PER_SEC);
frameCounter ++;
if (frameCounter == 5 && shouldTakeScreenshot == true)
if (shouldTakeScreenshot == true && videoDriver.getFrameCounter () == 5)
{
takeScreenshot (context->getWallpaper (), screenshotPath, screenshotFormat);
takeScreenshot (context.getWallpaper (), screenshotPath, screenshotFormat);
// disable screenshot just in case the counter overflows
shouldTakeScreenshot = false;
}
@ -672,16 +498,9 @@ int main (int argc, char* argv[])
sLog.out ("Stop requested");
// terminate gl
glfwTerminate ();
// terminate free image
FreeImage_DeInitialise ();
// terminate SDL
SDL_QuitSubSystem(SDL_INIT_AUDIO);
SDL_Quit ();
// free context
delete context;
return 0;
}

View File

@ -0,0 +1,68 @@
#include "FileSystem.h"
#include "WallpaperEngine/Logging/CLog.h"
#include <climits>
#include <cstdlib>
#include <sstream>
#include <filesystem>
#include <sys/stat.h>
const char* assets_default_paths [] = {
".steam/steam/steamapps/common",
".local/share/Steam/steamapps/common",
nullptr
};
const char* workshop_content_default_paths [] = {
".local/share/Steam/steamapps/workshop/content",
".steam/steam/steamapps/workshop/content",
nullptr
};
std::filesystem::path detectHomepath ()
{
char* home = getenv ("HOME");
if (home == nullptr)
sLog.exception ("Cannot find home directory for the current user");
std::filesystem::path path = home;
if (std::filesystem::is_directory (path) == false)
sLog.exception ("Cannot find home directory for current user, ", home, " is not a directory");
return home;
}
std::filesystem::path Steam::FileSystem::workshopDirectory (int appID, const std::string& contentID)
{
auto homepath = detectHomepath ();
for (const char** current = workshop_content_default_paths; *current != nullptr; current ++)
{
auto currentpath = std::filesystem::path (homepath) / *current / std::to_string (appID) / contentID;
if (std::filesystem::exists (currentpath) == false || std::filesystem::is_directory (currentpath) == false)
continue;
return currentpath;
}
sLog.exception ("Cannot find workshop directory for steam app ", appID, " and content ", contentID);
}
std::filesystem::path Steam::FileSystem::appDirectory (const std::string& appDirectory, const std::string& path)
{
auto homepath = detectHomepath ();
for (const char** current = assets_default_paths; *current != nullptr; current ++)
{
auto currentpath = std::filesystem::path (homepath) / *current / appDirectory / path;
if (std::filesystem::exists (currentpath) == false || std::filesystem::is_directory (currentpath) == false)
continue;
return currentpath;
}
sLog.exception ("Cannot find directory for steam app ", appDirectory, ": ", path);
}

View File

@ -0,0 +1,9 @@
#pragma once
#include <string>
#include <filesystem>
namespace Steam::FileSystem
{
std::filesystem::path workshopDirectory (int appID, const std::string& contentID);
std::filesystem::path appDirectory (const std::string& appDirectory, const std::string& path);
}

View File

@ -10,16 +10,13 @@ void CCombinedContainer::add (CContainer* container)
const void* CCombinedContainer::readFile (std::string filename, uint32_t* length) const
{
auto cur = this->m_containers.begin ();
auto end = this->m_containers.end ();
for (; cur != end; cur ++)
for (auto cur : this->m_containers)
{
try
{
// try to read the file on the current container, if the file doesn't exists
// an exception will be thrown
return (*cur)->readFile (filename, length);
return cur->readFile (filename, length);
}
catch (CAssetLoadException& ex)
{

View File

@ -14,9 +14,6 @@ namespace WallpaperEngine::Assets
class CCombinedContainer : public CContainer
{
public:
CCombinedContainer () {}
~CCombinedContainer () {}
/**
* Adds a container to the list
*

View File

@ -1,13 +1,15 @@
#include "common.h"
#include <sys/stat.h>
#include <utility>
#include "CDirectory.h"
#include "CAssetLoadException.h"
using namespace WallpaperEngine::Assets;
CDirectory::CDirectory (std::string basepath) :
m_basepath (std::move (basepath))
CDirectory::CDirectory (std::filesystem::path basepath) :
m_basepath (std::move(basepath))
{
// ensure the specified path exists
struct stat buffer;
@ -26,7 +28,7 @@ CDirectory::~CDirectory ()
const void* CDirectory::readFile (std::string filename, uint32_t* length) const
{
std::string final = this->m_basepath + filename;
std::filesystem::path final = std::filesystem::path (this->m_basepath) / filename;
// first check the cache, if the file is there already just return the data in there
auto it = this->m_cache.find (final);

View File

@ -3,6 +3,7 @@
#include <string>
#include <stdexcept>
#include <map>
#include <filesystem>
#include "CContainer.h"
#include "CFileEntry.h"
@ -12,12 +13,12 @@ namespace WallpaperEngine::Assets
class CDirectory : public CContainer
{
public:
CDirectory (std::string basepath);
CDirectory (std::filesystem::path basepath);
~CDirectory ();
const void* readFile (std::string filename, uint32_t* length) const override;
private:
std::string m_basepath;
std::filesystem::path m_basepath;
std::map <std::string, CFileEntry> m_cache;
};
};

View File

@ -21,8 +21,8 @@ public:
uint32_t length;
};
CPackage::CPackage (const std::string& path) :
m_path (path),
CPackage::CPackage (std::filesystem::path path) :
m_path (std::move(path)),
m_contents ()
{
this->init ();
@ -150,32 +150,25 @@ void CPackage::loadFiles (FILE* fp)
// get current baseOffset, this is where the files start
long baseOffset = ftell (fp);
// read file contents now
auto cur = list.begin ();
auto end = list.end ();
for (; cur != end; cur ++)
for (const auto& cur : list)
{
long offset = (*cur).offset + baseOffset;
long offset = cur.offset + baseOffset;
// with all the data we can jump to the offset and read the content
if (fseek (fp, offset, SEEK_SET) != 0)
sLog.exception ("Cannot find file ", (*cur).filename, " from package ", this->m_path);
sLog.exception ("Cannot find file ", cur.filename, " from package ", this->m_path);
// allocate memory for the file's contents and read it from the file
char* fileContents = new char [(*cur).length];
char* fileContents = new char [cur.length];
if (fread (fileContents, (*cur).length, 1, fp) != 1)
if (fread (fileContents, cur.length, 1, fp) != 1)
{
delete[] fileContents;
sLog.exception ("Cannot read file ", (*cur).filename, " contents from package ", this->m_path);
sLog.exception ("Cannot read file ", cur.filename, " contents from package ", this->m_path);
}
// add the file to the map
this->m_contents.insert (std::make_pair <std::string, CFileEntry> (
std::move((*cur).filename),
CFileEntry (fileContents, (*cur).length))
);
this->m_contents.insert_or_assign (cur.filename, CFileEntry (fileContents, cur.length));
}
}

View File

@ -1,7 +1,3 @@
//
// Created by almamu on 8/8/21.
//
#pragma once
#include <string>
@ -10,6 +6,7 @@
#include <exception>
#include <stdexcept>
#include <cstring>
#include <filesystem>
#include "CContainer.h"
#include "CFileEntry.h"
@ -19,7 +16,7 @@ namespace WallpaperEngine::Assets
class CPackage : public CContainer
{
public:
CPackage (const std::string& path);
CPackage (std::filesystem::path path);
~CPackage ();
const void* readFile (std::string filename, uint32_t* length) const override;
@ -62,7 +59,7 @@ namespace WallpaperEngine::Assets
uint32_t readInteger (FILE* fp);
private:
std::string m_path;
std::filesystem::path m_path;
std::map <std::string, CFileEntry> m_contents;
};
}

View File

@ -322,16 +322,10 @@ CTexture::TextureHeader::TextureHeader ()
CTexture::TextureHeader::~TextureHeader ()
{
auto imgCur = this->images.begin ();
auto imgEnd = this->images.end ();
for (; imgCur != imgEnd; imgCur ++)
for (const auto& imgCur : this->images)
{
auto cur = (*imgCur).second.begin ();
auto end = (*imgCur).second.end ();
for (; cur != end; cur ++)
delete *cur;
for (auto cur : imgCur.second)
delete cur;
}
}

View File

@ -121,28 +121,20 @@ CObject* CObject::fromJSON (json data, CScene* scene, const CContainer* containe
if (effects_it != data.end () && (*effects_it).is_array () == true)
{
auto cur = (*effects_it).begin ();
auto end = (*effects_it).end ();
for (; cur != end; cur ++)
for (const auto& cur : *effects_it)
{
auto effectVisible = jsonFindUserConfig <CUserSettingBoolean, bool> (data, "visible", true);
object->insertEffect (
Objects::CEffect::fromJSON (*cur, effectVisible, object, container)
Objects::CEffect::fromJSON (cur, effectVisible, object, container)
);
}
}
if (dependencies_it != data.end () && (*dependencies_it).is_array () == true)
{
auto cur = (*dependencies_it).begin ();
auto end = (*dependencies_it).end ();
for (; cur != end; cur ++)
{
object->insertDependency (*cur);
}
for (const auto& cur : *dependencies_it)
object->insertDependency (cur);
}
return object;

View File

@ -56,12 +56,9 @@ CProject* CProject::fromFile (const std::string& filename, CContainer* container
if (properties != (*general).end ())
{
auto cur = (*properties).begin ();
auto end = (*properties).end ();
for (; cur != end; cur ++)
for (const auto& cur : (*properties).items ())
{
Projects::CProperty* property = Projects::CProperty::fromJSON (*cur, cur.key ());
Projects::CProperty* property = Projects::CProperty::fromJSON (cur.value (), cur.key ());
if (property != nullptr)
project->insertProperty (property);

View File

@ -101,15 +101,8 @@ CScene* CScene::fromFile (const std::string& filename, CContainer* container)
WallpaperEngine::Core::aToColorf(skylightcolor)
);
auto cur = (*objects_it).begin ();
auto end = (*objects_it).end ();
for (; cur != end; cur ++)
{
scene->insertObject (
CObject::fromJSON (*cur, scene, container)
);
}
for (const auto& cur : *objects_it)
scene->insertObject (CObject::fromJSON (cur, scene, container));
return scene;
}

View File

@ -84,21 +84,17 @@ CEffect* CEffect::fromJSON (json data, CUserSettingBoolean* visible, Core::CObje
Images::CMaterial* material = effect->getMaterials ().at (passNumber);
auto passCur = material->getPasses ().begin ();
auto passEnd = material->getPasses ().end ();
for (; passCur != passEnd; passCur ++)
for (const auto& passCur : material->getPasses ())
{
if (textures_it != (*cur).end ())
{
auto texturesCur = (*textures_it).begin ();
auto texturesEnd = (*textures_it).end ();
int textureNumber = 0;
for (int textureNumber = 0; texturesCur != texturesEnd; texturesCur ++)
for (const auto& texturesCur : (*textures_it))
{
std::string texture;
if ((*texturesCur).is_null () == true)
if (texturesCur.is_null () == true)
{
if (textureNumber == 0)
{
@ -113,15 +109,15 @@ CEffect* CEffect::fromJSON (json data, CUserSettingBoolean* visible, Core::CObje
}
else
{
texture = *texturesCur;
texture = texturesCur;
}
std::vector<std::string> passTextures = (*passCur)->getTextures ();
std::vector<std::string> passTextures = passCur->getTextures ();
if (textureNumber < passTextures.size ())
(*passCur)->setTexture (textureNumber, texture);
passCur->setTexture (textureNumber, texture);
else
(*passCur)->insertTexture (texture);
passCur->insertTexture (texture);
textureNumber ++;
}
@ -129,12 +125,12 @@ CEffect* CEffect::fromJSON (json data, CUserSettingBoolean* visible, Core::CObje
if (combos_it != (*cur).end ())
{
CEffect::combosFromJSON (combos_it, *passCur);
CEffect::combosFromJSON (combos_it, passCur);
}
if (constants_it != (*cur).end ())
{
CEffect::constantsFromJSON (constants_it, *passCur);
CEffect::constantsFromJSON (constants_it, passCur);
}
}
}
@ -145,23 +141,15 @@ CEffect* CEffect::fromJSON (json data, CUserSettingBoolean* visible, Core::CObje
void CEffect::combosFromJSON (json::const_iterator combos_it, Core::Objects::Images::Materials::CPass* pass)
{
auto cur = (*combos_it).begin ();
auto end = (*combos_it).end ();
for (; cur != end; cur ++)
{
pass->insertCombo (cur.key (), *cur);
}
for (const auto& cur : (*combos_it).items ())
pass->insertCombo (cur.key (), cur.value ());
}
void CEffect::constantsFromJSON (json::const_iterator constants_it, Core::Objects::Images::Materials::CPass* pass)
{
auto cur = (*constants_it).begin ();
auto end = (*constants_it).end ();
for (; cur != end; cur ++)
for (auto& cur : (*constants_it).items ())
{
json::const_iterator val = cur;
auto val = cur.value ();
Effects::Constants::CShaderConstant* constant = nullptr;
@ -169,33 +157,35 @@ void CEffect::constantsFromJSON (json::const_iterator constants_it, Core::Object
// for the UI, take the value, which is what we need
// TODO: SUPPORT USER SETTINGS HERE
if ((*cur).is_object () == true)
if (cur.value ().is_object () == true)
{
val = (*cur).find ("value");
auto it = cur.value ().find ("value");
if (val == (*cur).end ())
if (it == cur.value ().end ())
{
sLog.error ("Found object for shader constant without \"value\" member");
continue;
}
val = it.value ();
}
if ((*val).is_number_float () == true)
if (val.is_number_float () == true)
{
constant = new Effects::Constants::CShaderConstantFloat ((*val).get <float> ());
constant = new Effects::Constants::CShaderConstantFloat (val.get <float> ());
}
else if ((*val).is_number_integer () == true)
else if (val.is_number_integer () == true)
{
constant = new Effects::Constants::CShaderConstantInteger ((*val).get <int> ());
constant = new Effects::Constants::CShaderConstantInteger (val.get <int> ());
}
else if ((*val).is_string () == true)
else if (val.is_string () == true)
{
// try a vector 4 first, then a vector3 and then a vector 2
constant = new Effects::Constants::CShaderConstantVector4 (WallpaperEngine::Core::aToVector4 (*val));
constant = new Effects::Constants::CShaderConstantVector4 (WallpaperEngine::Core::aToVector4 (val));
}
else
{
sLog.exception ("unknown shader constant type ", *val);
sLog.exception ("unknown shader constant type ", val);
}
pass->insertConstant (cur.key (), constant);
@ -204,64 +194,38 @@ void CEffect::constantsFromJSON (json::const_iterator constants_it, Core::Object
void CEffect::fbosFromJSON (json::const_iterator fbos_it, CEffect* effect)
{
auto cur = (*fbos_it).begin ();
auto end = (*fbos_it).end ();
for (; cur != end; cur ++)
{
effect->insertFBO (
Effects::CFBO::fromJSON (*cur)
);
}
for (const auto& cur : (*fbos_it))
effect->insertFBO (Effects::CFBO::fromJSON (cur));
}
void CEffect::dependencyFromJSON (json::const_iterator dependencies_it, CEffect* effect)
{
auto cur = (*dependencies_it).begin ();
auto end = (*dependencies_it).end ();
for (; cur != end; cur ++)
{
effect->insertDependency (*cur);
}
for (const auto& cur : (*dependencies_it))
effect->insertDependency (cur);
}
void CEffect::materialsFromJSON (json::const_iterator passes_it, CEffect* effect, const CContainer* container)
{
auto cur = (*passes_it).begin ();
auto end = (*passes_it).end ();
for (; cur != end; cur ++)
for (const auto& cur : (*passes_it))
{
auto materialfile = (*cur).find ("material");
auto target = (*cur).find ("target");
auto bind = (*cur).find ("bind");
auto materialfile = cur.find ("material");
auto target = cur.find ("target");
auto bind = cur.find ("bind");
if (materialfile == (*cur).end ())
if (materialfile == cur.end ())
sLog.exception ("Found an effect ", effect->m_name, " without material");
Images::CMaterial* material = nullptr;
if (target == (*cur).end ())
{
if (target == cur.end ())
material = Images::CMaterial::fromFile ((*materialfile).get <std::string> (), container);
}
else
{
material = Images::CMaterial::fromFile ((*materialfile).get <std::string> (), *target, container);
}
if (bind != (*cur).end ())
if (bind != cur.end ())
{
auto bindCur = (*bind).begin ();
auto bindEnd = (*bind).end ();
for (; bindCur != bindEnd; bindCur ++)
{
material->insertTextureBind (
Effects::CBind::fromJSON (*bindCur)
);
}
for (const auto& bindCur : (*bind))
material->insertTextureBind (Effects::CBind::fromJSON (bindCur));
}
effect->insertMaterial (material);
@ -290,16 +254,9 @@ bool CEffect::isVisible () const
Effects::CFBO* CEffect::findFBO (const std::string& name)
{
auto cur = this->m_fbos.begin ();
auto end = this->m_fbos.end ();
for (; cur != end; cur ++)
{
if ((*cur)->getName () == name)
{
return (*cur);
}
}
for (const auto& cur : this->m_fbos)
if (cur->getName () == name)
return cur;
sLog.exception ("cannot find fbo ", name);
}

View File

@ -33,36 +33,14 @@ CParticle* CParticle::fromFile (
if (controlpoint_it != data.end ())
{
auto cur = (*controlpoint_it).begin ();
auto end = (*controlpoint_it).end ();
for (; cur != end; cur ++)
{
particle->insertControlPoint (
Particles::CControlPoint::fromJSON (*cur)
);
}
for (const auto& cur : (*controlpoint_it))
particle->insertControlPoint (Particles::CControlPoint::fromJSON (cur));
}
auto cur = (*emitter_it).begin ();
auto end = (*emitter_it).end ();
for (; cur != end; cur ++)
{
particle->insertEmitter (
Particles::CEmitter::fromJSON (*cur)
);
}
cur = (*initializer_it).begin ();
end = (*initializer_it).end ();
for (; cur != end; cur ++)
{
particle->insertInitializer (
Particles::CInitializer::fromJSON (*cur)
);
}
for (const auto& cur : (*emitter_it))
particle->insertEmitter (Particles::CEmitter::fromJSON (cur));
for (const auto&cur : (*initializer_it))
particle->insertInitializer (Particles::CInitializer::fromJSON (cur));
return particle;
}

View File

@ -42,13 +42,8 @@ WallpaperEngine::Core::CObject* CSound::fromJSON (
angles
);
auto cur = (*sound_it).begin ();
auto end = (*sound_it).end ();
for (; cur != end; cur ++)
{
sound->insertSound (*cur);
}
for (const auto& cur : (*sound_it))
sound->insertSound (cur);
return sound;
}

View File

@ -43,15 +43,8 @@ CMaterial* CMaterial::fromJSON (const std::string& name, json data)
CMaterial* material = new CMaterial (name);
auto cur = (*passes_it).begin ();
auto end = (*passes_it).end ();
for (; cur != end; cur ++)
{
material->insertPass (
Materials::CPass::fromJSON (*cur)
);
}
for (const auto& cur : (*passes_it))
material->insertPass (Materials::CPass::fromJSON (cur));
return material;
}

View File

@ -41,39 +41,29 @@ CPass* CPass::fromJSON (json data)
if (textures_it != data.end ())
{
auto cur = (*textures_it).begin ();
auto end = (*textures_it).end ();
for (;cur != end; cur ++)
for (const auto& cur : (*textures_it))
{
if ((*cur).is_null () == true)
if (cur.is_null () == true)
{
pass->insertTexture ("");
}
else
{
pass->insertTexture (*cur);
pass->insertTexture (cur);
}
}
}
if (combos_it != data.end ())
{
auto cur = (*combos_it).begin ();
auto end = (*combos_it).end ();
for (; cur != end; cur ++)
for (const auto& cur : (*combos_it).items ())
{
std::string name = cur.key ();
if ((*cur).is_number_integer () == true)
{
pass->insertCombo (name, *cur);
}
if (cur.value ().is_number_integer () == true)
pass->insertCombo (name, cur.value ());
else
{
sLog.exception ("unexpected non-integer combo on pass");
}
}
}

View File

@ -23,20 +23,15 @@ CPropertyCombo* CPropertyCombo::fromJSON (json data, const std::string& name)
if (options->is_array () == false)
sLog.exception ("Property combo options should be an array");
auto cur = (*options).begin ();
auto end = (*options).end ();
for (; cur != end; cur ++)
for (auto& cur : (*options))
{
if ((*cur).is_object () == false)
{
// TODO: PROPERLY REPORT THESE ISSUES
// TODO: PROPERLY REPORT THESE ISSUES
if (cur.is_object () == false)
continue;
}
// check for label and value to ensure they're there
auto label = jsonFindRequired (*cur, "label", "Label is required for a property combo option");
auto value = jsonFindRequired (*cur, "value", "Value is required for a property combo option");
auto label = jsonFindRequired (cur, "label", "Label is required for a property combo option");
auto value = jsonFindRequired (cur, "value", "Value is required for a property combo option");
combo->addValue (*label, *value);
}

View File

@ -12,6 +12,9 @@
#include "CRenderContext.h"
#include "CVideo.h"
#define DEFAULT_WINDOW_WIDTH 1280
#define DEFAULT_WINDOW_HEIGHT 720
using namespace WallpaperEngine::Render;
XErrorHandler originalErrorHandler;
@ -25,7 +28,7 @@ void CustomXIOErrorExitHandler (Display* dsp, void* userdata)
#endif /* DEBUG */
// refetch all the resources
context->initializeViewports ();
context->initialize ();
}
int CustomXErrorHandler (Display* dpy, XErrorEvent* event)
@ -49,24 +52,32 @@ int CustomXIOErrorHandler (Display* dsp)
return 0;
}
CRenderContext::CRenderContext (std::vector <std::string> screens, GLFWwindow* window, CContainer* container) :
CRenderContext::CRenderContext (std::vector <std::string> screens, CVideoDriver& driver, CContainer* container) :
m_wallpaper (nullptr),
m_screens (std::move (screens)),
m_isRootWindow (m_screens.empty () == false),
m_defaultViewport ({0, 0, 1920, 1080}),
m_window (window),
m_driver (driver),
m_container (container),
m_textureCache (new CTextureCache (this))
{
this->initializeViewports ();
this->initialize ();
}
void CRenderContext::initializeViewports ()
void CRenderContext::initialize ()
{
if (this->m_isRootWindow == false || this->m_screens.empty () == true)
return;
if (this->m_screens.empty () == true)
this->setupWindow ();
else
this->setupScreens ();
}
// clear the viewports we're drawing to
void CRenderContext::setupWindow ()
{
this->m_driver.showWindow ();
this->m_driver.resizeWindow ({DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT});
}
void CRenderContext::setupScreens ()
{
this->m_viewports.clear ();
this->m_display = XOpenDisplay (nullptr);
@ -86,9 +97,6 @@ void CRenderContext::initializeViewports ()
return;
}
// hide the glfw window if the viewports are to be detected
glfwHideWindow (this->m_window);
Window root = DefaultRootWindow (this->m_display);
int fullWidth = DisplayWidth (this->m_display, DefaultScreen (this->m_display));
int fullHeight = DisplayHeight (this->m_display, DefaultScreen (this->m_display));
@ -109,28 +117,21 @@ void CRenderContext::initializeViewports ()
XRROutputInfo* info = XRRGetOutputInfo (this->m_display, screenResources, screenResources->outputs [i]);
// there are some situations where xrandr returns null (like screen not using the extension)
if (info == nullptr)
if (info == nullptr || info->connection != RR_Connected)
continue;
auto cur = this->m_screens.begin ();
auto end = this->m_screens.end ();
for (; cur != end; cur ++)
for (const auto& cur : this->m_screens)
{
if (info->connection == RR_Connected && strcmp (info->name, (*cur).c_str ()) == 0)
{
XRRCrtcInfo* crtc = XRRGetCrtcInfo (this->m_display, screenResources, info->crtc);
if (strcmp (info->name, cur.c_str ()) != 0)
continue;
sLog.out ("Found requested screen: ", info->name, " -> ", crtc->x, "x", crtc->y, ":", crtc->width, "x", crtc->height);
XRRCrtcInfo* crtc = XRRGetCrtcInfo (this->m_display, screenResources, info->crtc);
glm::ivec4 viewport = {
crtc->x, crtc->y, crtc->width, crtc->height
};
sLog.out ("Found requested screen: ", info->name, " -> ", crtc->x, "x", crtc->y, ":", crtc->width, "x", crtc->height);
this->m_viewports.push_back ({viewport, *cur});
this->m_viewports.push_back ({{crtc->x, crtc->y, crtc->width, crtc->height}, cur});
XRRFreeCrtcInfo (crtc);
}
XRRFreeCrtcInfo (crtc);
}
XRRFreeOutputInfo (info);
@ -169,6 +170,58 @@ CRenderContext::~CRenderContext ()
}
}
void CRenderContext::renderScreens ()
{
bool firstFrame = true;
bool renderFrame = true;
int fullWidth = DisplayWidth (this->m_display, DefaultScreen (this->m_display));
int fullHeight = DisplayHeight (this->m_display, DefaultScreen (this->m_display));
Window root = DefaultRootWindow (this->m_display);
for (const auto& cur : this->m_viewports)
{
if (DEBUG)
{
std::string str = "Rendering to screen " + cur.name;
glPushDebugGroup (GL_DEBUG_SOURCE_APPLICATION, 0, -1, str.c_str ());
}
// render the background
this->m_wallpaper->render (cur.viewport, false, renderFrame, firstFrame);
// scenes need to render a new frame for each viewport as they produce different results
// but videos should only be rendered once per group of viewports
firstFrame = false;
renderFrame = !this->m_wallpaper->is <CVideo> ();
if (DEBUG)
glPopDebugGroup ();
}
// read the full texture into the image
glReadPixels (0, 0, fullWidth, fullHeight, GL_BGRA, GL_UNSIGNED_BYTE, (void*) this->m_imageData);
// put the image back into the screen
XPutImage (this->m_display, this->m_pixmap, this->m_gc, this->m_image, 0, 0, 0, 0, fullWidth, fullHeight);
// _XROOTPMAP_ID & ESETROOT_PMAP_ID allow other programs (compositors) to
// edit the background. Without these, other programs will clear the screen.
// it also forces the compositor to refresh the background (tested with picom)
Atom prop_root = XInternAtom(this->m_display, "_XROOTPMAP_ID", False);
Atom prop_esetroot = XInternAtom(this->m_display, "ESETROOT_PMAP_ID", False);
XChangeProperty(this->m_display, root, prop_root, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &this->m_pixmap, 1);
XChangeProperty(this->m_display, root, prop_esetroot, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &this->m_pixmap, 1);
XClearWindow(this->m_display, root);
XFlush(this->m_display);
}
void CRenderContext::renderWindow ()
{
// render the background to the window directly
this->m_wallpaper->render ({0, 0, this->m_driver.getFramebufferSize ()}, true);
}
void CRenderContext::render ()
{
if (this->m_wallpaper == nullptr)
@ -178,54 +231,11 @@ void CRenderContext::render ()
this->m_mouse->update ();
if (this->m_viewports.empty () == false)
{
bool firstFrame = true;
bool renderFrame = true;
auto cur = this->m_viewports.begin ();
auto end = this->m_viewports.end ();
int fullWidth = DisplayWidth (this->m_display, DefaultScreen (this->m_display));
int fullHeight = DisplayHeight (this->m_display, DefaultScreen (this->m_display));
Window root = DefaultRootWindow (this->m_display);
for (; cur != end; cur ++)
{
if (DEBUG)
{
std::string str = "Rendering to screen " + (*cur).name;
glPushDebugGroup (GL_DEBUG_SOURCE_APPLICATION, 0, -1, str.c_str ());
}
// render the background
this->m_wallpaper->render ((*cur).viewport, false, renderFrame, firstFrame);
// scenes need to render a new frame for each viewport as they produce different results
// but videos should only be rendered once per group of viewports
firstFrame = false;
renderFrame = !this->m_wallpaper->is <CVideo> ();
if (DEBUG)
glPopDebugGroup ();
}
// read the full texture into the image
glReadPixels (0, 0, fullWidth, fullHeight, GL_BGRA, GL_UNSIGNED_BYTE, (void*) this->m_imageData);
// put the image back into the screen
XPutImage (this->m_display, this->m_pixmap, this->m_gc, this->m_image, 0, 0, 0, 0, fullWidth, fullHeight);
// _XROOTPMAP_ID & ESETROOT_PMAP_ID allow other programs (compositors) to
// edit the background. Without these, other programs will clear the screen.
// it also forces the compositor to refresh the background (tested with picom)
Atom prop_root = XInternAtom(this->m_display, "_XROOTPMAP_ID", False);
Atom prop_esetroot = XInternAtom(this->m_display, "ESETROOT_PMAP_ID", False);
XChangeProperty(this->m_display, root, prop_root, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &this->m_pixmap, 1);
XChangeProperty(this->m_display, root, prop_esetroot, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &this->m_pixmap, 1);
XClearWindow(this->m_display, root);
XFlush(this->m_display);
}
this->renderScreens ();
else
this->m_wallpaper->render (this->m_defaultViewport, true);
this->renderWindow ();
this->m_driver.swapBuffers ();
}
void CRenderContext::setWallpaper (CWallpaper* wallpaper)
@ -249,11 +259,6 @@ void CRenderContext::setWallpaper (CWallpaper* wallpaper)
}
}
void CRenderContext::setDefaultViewport (glm::vec4 defaultViewport)
{
this->m_defaultViewport = defaultViewport;
}
CMouseInput* CRenderContext::getMouse () const
{
return this->m_mouse;

View File

@ -4,11 +4,19 @@
#include <glm/vec4.hpp>
#include "WallpaperEngine/Input/CMouseInput.h"
#include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
#include "CTextureCache.h"
#include "CWallpaper.h"
#include <X11/Xlib.h>
using namespace WallpaperEngine::Assets;
using namespace WallpaperEngine::Input;
using namespace WallpaperEngine::Render::Drivers;
namespace WallpaperEngine::Render::Drivers
{
class CVideoDriver;
}
namespace WallpaperEngine::Render
{
@ -18,13 +26,12 @@ namespace WallpaperEngine::Render
class CRenderContext
{
public:
CRenderContext (std::vector <std::string> screens, GLFWwindow* window, CContainer* container);
CRenderContext (std::vector <std::string> screens, CVideoDriver& driver, CContainer* container);
~CRenderContext ();
void initializeViewports ();
void initialize ();
void render ();
void setWallpaper (CWallpaper* wallpaper);
void setDefaultViewport (glm::vec4 defaultViewport);
CMouseInput* getMouse () const;
void setMouse (CMouseInput* mouse);
CWallpaper* getWallpaper () const;
@ -32,6 +39,12 @@ namespace WallpaperEngine::Render
const ITexture* resolveTexture (const std::string& name);
private:
void setupScreens ();
void setupWindow ();
void renderScreens ();
void renderWindow ();
struct viewport
{
glm::ivec4 viewport;
@ -42,15 +55,13 @@ namespace WallpaperEngine::Render
Pixmap m_pixmap;
GC m_gc;
XImage* m_image;
GLFWwindow* m_window;
CVideoDriver& m_driver;
char* m_imageData;
CFBO* m_fbo;
std::vector <std::string> m_screens;
std::vector <viewport> m_viewports;
glm::vec4 m_defaultViewport;
CWallpaper* m_wallpaper;
CMouseInput* m_mouse;
bool m_isRootWindow;
CContainer* m_container;
CTextureCache* m_textureCache;
};

View File

@ -24,15 +24,12 @@ CScene::CScene (Core::CScene* scene, CRenderContext* context) :
if (scene->getOrthogonalProjection ()->isAuto () == true)
{
// calculate the size of the projection based on the size of everything
auto cur = scene->getObjects ().begin ();
auto end = scene->getObjects ().end ();
for (; cur != end; cur ++)
for (const auto& cur : scene->getObjects ())
{
if ((*cur).second->is<Core::Objects::CImage> () == false)
if (cur.second->is<Core::Objects::CImage> () == false)
continue;
glm::vec2 size = (*cur).second->as <Core::Objects::CImage> ()->getSize ();
glm::vec2 size = cur.second->as <Core::Objects::CImage> ()->getSize ();
scene->getOrthogonalProjection ()->setWidth (size.x);
scene->getOrthogonalProjection ()->setHeight (size.y);
@ -55,21 +52,13 @@ CScene::CScene (Core::CScene* scene, CRenderContext* context) :
this->setupFramebuffers ();
// create all objects based off their dependencies
for (const auto& cur : scene->getObjects ())
this->createObject (cur.second);
// copy over objects by render order
for (const auto& cur : scene->getObjectsByRenderOrder ())
{
auto cur = scene->getObjects ().begin ();
auto end = scene->getObjects ().end ();
for (; cur != end; cur++)
this->createObject ((*cur).second);
}
// now setup the render order
auto cur = scene->getObjectsByRenderOrder ().begin ();
auto end = scene->getObjectsByRenderOrder ().end ();
for (; cur != end; cur ++)
{
auto obj = this->m_objects.find ((*cur)->getId ());
auto obj = this->m_objects.find (cur->getId ());
// ignores not created objects like particle systems
if (obj == this->m_objects.end ())
@ -183,16 +172,13 @@ Render::CObject* CScene::createObject (Core::CObject* object)
return (*current).second;
// check dependencies too!
auto depCur = object->getDependencies ().begin ();
auto depEnd = object->getDependencies ().end ();
for (; depCur != depEnd; depCur ++)
for (const auto& cur : object->getDependencies ())
{
// self-dependency is a possibility...
if ((*depCur) == object->getId ())
if (cur == object->getId ())
continue;
auto dep = this->getScene ()->getObjects ().find (*depCur);
auto dep = this->getScene ()->getObjects ().find (cur);
if (dep != this->getScene ()->getObjects ().end ())
this->createObject ((*dep).second);
@ -232,10 +218,6 @@ CCamera* CScene::getCamera () const
void CScene::renderFrame (glm::ivec4 viewport)
{
auto projection = this->getScene ()->getOrthogonalProjection ();
auto cur = this->m_objectsByRenderOrder.begin ();
auto end = this->m_objectsByRenderOrder.end ();
// ensure the virtual mouse position is up to date
this->updateMouse (viewport);
@ -256,8 +238,8 @@ void CScene::renderFrame (glm::ivec4 viewport)
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (; cur != end; cur ++)
(*cur)->render ();
for (const auto& cur : this->m_objectsByRenderOrder)
cur->render ();
}
void CScene::updateMouse (glm::ivec4 viewport)

View File

@ -0,0 +1,101 @@
#include "COpenGLDriver.h"
#include "common.h"
#include <FreeImage.h>
using namespace WallpaperEngine::Render::Drivers;
COpenGLDriver::COpenGLDriver (const char* windowTitle) :
m_frameCounter (0)
{
// initialize glfw
if (glfwInit () == GLFW_FALSE)
sLog.exception ("Failed to initialize glfw");
// set some window hints (opengl version to be used)
glfwWindowHint (GLFW_SAMPLES, 4);
glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint (GLFW_VISIBLE, GLFW_FALSE);
if (DEBUG)
glfwWindowHint (GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
// create window, size doesn't matter as long as we don't show it
this->m_window = glfwCreateWindow (640, 480, windowTitle, nullptr, nullptr);
if (this->m_window == nullptr)
sLog.exception ("Cannot create window");
// make context current, required for glew initialization
glfwMakeContextCurrent (this->m_window);
// initialize glew for rendering
GLenum result = glewInit ();
if (result != GLEW_OK)
sLog.error("Failed to initialize GLEW: ", glewGetErrorString (result));
// initialize free image
FreeImage_Initialise (TRUE);
}
COpenGLDriver::~COpenGLDriver ()
{
glfwTerminate ();
FreeImage_DeInitialise();
}
float COpenGLDriver::getRenderTime ()
{
return (float) glfwGetTime ();
}
bool COpenGLDriver::closeRequested ()
{
return glfwWindowShouldClose (this->m_window);
}
void COpenGLDriver::resizeWindow (glm::ivec2 size)
{
glfwSetWindowSize (this->m_window, size.x, size.y);
}
void COpenGLDriver::showWindow ()
{
glfwShowWindow (this->m_window);
}
void COpenGLDriver::hideWindow ()
{
glfwHideWindow (this->m_window);
}
glm::ivec2 COpenGLDriver::getFramebufferSize ()
{
glm::ivec2 size;
glfwGetFramebufferSize (this->m_window, &size.x, &size.y);
return size;
}
void COpenGLDriver::swapBuffers ()
{
// do buffer swapping first
glfwSwapBuffers (this->m_window);
// poll for events
glfwPollEvents ();
// increase frame counter
this->m_frameCounter ++;
}
uint32_t COpenGLDriver::getFrameCounter ()
{
return this->m_frameCounter;
}
GLFWwindow* COpenGLDriver::getWindow ()
{
return this->m_window;
}

View File

@ -0,0 +1,29 @@
#pragma once
#include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
#include <GL/glew.h>
#include <GLFW/glfw3.h>
namespace WallpaperEngine::Render::Drivers
{
class COpenGLDriver : public CVideoDriver
{
public:
COpenGLDriver (const char* windowTitle);
~COpenGLDriver();
float getRenderTime () override;
bool closeRequested () override;
void resizeWindow (glm::ivec2 size) override;
void showWindow () override;
void hideWindow () override;
glm::ivec2 getFramebufferSize () override;
void swapBuffers () override;
uint32_t getFrameCounter () override;
GLFWwindow* getWindow ();
private:
GLFWwindow* m_window;
uint32_t m_frameCounter;
};
}

View File

@ -0,0 +1,3 @@
#include "CVideoDriver.h"
using namespace WallpaperEngine::Render::Drivers;

View File

@ -0,0 +1,19 @@
#pragma once
#include <glm/vec2.hpp>
namespace WallpaperEngine::Render::Drivers
{
class CVideoDriver
{
public:
virtual float getRenderTime () = 0;
virtual bool closeRequested () = 0;
virtual void resizeWindow (glm::ivec2 size) = 0;
virtual void showWindow () = 0;
virtual void hideWindow () = 0;
virtual glm::ivec2 getFramebufferSize () = 0;
virtual void swapBuffers () = 0;
virtual uint32_t getFrameCounter () = 0;
};
}

View File

@ -23,46 +23,33 @@ const std::vector<Effects::CMaterial*>& CEffect::getMaterials () const
const CFBO* CEffect::findFBO (const std::string& name) const
{
auto cur = this->m_fbos.begin ();
auto end = this->m_fbos.end ();
for (; cur != end; cur ++)
{
if ((*cur)->getName () == name)
{
return *cur;
}
}
for (const auto& cur : this->m_fbos)
if (cur->getName () == name)
return cur;
return nullptr;
}
void CEffect::generatePasses ()
{
auto cur = this->m_effect->getMaterials ().begin ();
auto end = this->m_effect->getMaterials ().end ();
for (; cur != end; cur ++)
this->m_materials.emplace_back (new Effects::CMaterial (this, *cur));
for (const auto& cur : this->m_effect->getMaterials ())
this->m_materials.emplace_back (new Effects::CMaterial (this, cur));
}
void CEffect::generateFBOs ()
{
auto cur = this->m_effect->getFbos ().begin ();
auto end = this->m_effect->getFbos ().end ();
for (; cur != end; cur ++)
for (const auto& cur : this->m_effect->getFbos ())
{
this->m_fbos.push_back (
new CFBO (
(*cur)->getName (),
cur->getName (),
ITexture::TextureFormat::ARGB8888, // TODO: CHANGE
this->m_image->getTexture ()->getFlags (), // TODO: CHANGE
(*cur)->getScale (),
this->m_image->getSize ().x / (*cur)->getScale (),
this->m_image->getSize ().y / (*cur)->getScale (),
this->m_image->getSize ().x / (*cur)->getScale (),
this->m_image->getSize ().y / (*cur)->getScale ()
cur->getScale (),
this->m_image->getSize ().x / cur->getScale (),
this->m_image->getSize ().y / cur->getScale (),
this->m_image->getSize ().x / cur->getScale (),
this->m_image->getSize ().y / cur->getScale ()
)
);
}

View File

@ -242,34 +242,21 @@ void CImage::setup ()
);
// add blendmode to the combos
auto cur = this->m_material->getPasses ().begin ();
auto end = this->m_material->getPasses ().end ();
for (; cur != end; cur ++)
this->m_passes.push_back (*cur);
for (const auto& cur : this->m_material->getPasses ())
this->m_passes.push_back (cur);
}
// prepare the passes list
if (this->getImage ()->getEffects ().empty () == false)
{
// generate the effects used by this material
auto cur = this->getImage ()->getEffects ().begin ();
auto end = this->getImage ()->getEffects ().end ();
for (; cur != end; cur ++)
for (const auto& cur : this->getImage ()->getEffects ())
{
auto effect = new CEffect (this, *cur);
auto materialCur = effect->getMaterials ().begin ();
auto materialEnd = effect->getMaterials ().end ();
auto effect = new CEffect (this, cur);
for (; materialCur != materialEnd; materialCur ++)
{
auto passCur = (*materialCur)->getPasses ().begin ();
auto passEnd = (*materialCur)->getPasses ().end ();
for (; passCur != passEnd; passCur ++)
this->m_passes.push_back (*passCur);
}
for (const auto& material : effect->getMaterials ())
for (const auto& pass : material->getPasses ())
this->m_passes.push_back (pass);
this->m_effects.push_back (effect);
}
@ -289,11 +276,8 @@ void CImage::setup ()
);
// add blendmode to the combos
auto cur = this->m_colorBlendMaterial->getPasses ().begin ();
auto end = this->m_colorBlendMaterial->getPasses ().end ();
for (; cur != end; cur ++)
this->m_passes.push_back (*cur);
for (const auto& cur : this->m_colorBlendMaterial->getPasses ())
this->m_passes.push_back (cur);
}
// if there's more than one pass the blendmode has to be moved from the beginning to the end
@ -306,16 +290,11 @@ void CImage::setup ()
(*first)->getPass ()->setBlendingMode ("normal");
}
{
// calculate full animation time (if any)
this->m_animationTime = 0.0f;
// calculate full animation time (if any)
this->m_animationTime = 0.0f;
auto cur = this->getTexture ()->getFrames ().begin ();
auto end = this->getTexture ()->getFrames ().end ();
for (; cur != end; cur++)
this->m_animationTime += (*cur)->frametime;
}
for (const auto& cur : this->getTexture ()->getFrames ())
this->m_animationTime += cur->frametime;
this->setupPasses ();
this->m_initialized = true;

View File

@ -13,13 +13,10 @@ CSound::CSound (CScene* scene, Core::Objects::CSound* sound) :
void CSound::load ()
{
auto cur = this->m_sound->getSounds ().begin ();
auto end = this->m_sound->getSounds ().end ();
for (; cur != end; cur ++)
for (const auto& cur : this->m_sound->getSounds ())
{
uint32_t filesize = 0;
const void* filebuffer = this->getContainer ()->readFile ((*cur), &filesize);
const void* filebuffer = this->getContainer ()->readFile (cur, &filesize);
this->m_audioStreams.push_back (new Audio::CAudioStream (filebuffer, filesize));
this->m_soundBuffer.push_back (filebuffer);

View File

@ -23,12 +23,9 @@ CImage* CMaterial::getImage () const
void CMaterial::generatePasses ()
{
auto cur = this->m_material->getPasses ().begin ();
auto end = this->m_material->getPasses ().end ();
// these are simple now, just create the entries and done
for (; cur != end; cur ++)
this->m_passes.emplace_back (new CPass (this, *cur));
for (const auto& cur : this->m_material->getPasses ())
this->m_passes.emplace_back (new CPass (this, cur));
}
const Core::Objects::Images::CMaterial* CMaterial::getMaterial () const

View File

@ -136,26 +136,22 @@ void CPass::render ()
// calculate current texture and frame
double currentRenderTime = fmod (static_cast <double> (g_Time), this->m_material->getImage ()->getAnimationTime ());
// find the right frame now
auto frameCur = texture->getFrames ().begin ();
auto frameEnd = texture->getFrames ().end ();
for (; frameCur != frameEnd; frameCur ++)
for (const auto& frameCur : texture->getFrames ())
{
currentRenderTime -= (*frameCur)->frametime;
currentRenderTime -= frameCur->frametime;
if (currentRenderTime <= 0.0f)
{
// frame found, store coordinates and done
currentTexture = (*frameCur)->frameNumber;
currentTexture = frameCur->frameNumber;
translation.x = (*frameCur)->x / texture->getTextureWidth (currentTexture);
translation.y = (*frameCur)->y / texture->getTextureHeight (currentTexture);
translation.x = frameCur->x / texture->getTextureWidth (currentTexture);
translation.y = frameCur->y / texture->getTextureHeight (currentTexture);
rotation.x = (*frameCur)->width1 / static_cast<float> (texture->getTextureWidth (currentTexture));
rotation.y = (*frameCur)->width2 / static_cast<float> (texture->getTextureWidth(currentTexture));
rotation.z = (*frameCur)->height2 / static_cast<float> (texture->getTextureHeight (currentTexture));
rotation.w = (*frameCur)->height1 / static_cast<float> (texture->getTextureHeight (currentTexture));
rotation.x = frameCur->width1 / static_cast<float> (texture->getTextureWidth (currentTexture));
rotation.y = frameCur->width2 / static_cast<float> (texture->getTextureWidth(currentTexture));
rotation.z = frameCur->height2 / static_cast<float> (texture->getTextureHeight (currentTexture));
rotation.w = frameCur->height1 / static_cast<float> (texture->getTextureHeight (currentTexture));
break;
}
}
@ -168,118 +164,97 @@ void CPass::render ()
// continue on the map from the second texture
if (this->m_finalTextures.empty () == false)
{
auto cur = this->m_finalTextures.begin ();
auto end = this->m_finalTextures.end ();
for (; cur != end; cur ++)
for (const auto& cur : this->m_finalTextures)
{
texture = this->resolveTexture ((*cur).second, (*cur).first, this->m_input);
texture = this->resolveTexture (cur.second, cur.first, this->m_input);
glActiveTexture (GL_TEXTURE0 + (*cur).first);
glActiveTexture (GL_TEXTURE0 + cur.first);
glBindTexture (GL_TEXTURE_2D, texture->getTextureID (0));
}
}
// add uniforms
for (const auto& cur : this->m_uniforms)
{
auto cur = this->m_uniforms.begin ();
auto end = this->m_uniforms.end ();
UniformEntry* entry = cur.second;
for (; cur != end; cur ++)
switch (entry->type)
{
UniformEntry* entry = (*cur).second;
switch (entry->type)
{
case Double:
glUniform1d (entry->id, *reinterpret_cast <const double*> (entry->value));
break;
case Float:
glUniform1f (entry->id, *reinterpret_cast <const float*> (entry->value));
break;
case Integer:
glUniform1i (entry->id, *reinterpret_cast <const int*> (entry->value));
break;
case Vector4:
glUniform4fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec4*> (entry->value)));
break;
case Vector3:
glUniform3fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec3*> (entry->value)));
break;
case Vector2:
glUniform2fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec2*> (entry->value)));
break;
case Matrix4:
glUniformMatrix4fv (entry->id, 1, GL_FALSE, glm::value_ptr (*reinterpret_cast <const glm::mat4*> (entry->value)));
break;
}
case Double:
glUniform1d (entry->id, *reinterpret_cast <const double*> (entry->value));
break;
case Float:
glUniform1f (entry->id, *reinterpret_cast <const float*> (entry->value));
break;
case Integer:
glUniform1i (entry->id, *reinterpret_cast <const int*> (entry->value));
break;
case Vector4:
glUniform4fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec4*> (entry->value)));
break;
case Vector3:
glUniform3fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec3*> (entry->value)));
break;
case Vector2:
glUniform2fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec2*> (entry->value)));
break;
case Matrix4:
glUniformMatrix4fv (entry->id, 1, GL_FALSE, glm::value_ptr (*reinterpret_cast <const glm::mat4*> (entry->value)));
break;
}
}
// add reference uniforms
for (const auto& cur : this->m_referenceUniforms)
{
auto cur = this->m_referenceUniforms.begin ();
auto end = this->m_referenceUniforms.end ();
ReferenceUniformEntry* entry = cur.second;
for (; cur != end; cur ++)
switch (entry->type)
{
ReferenceUniformEntry* entry = (*cur).second;
switch (entry->type)
{
case Double:
glUniform1d (entry->id, *reinterpret_cast <const double*> (*entry->value));
break;
case Float:
glUniform1f (entry->id, *reinterpret_cast <const float*> (*entry->value));
break;
case Integer:
glUniform1i (entry->id, *reinterpret_cast <const int*> (*entry->value));
break;
case Vector4:
glUniform4fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec4*> (*entry->value)));
break;
case Vector3:
glUniform3fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec3*> (*entry->value)));
break;
case Vector2:
glUniform2fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec2*> (*entry->value)));
break;
case Matrix4:
glUniformMatrix4fv (entry->id, 1, GL_FALSE, glm::value_ptr (*reinterpret_cast <const glm::mat4*> (*entry->value)));
break;
}
case Double:
glUniform1d (entry->id, *reinterpret_cast <const double*> (*entry->value));
break;
case Float:
glUniform1f (entry->id, *reinterpret_cast <const float*> (*entry->value));
break;
case Integer:
glUniform1i (entry->id, *reinterpret_cast <const int*> (*entry->value));
break;
case Vector4:
glUniform4fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec4*> (*entry->value)));
break;
case Vector3:
glUniform3fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec3*> (*entry->value)));
break;
case Vector2:
glUniform2fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec2*> (*entry->value)));
break;
case Matrix4:
glUniformMatrix4fv (entry->id, 1, GL_FALSE, glm::value_ptr (*reinterpret_cast <const glm::mat4*> (*entry->value)));
break;
}
}
// used in animations when one of the frames is vertical instead of horizontal
// rotation with translation = origin and end of the image to display
if (this->g_Texture0Rotation != -1)
{
// used in animations when one of the frames is vertical instead of horizontal
// rotation with translation = origin and end of the image to display
glUniform4f (this->g_Texture0Rotation, rotation.x, rotation.y, rotation.z, rotation.w);
}
// this actually picks the origin point of the image from the atlast
if (this->g_Texture0Translation != -1)
{
// this actually picks the origin point of the image from the atlast
glUniform2f (this->g_Texture0Translation, translation.x, translation.y);
}
for (const auto& cur : this->m_attribs)
{
auto cur = this->m_attribs.begin ();
auto end = this->m_attribs.end ();
glEnableVertexAttribArray (cur->id);
glBindBuffer (GL_ARRAY_BUFFER, *cur->value);
glVertexAttribPointer (cur->id, cur->elements, cur->type, GL_FALSE, 0, nullptr);
for (; cur != end; cur ++)
{
glEnableVertexAttribArray ((*cur)->id);
glBindBuffer (GL_ARRAY_BUFFER, *(*cur)->value);
glVertexAttribPointer ((*cur)->id, (*cur)->elements, (*cur)->type, GL_FALSE, 0, nullptr);
if (DEBUG)
glObjectLabel (GL_BUFFER, *(*cur)->value, -1, (
"Image " + std::to_string (this->getMaterial ()->getImage ()->getId ()) +
" Pass " + this->m_pass->getShader() +
" " + (*cur)->name
).c_str ()
);
}
if (DEBUG)
glObjectLabel (GL_BUFFER, *cur->value, -1, (
"Image " + std::to_string (this->getMaterial ()->getImage ()->getId ()) +
" Pass " + this->m_pass->getShader() +
" " + cur->name
).c_str ()
);
}
// start actual rendering now
@ -287,13 +262,8 @@ void CPass::render ()
glDrawArrays (GL_TRIANGLES, 0, 6);
// disable vertex attribs array and textures
{
auto cur = this->m_attribs.begin ();
auto end = this->m_attribs.end ();
for (; cur != end; cur ++)
glDisableVertexAttribArray ((*cur)->id);
}
for (const auto& cur : this->m_attribs)
glDisableVertexAttribArray (cur->id);
// unbind all the used textures
glActiveTexture (GL_TEXTURE0);
@ -302,12 +272,9 @@ void CPass::render ()
// continue on the map from the second texture
if (this->m_finalTextures.empty () == false)
{
auto cur = this->m_finalTextures.begin ();
auto end = this->m_finalTextures.end ();
for (; cur != end; cur ++)
for (const auto& cur : this->m_finalTextures)
{
glActiveTexture (GL_TEXTURE0 + (*cur).first);
glActiveTexture (GL_TEXTURE0 + cur.first);
glBindTexture (GL_TEXTURE_2D, 0);
}
}
@ -600,19 +567,14 @@ void CPass::setupUniforms ()
}
}
for (const auto& cur : this->m_finalTextures)
{
auto cur = this->m_finalTextures.begin ();
auto end = this->m_finalTextures.end ();
std::ostringstream namestream;
for (; cur != end; cur ++)
{
std::ostringstream namestream;
namestream << "g_Texture" << cur.first << "Resolution";
namestream << "g_Texture" << (*cur).first << "Resolution";
texture = this->resolveTexture ((*cur).second, (*cur).first, texture);
this->addUniform (namestream.str (), texture->getResolution ());
}
texture = this->resolveTexture (cur.second, cur.first, texture);
this->addUniform (namestream.str (), texture->getResolution ());
}
auto projection = this->getMaterial ()->getImage ()->getScene ()->getScene ()->getOrthogonalProjection ();
@ -744,128 +706,113 @@ void CPass::setupTextures ()
void CPass::setupShaderVariables ()
{
// find variables in the shaders and set the value with the constants if possible
for (const auto& cur : this->m_pass->getConstants ())
{
// find variables in the shaders and set the value with the constants if possible
auto cur = this->m_pass->getConstants ().begin ();
auto end = this->m_pass->getConstants ().end ();
CShaderVariable* vertexVar = this->m_vertShader->findParameter (cur.first);
CShaderVariable* pixelVar = this->m_fragShader->findParameter (cur.first);
for (; cur != end; cur ++)
// variable not found, can be ignored
if (vertexVar == nullptr && pixelVar == nullptr)
continue;
// if both can be found, ensure they're the correct type
/*if (vertexVar != nullptr && pixelVar != nullptr)
{
CShaderVariable* vertexVar = this->m_vertShader->findParameter ((*cur).first);
CShaderVariable* pixelVar = this->m_fragShader->findParameter ((*cur).first);
if (vertexVar->getType () != pixelVar->getType ())
throw std::runtime_error ("Pixel and vertex shader variable types do not match");
}*/
// variable not found, can be ignored
if (vertexVar == nullptr && pixelVar == nullptr)
continue;
// get one instance of it
CShaderVariable* var = vertexVar == nullptr ? pixelVar : vertexVar;
// if both can be found, ensure they're the correct type
/*if (vertexVar != nullptr && pixelVar != nullptr)
// ensure the shader's and the constant are of the same type
if (cur.second->getType () != var->getType ())
{
// there's situations where this type mismatch is actually expected
// integers and floats are equivalent, this could be detected at load time
// but that'd mean to compile the shader in the load, and not on the render stage
// so take into account these conversions here
if (cur.second->is <CShaderConstantFloat> () == true && var->is <CShaderVariableInteger> () == true)
{
if (vertexVar->getType () != pixelVar->getType ())
throw std::runtime_error ("Pixel and vertex shader variable types do not match");
}*/
// get one instance of it
CShaderVariable* var = vertexVar == nullptr ? pixelVar : vertexVar;
// ensure the shader's and the constant are of the same type
if ((*cur).second->getType () != var->getType ())
// create an integer value from a float
this->addUniform (var->getName (), static_cast <int> (*cur.second->as <CShaderConstantFloat> ()->getValue ()));
}
else if (cur.second->is <CShaderConstantInteger> () == true && var->is <CShaderVariableFloat> () == true)
{
// there's situations where this type mismatch is actually expected
// integers and floats are equivalent, this could be detected at load time
// but that'd mean to compile the shader in the load, and not on the render stage
// so take into account these conversions here
// create a float value from an integer
this->addUniform (var->getName (), static_cast <float> (*cur.second->as <CShaderConstantInteger> ()->getValue ()));
}
else if (cur.second->is <CShaderConstantVector4> () == true && var->is <CShaderVariableVector2> () == true)
{
CShaderConstantVector4* val = cur.second->as <CShaderConstantVector4> ();
if ((*cur).second->is <CShaderConstantFloat> () == true && var->is <CShaderVariableInteger> () == true)
{
// create an integer value from a float
this->addUniform (var->getName (), static_cast <int> (*(*cur).second->as <CShaderConstantFloat> ()->getValue ()));
}
else if ((*cur).second->is <CShaderConstantInteger> () == true && var->is <CShaderVariableFloat> () == true)
{
// create a float value from an integer
this->addUniform (var->getName (), static_cast <float> (*(*cur).second->as <CShaderConstantInteger> ()->getValue ()));
}
else if ((*cur).second->is <CShaderConstantVector4> () == true && var->is <CShaderVariableVector2> () == true)
{
CShaderConstantVector4* val = (*cur).second->as <CShaderConstantVector4> ();
// create a new vector2 with the first two values
this->addUniform (var->getName (), {val->getValue ()->x, val->getValue ()->y});
}
else if (cur.second->is <CShaderConstantVector4> () == true && var->is <CShaderVariableVector3> () == true)
{
CShaderConstantVector4* val = cur.second->as <CShaderConstantVector4> ();
// create a new vector2 with the first two values
this->addUniform (var->getName (), {val->getValue ()->x, val->getValue ()->y});
}
else if ((*cur).second->is <CShaderConstantVector4> () == true && var->is <CShaderVariableVector3> () == true)
{
CShaderConstantVector4* val = (*cur).second->as <CShaderConstantVector4> ();
this->addUniform (var->getName (), {val->getValue ()->x, val->getValue ()->y, val->getValue ()->z});
}
else
{
sLog.exception (
"Constant ",
(*cur).first,
" type does not match pixel/vertex shader variable and cannot be converted (",
(*cur).second->getType (),
" to ",
var->getType ()
);
}
this->addUniform (var->getName (), {val->getValue ()->x, val->getValue ()->y, val->getValue ()->z});
}
else
{
// now determine the constant's type and register the correct uniform for it
if ((*cur).second->is <CShaderConstantFloat> ())
this->addUniform (var->getName (), (*cur).second->as <CShaderConstantFloat> ()->getValue ());
else if ((*cur).second->is <CShaderConstantInteger> ())
this->addUniform (var->getName (), (*cur).second->as <CShaderConstantInteger> ()->getValue ());
else if ((*cur).second->is <CShaderConstantVector4> ())
this->addUniform (var->getName (), (*cur).second->as <CShaderConstantVector4> ()->getValue ());
sLog.exception (
"Constant ",
cur.first,
" type does not match pixel/vertex shader variable and cannot be converted (",
cur.second->getType (),
" to ",
var->getType ()
);
}
}
}
{
auto cur = this->m_vertShader->getParameters ().begin ();
auto end = this->m_vertShader->getParameters ().end ();
for (; cur != end; cur ++)
else
{
if (this->m_uniforms.find ((*cur)->getName ()) != this->m_uniforms.end ())
continue;
if ((*cur)->is <CShaderVariableFloat> ())
this->addUniform ((*cur)->getName (), const_cast <float*> (reinterpret_cast <const float*> ((*cur)->as <CShaderVariableFloat> ()->getValue ())));
else if ((*cur)->is <CShaderVariableInteger> ())
this->addUniform ((*cur)->getName (), const_cast <int*> (reinterpret_cast <const int*> ((*cur)->as <CShaderVariableInteger> ()->getValue ())));
else if ((*cur)->is <CShaderVariableVector2> ())
this->addUniform ((*cur)->getName (), const_cast <glm::vec2*> (reinterpret_cast <const glm::vec2*> ((*cur)->as <CShaderVariableVector2> ()->getValue ())));
else if ((*cur)->is <CShaderVariableVector3> ())
this->addUniform ((*cur)->getName (), const_cast <glm::vec3*> (reinterpret_cast <const glm::vec3*> ((*cur)->as <CShaderVariableVector3> ()->getValue ())));
else if ((*cur)->is <CShaderVariableVector4> ())
this->addUniform ((*cur)->getName (), const_cast <glm::vec4*> (reinterpret_cast <const glm::vec4*> ((*cur)->as <CShaderVariableVector4> ()->getValue ())));
// now determine the constant's type and register the correct uniform for it
if (cur.second->is <CShaderConstantFloat> ())
this->addUniform (var->getName (), cur.second->as <CShaderConstantFloat> ()->getValue ());
else if (cur.second->is <CShaderConstantInteger> ())
this->addUniform (var->getName (), cur.second->as <CShaderConstantInteger> ()->getValue ());
else if (cur.second->is <CShaderConstantVector4> ())
this->addUniform (var->getName (), cur.second->as <CShaderConstantVector4> ()->getValue ());
}
}
for (const auto& cur : this->m_vertShader->getParameters ())
{
auto cur = this->m_fragShader->getParameters ().begin ();
auto end = this->m_fragShader->getParameters ().end ();
if (this->m_uniforms.find (cur->getName ()) != this->m_uniforms.end ())
continue;
for (; cur != end; cur ++)
{
if (this->m_uniforms.find ((*cur)->getName ()) != this->m_uniforms.end ())
continue;
if (cur->is <CShaderVariableFloat> ())
this->addUniform (cur->getName (), const_cast <float*> (reinterpret_cast <const float*> (cur->as <CShaderVariableFloat> ()->getValue ())));
else if (cur->is <CShaderVariableInteger> ())
this->addUniform (cur->getName (), const_cast <int*> (reinterpret_cast <const int*> (cur->as <CShaderVariableInteger> ()->getValue ())));
else if (cur->is <CShaderVariableVector2> ())
this->addUniform (cur->getName (), const_cast <glm::vec2*> (reinterpret_cast <const glm::vec2*> (cur->as <CShaderVariableVector2> ()->getValue ())));
else if (cur->is <CShaderVariableVector3> ())
this->addUniform (cur->getName (), const_cast <glm::vec3*> (reinterpret_cast <const glm::vec3*> (cur->as <CShaderVariableVector3> ()->getValue ())));
else if (cur->is <CShaderVariableVector4> ())
this->addUniform (cur->getName (), const_cast <glm::vec4*> (reinterpret_cast <const glm::vec4*> (cur->as <CShaderVariableVector4> ()->getValue ())));
}
if ((*cur)->is <CShaderVariableFloat> ())
this->addUniform ((*cur)->getName (), const_cast <float*> (reinterpret_cast <const float*> ((*cur)->as <CShaderVariableFloat> ()->getValue ())));
else if ((*cur)->is <CShaderVariableInteger> ())
this->addUniform ((*cur)->getName (), const_cast <int*> (reinterpret_cast <const int*> ((*cur)->as <CShaderVariableInteger> ()->getValue ())));
else if ((*cur)->is <CShaderVariableVector2> ())
this->addUniform ((*cur)->getName (), const_cast <glm::vec2*> (reinterpret_cast <const glm::vec2*> ((*cur)->as <CShaderVariableVector2> ()->getValue ())));
else if ((*cur)->is <CShaderVariableVector3> ())
this->addUniform ((*cur)->getName (), const_cast <glm::vec3*> (reinterpret_cast <const glm::vec3*> ((*cur)->as <CShaderVariableVector3> ()->getValue ())));
else if ((*cur)->is <CShaderVariableVector4> ())
this->addUniform ((*cur)->getName (), const_cast <glm::vec4*> (reinterpret_cast <const glm::vec4*> ((*cur)->as <CShaderVariableVector4> ()->getValue ())));
}
for (const auto& cur : this->m_fragShader->getParameters ())
{
if (this->m_uniforms.find (cur->getName ()) != this->m_uniforms.end ())
continue;
if (cur->is <CShaderVariableFloat> ())
this->addUniform (cur->getName (), const_cast <float*> (reinterpret_cast <const float*> (cur->as <CShaderVariableFloat> ()->getValue ())));
else if (cur->is <CShaderVariableInteger> ())
this->addUniform (cur->getName (), const_cast <int*> (reinterpret_cast <const int*> (cur->as <CShaderVariableInteger> ()->getValue ())));
else if (cur->is <CShaderVariableVector2> ())
this->addUniform (cur->getName (), const_cast <glm::vec2*> (reinterpret_cast <const glm::vec2*> (cur->as <CShaderVariableVector2> ()->getValue ())));
else if (cur->is <CShaderVariableVector3> ())
this->addUniform (cur->getName (), const_cast <glm::vec3*> (reinterpret_cast <const glm::vec3*> (cur->as <CShaderVariableVector3> ()->getValue ())));
else if (cur->is <CShaderVariableVector4> ())
this->addUniform (cur->getName (), const_cast <glm::vec4*> (reinterpret_cast <const glm::vec4*> (cur->as <CShaderVariableVector4> ()->getValue ())));
}
}

View File

@ -55,11 +55,8 @@ namespace WallpaperEngine::Render::Shaders
this->m_content = this->m_container->readIncludeShader (this->m_file);
// clone the combos into the baseCombos to keep track of values that must be embedded no matter what
auto cur = this->m_combos->begin ();
auto end = this->m_combos->end ();
for (; cur != end; cur ++)
this->m_baseCombos.insert (std::make_pair ((*cur).first, (*cur).second));
for (const auto& cur : *this->m_combos)
this->m_baseCombos.insert (std::make_pair (cur.first, cur.second));
}
bool Compiler::peekString(std::string str, std::string::const_iterator& it)
@ -526,36 +523,26 @@ namespace WallpaperEngine::Render::Shaders
"// Shader combo parameter definitions\n"
"// ======================================================\n";
// add combo values
for (const auto& cur : *this->m_foundCombos)
{
// add combo values
auto cur = this->m_foundCombos->begin ();
auto end = this->m_foundCombos->end ();
// find the right value for the combo in the combos map
auto combo = this->m_combos->find (cur.first);
for (; cur != end; cur++)
{
// find the right value for the combo in the combos map
auto combo = this->m_combos->find ((*cur).first);
if (combo == this->m_combos->end ())
continue;
if (combo == this->m_combos->end ())
continue;
finalCode += "#define " + (*cur).first + " " + std::to_string ((*combo).second) + "\n";
}
finalCode += "#define " + cur.first + " " + std::to_string ((*combo).second) + "\n";
}
// add base combos that come from the pass change that MUST be added
for (const auto& cur : this->m_baseCombos)
{
auto cur = this->m_baseCombos.begin ();
auto end = this->m_baseCombos.end ();
auto alreadyFound = this->m_foundCombos->find (cur.first);
for (; cur != end; cur ++)
{
auto alreadyFound = this->m_foundCombos->find ((*cur).first);
if (alreadyFound != this->m_foundCombos->end ())
continue;
if (alreadyFound != this->m_foundCombos->end ())
continue;
finalCode += "#define " + (*cur).first + " " + std::to_string ((*cur).second) + "\n";
}
finalCode += "#define " + cur.first + " " + std::to_string (cur.second) + "\n";
}
}
@ -737,16 +724,9 @@ namespace WallpaperEngine::Render::Shaders
Variables::CShaderVariable* Compiler::findParameter (const std::string& identifier)
{
auto cur = this->m_parameters.begin ();
auto end = this->m_parameters.end ();
for (; cur != end; cur ++)
{
if ((*cur)->getIdentifierName () == identifier)
{
return (*cur);
}
}
for (const auto& cur : this->m_parameters)
if (cur->getIdentifierName () == identifier)
return cur;
return nullptr;
}