mirror of
https://github.com/Almamu/linux-wallpaperengine.git
synced 2025-07-13 21:02:34 +08:00
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:
parent
d370e028ff
commit
a24b1923f6
@ -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
307
main.cpp
@ -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;
|
||||
}
|
68
src/Steam/FileSystem/FileSystem.cpp
Normal file
68
src/Steam/FileSystem/FileSystem.cpp
Normal 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);
|
||||
}
|
9
src/Steam/FileSystem/FileSystem.h
Normal file
9
src/Steam/FileSystem/FileSystem.h
Normal 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);
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
@ -14,9 +14,6 @@ namespace WallpaperEngine::Assets
|
||||
class CCombinedContainer : public CContainer
|
||||
{
|
||||
public:
|
||||
CCombinedContainer () {}
|
||||
~CCombinedContainer () {}
|
||||
|
||||
/**
|
||||
* Adds a container to the list
|
||||
*
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
};
|
||||
};
|
@ -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));
|
||||
}
|
||||
}
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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)
|
||||
|
101
src/WallpaperEngine/Render/Drivers/COpenGLDriver.cpp
Normal file
101
src/WallpaperEngine/Render/Drivers/COpenGLDriver.cpp
Normal 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;
|
||||
}
|
29
src/WallpaperEngine/Render/Drivers/COpenGLDriver.h
Normal file
29
src/WallpaperEngine/Render/Drivers/COpenGLDriver.h
Normal 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;
|
||||
};
|
||||
}
|
3
src/WallpaperEngine/Render/Drivers/CVideoDriver.cpp
Normal file
3
src/WallpaperEngine/Render/Drivers/CVideoDriver.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
#include "CVideoDriver.h"
|
||||
|
||||
using namespace WallpaperEngine::Render::Drivers;
|
19
src/WallpaperEngine/Render/Drivers/CVideoDriver.h
Normal file
19
src/WallpaperEngine/Render/Drivers/CVideoDriver.h
Normal 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;
|
||||
};
|
||||
}
|
@ -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 ()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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 ())));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user