mirror of
https://github.com/Almamu/linux-wallpaperengine.git
synced 2025-07-14 21:32:23 +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
|
linux-wallpaperengine
|
||||||
main.cpp
|
main.cpp
|
||||||
|
|
||||||
|
src/Steam/FileSystem/FileSystem.h
|
||||||
|
src/Steam/FileSystem/FileSystem.cpp
|
||||||
|
|
||||||
src/WallpaperEngine/Logging/CLog.cpp
|
src/WallpaperEngine/Logging/CLog.cpp
|
||||||
src/WallpaperEngine/Logging/CLog.h
|
src/WallpaperEngine/Logging/CLog.h
|
||||||
|
|
||||||
@ -83,6 +86,10 @@ add_executable(
|
|||||||
src/WallpaperEngine/Render/Shaders/Compiler.h
|
src/WallpaperEngine/Render/Shaders/Compiler.h
|
||||||
src/WallpaperEngine/Render/Shaders/Compiler.cpp
|
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.h
|
||||||
src/WallpaperEngine/Render/CRenderContext.cpp
|
src/WallpaperEngine/Render/CRenderContext.cpp
|
||||||
src/WallpaperEngine/Render/CTextureCache.h
|
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 <FreeImage.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
#include <csignal>
|
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <SDL_mixer.h>
|
||||||
|
#include <csignal>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <iostream>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "WallpaperEngine/Core/CProject.h"
|
#include "WallpaperEngine/Core/CProject.h"
|
||||||
#include "WallpaperEngine/Render/CRenderContext.h"
|
#include "WallpaperEngine/Render/CRenderContext.h"
|
||||||
@ -22,25 +23,18 @@
|
|||||||
#include "WallpaperEngine/Assets/CCombinedContainer.h"
|
#include "WallpaperEngine/Assets/CCombinedContainer.h"
|
||||||
#include "WallpaperEngine/Assets/CPackageLoadException.h"
|
#include "WallpaperEngine/Assets/CPackageLoadException.h"
|
||||||
|
|
||||||
|
#include "WallpaperEngine/Render/Drivers/COpenGLDriver.h"
|
||||||
|
#include "Steam/FileSystem/FileSystem.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
#define WORKSHOP_APP_ID 431960
|
||||||
|
#define APP_DIRECTORY "wallpaper_engine"
|
||||||
|
|
||||||
float g_Time;
|
float g_Time;
|
||||||
float g_TimeLast;
|
float g_TimeLast;
|
||||||
bool g_KeepRunning = true;
|
bool g_KeepRunning = true;
|
||||||
int g_AudioVolume = 15;
|
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)
|
void print_help (const char* route)
|
||||||
{
|
{
|
||||||
sLog.out ("Usage: ", route, " [options] background_path/background_id");
|
sLog.out ("Usage: ", route, " [options] background_path/background_id");
|
||||||
@ -81,86 +75,11 @@ void signalhandler(int sig)
|
|||||||
g_KeepRunning = false;
|
g_KeepRunning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int handleValidatePath (const char* path, std::string& final)
|
void addPkg (CCombinedContainer* containers, const std::filesystem::path& path, std::string pkgfile)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
std::string scene_path = path + pkgfile;
|
auto scene_path = std::filesystem::path (path) / pkgfile;
|
||||||
|
|
||||||
// add the package to the list
|
// add the package to the list
|
||||||
containers->add (new WallpaperEngine::Assets::CPackage (scene_path));
|
containers->add (new WallpaperEngine::Assets::CPackage (scene_path));
|
||||||
@ -278,7 +197,7 @@ CVirtualContainer* buildVirtualContainer ()
|
|||||||
return container;
|
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;
|
GLint width, height;
|
||||||
|
|
||||||
@ -344,8 +263,8 @@ int main (int argc, char* argv[])
|
|||||||
bool shouldListPropertiesAndStop = false;
|
bool shouldListPropertiesAndStop = false;
|
||||||
FREE_IMAGE_FORMAT screenshotFormat = FIF_UNKNOWN;
|
FREE_IMAGE_FORMAT screenshotFormat = FIF_UNKNOWN;
|
||||||
std::string path;
|
std::string path;
|
||||||
std::string assetsDir;
|
std::filesystem::path assetsPath;
|
||||||
std::string screenshotPath;
|
std::filesystem::path screenshotPath;
|
||||||
|
|
||||||
static struct option long_options [] = {
|
static struct option long_options [] = {
|
||||||
{"screen-root", required_argument, 0, 'r'},
|
{"screen-root", required_argument, 0, 'r'},
|
||||||
@ -413,8 +332,7 @@ int main (int argc, char* argv[])
|
|||||||
maximumFPS = atoi (optarg);
|
maximumFPS = atoi (optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'a':
|
case 'a': assetsPath = optarg;
|
||||||
assetsDir = optarg;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
@ -444,103 +362,60 @@ int main (int argc, char* argv[])
|
|||||||
// validate screenshot file just to make sure
|
// validate screenshot file just to make sure
|
||||||
if (shouldTakeScreenshot == true)
|
if (shouldTakeScreenshot == true)
|
||||||
{
|
{
|
||||||
// ensure the file is one of the supported formats
|
if (screenshotPath.has_extension () == false)
|
||||||
std::string extension = screenshotPath.substr (screenshotPath.find_last_of (".") + 1);
|
sLog.exception ("Cannot determine screenshot format");
|
||||||
|
|
||||||
if (extension == "bmp")
|
std::string extension = screenshotPath.extension ();
|
||||||
|
|
||||||
|
if (extension == ".bmp")
|
||||||
screenshotFormat = FIF_BMP;
|
screenshotFormat = FIF_BMP;
|
||||||
else if (extension == "png")
|
else if (extension == ".png")
|
||||||
screenshotFormat = FIF_PNG;
|
screenshotFormat = FIF_PNG;
|
||||||
else if (extension == "jpg" || extension == "jpeg")
|
else if (extension == ".jpg" || extension == ".jpeg")
|
||||||
screenshotFormat = FIF_JPEG;
|
screenshotFormat = FIF_JPEG;
|
||||||
else
|
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
|
// 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)
|
if (path.find ('/') == std::string::npos)
|
||||||
{
|
path = Steam::FileSystem::workshopDirectory (WORKSHOP_APP_ID, path);
|
||||||
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 += "/";
|
|
||||||
|
|
||||||
|
WallpaperEngine::Assets::CCombinedContainer containers;
|
||||||
// the background's path is required to load project.json regardless of the type of background we're using
|
// 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
|
// add the virtual container for mocked up files
|
||||||
containers->add (buildVirtualContainer ());
|
containers.add (buildVirtualContainer ());
|
||||||
// try to add the common packages
|
// try to add the common packages
|
||||||
addPkg (containers, path, "scene.pkg");
|
addPkg (&containers, path, "scene.pkg");
|
||||||
addPkg (containers, path, "gifscene.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;
|
assetsPath = Steam::FileSystem::appDirectory (APP_DIRECTORY, "assets");
|
||||||
|
|
||||||
int error = handleValidatePath (tmppath.c_str (), tmppath);
|
|
||||||
|
|
||||||
if (error != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
assetsDir = tmppath;
|
|
||||||
sLog.out ("Found wallpaper engine's assets at ", assetsDir);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
catch (std::runtime_error)
|
||||||
if (assetsDir.empty () == true)
|
|
||||||
{
|
{
|
||||||
unsigned long len = strlen (argv [0]) + 1;
|
// set current path as assets' folder
|
||||||
char* copy = new char[len];
|
std::filesystem::path directory = std::filesystem::canonical ("/proc/self/exe")
|
||||||
|
.parent_path () / "assets";
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
validatePath (assetsDir.c_str (), assetsDir);
|
sLog.out ("Found wallpaper engine's assets at ", assetsPath, " based on --assets-dir parameter");
|
||||||
sLog.out ("Found wallpaper engine's assets at ", assetsDir, " 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");
|
sLog.exception ("Cannot determine a valid path for the wallpaper engine assets");
|
||||||
|
|
||||||
// add containers to the list
|
// add containers to the list
|
||||||
containers->add (new WallpaperEngine::Assets::CDirectory (assetsDir + "/"));
|
containers.add (new WallpaperEngine::Assets::CDirectory (assetsPath));
|
||||||
|
|
||||||
// parse the project.json file
|
// 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
|
// go to the right folder so the videos will play
|
||||||
if (project->getWallpaper ()->is <WallpaperEngine::Core::CVideo> () == true)
|
if (project->getWallpaper ()->is <WallpaperEngine::Core::CVideo> () == true)
|
||||||
chdir (path.c_str ());
|
chdir (path.c_str ());
|
||||||
@ -570,98 +445,49 @@ int main (int argc, char* argv[])
|
|||||||
std::signal(SIGINT, signalhandler);
|
std::signal(SIGINT, signalhandler);
|
||||||
std::signal(SIGTERM, 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)
|
if (shouldEnableAudio == true && SDL_Init (SDL_INIT_AUDIO) < 0)
|
||||||
{
|
{
|
||||||
sLog.error ("SDL", "Cannot initialize SDL audio system, SDL_GetError: ", SDL_GetError());
|
sLog.error ("Cannot initialize SDL audio system, SDL_GetError: ", SDL_GetError());
|
||||||
sLog.error ("SDL", "Continuing without audio support");
|
sLog.error ("Continuing without audio support");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initialize OpenGL driver
|
||||||
|
WallpaperEngine::Render::Drivers::COpenGLDriver videoDriver ("Wallpaper Engine");
|
||||||
// initialize custom context class
|
// 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
|
// initialize mouse support
|
||||||
context->setMouse (new CMouseInput (window));
|
context.setMouse (new CMouseInput (videoDriver.getWindow ()));
|
||||||
// set the default viewport
|
|
||||||
context->setDefaultViewport ({0, 0, windowWidth, windowHeight});
|
|
||||||
// ensure the context knows what wallpaper to render
|
// ensure the context knows what wallpaper to render
|
||||||
context->setWallpaper (
|
context.setWallpaper (
|
||||||
WallpaperEngine::Render::CWallpaper::fromWallpaper (project->getWallpaper (), context)
|
WallpaperEngine::Render::CWallpaper::fromWallpaper (project->getWallpaper (), &context)
|
||||||
);
|
);
|
||||||
|
|
||||||
// update maximum FPS if it's a video
|
// update maximum FPS if it's a video
|
||||||
if (context->getWallpaper ()->is <WallpaperEngine::Render::CVideo> () == true)
|
if (context.getWallpaper ()->is <WallpaperEngine::Render::CVideo> () == true)
|
||||||
maximumFPS = context->getWallpaper ()->as <WallpaperEngine::Render::CVideo> ()->getFPS ();
|
maximumFPS = context.getWallpaper ()->as <WallpaperEngine::Render::CVideo> ()->getFPS ();
|
||||||
|
|
||||||
// TODO: FIGURE OUT THE REQUIRED INPUT MODE, AS SOME WALLPAPERS USE THINGS LIKE MOUSE POSITION
|
float startTime, endTime, minimumTime = 1.0f / maximumFPS;
|
||||||
// glfwSetInputMode (window, GLFW_STICKY_KEYS, GL_TRUE);
|
|
||||||
|
|
||||||
double startTime, endTime, minimumTime = 1.0 / maximumFPS;
|
while (videoDriver.closeRequested () == false && g_KeepRunning == true)
|
||||||
|
|
||||||
uint32_t frameCounter = 0;
|
|
||||||
|
|
||||||
while (glfwWindowShouldClose (window) == 0 && 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
|
// keep track of the previous frame's time
|
||||||
g_TimeLast = g_Time;
|
g_TimeLast = g_Time;
|
||||||
// calculate the current time value
|
// calculate the current time value
|
||||||
g_Time = (float) glfwGetTime ();
|
g_Time = videoDriver.getRenderTime ();
|
||||||
// get the start time of the frame
|
// get the start time of the frame
|
||||||
startTime = glfwGetTime ();
|
startTime = g_Time;
|
||||||
// render the scene
|
// render the scene
|
||||||
context->render ();
|
context.render ();
|
||||||
// do buffer swapping
|
|
||||||
glfwSwapBuffers (window);
|
|
||||||
// poll for events (like closing the window)
|
|
||||||
glfwPollEvents ();
|
|
||||||
// get the end time of the frame
|
// get the end time of the frame
|
||||||
endTime = glfwGetTime ();
|
endTime = videoDriver.getRenderTime ();
|
||||||
|
|
||||||
// ensure the frame time is correct to not overrun FPS
|
// ensure the frame time is correct to not overrun FPS
|
||||||
if ((endTime - startTime) < minimumTime)
|
if ((endTime - startTime) < minimumTime)
|
||||||
usleep ((minimumTime - (endTime - startTime)) * CLOCKS_PER_SEC);
|
usleep ((minimumTime - (endTime - startTime)) * CLOCKS_PER_SEC);
|
||||||
|
|
||||||
frameCounter ++;
|
if (shouldTakeScreenshot == true && videoDriver.getFrameCounter () == 5)
|
||||||
|
|
||||||
if (frameCounter == 5 && shouldTakeScreenshot == true)
|
|
||||||
{
|
{
|
||||||
takeScreenshot (context->getWallpaper (), screenshotPath, screenshotFormat);
|
takeScreenshot (context.getWallpaper (), screenshotPath, screenshotFormat);
|
||||||
// disable screenshot just in case the counter overflows
|
// disable screenshot just in case the counter overflows
|
||||||
shouldTakeScreenshot = false;
|
shouldTakeScreenshot = false;
|
||||||
}
|
}
|
||||||
@ -672,16 +498,9 @@ int main (int argc, char* argv[])
|
|||||||
|
|
||||||
sLog.out ("Stop requested");
|
sLog.out ("Stop requested");
|
||||||
|
|
||||||
// terminate gl
|
|
||||||
glfwTerminate ();
|
|
||||||
// terminate free image
|
|
||||||
FreeImage_DeInitialise ();
|
|
||||||
// terminate SDL
|
// terminate SDL
|
||||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||||
SDL_Quit ();
|
SDL_Quit ();
|
||||||
|
|
||||||
// free context
|
|
||||||
delete context;
|
|
||||||
|
|
||||||
return 0;
|
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
|
const void* CCombinedContainer::readFile (std::string filename, uint32_t* length) const
|
||||||
{
|
{
|
||||||
auto cur = this->m_containers.begin ();
|
for (auto cur : this->m_containers)
|
||||||
auto end = this->m_containers.end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// try to read the file on the current container, if the file doesn't exists
|
// try to read the file on the current container, if the file doesn't exists
|
||||||
// an exception will be thrown
|
// an exception will be thrown
|
||||||
return (*cur)->readFile (filename, length);
|
return cur->readFile (filename, length);
|
||||||
}
|
}
|
||||||
catch (CAssetLoadException& ex)
|
catch (CAssetLoadException& ex)
|
||||||
{
|
{
|
||||||
|
@ -14,9 +14,6 @@ namespace WallpaperEngine::Assets
|
|||||||
class CCombinedContainer : public CContainer
|
class CCombinedContainer : public CContainer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CCombinedContainer () {}
|
|
||||||
~CCombinedContainer () {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a container to the list
|
* Adds a container to the list
|
||||||
*
|
*
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "CDirectory.h"
|
#include "CDirectory.h"
|
||||||
#include "CAssetLoadException.h"
|
#include "CAssetLoadException.h"
|
||||||
|
|
||||||
using namespace WallpaperEngine::Assets;
|
using namespace WallpaperEngine::Assets;
|
||||||
|
|
||||||
CDirectory::CDirectory (std::string basepath) :
|
CDirectory::CDirectory (std::filesystem::path basepath) :
|
||||||
m_basepath (std::move (basepath))
|
m_basepath (std::move(basepath))
|
||||||
{
|
{
|
||||||
// ensure the specified path exists
|
// ensure the specified path exists
|
||||||
struct stat buffer;
|
struct stat buffer;
|
||||||
@ -26,7 +28,7 @@ CDirectory::~CDirectory ()
|
|||||||
|
|
||||||
const void* CDirectory::readFile (std::string filename, uint32_t* length) const
|
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
|
// first check the cache, if the file is there already just return the data in there
|
||||||
auto it = this->m_cache.find (final);
|
auto it = this->m_cache.find (final);
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
#include "CContainer.h"
|
#include "CContainer.h"
|
||||||
#include "CFileEntry.h"
|
#include "CFileEntry.h"
|
||||||
@ -12,12 +13,12 @@ namespace WallpaperEngine::Assets
|
|||||||
class CDirectory : public CContainer
|
class CDirectory : public CContainer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CDirectory (std::string basepath);
|
CDirectory (std::filesystem::path basepath);
|
||||||
~CDirectory ();
|
~CDirectory ();
|
||||||
|
|
||||||
const void* readFile (std::string filename, uint32_t* length) const override;
|
const void* readFile (std::string filename, uint32_t* length) const override;
|
||||||
private:
|
private:
|
||||||
std::string m_basepath;
|
std::filesystem::path m_basepath;
|
||||||
std::map <std::string, CFileEntry> m_cache;
|
std::map <std::string, CFileEntry> m_cache;
|
||||||
};
|
};
|
||||||
};
|
};
|
@ -21,8 +21,8 @@ public:
|
|||||||
uint32_t length;
|
uint32_t length;
|
||||||
};
|
};
|
||||||
|
|
||||||
CPackage::CPackage (const std::string& path) :
|
CPackage::CPackage (std::filesystem::path path) :
|
||||||
m_path (path),
|
m_path (std::move(path)),
|
||||||
m_contents ()
|
m_contents ()
|
||||||
{
|
{
|
||||||
this->init ();
|
this->init ();
|
||||||
@ -150,32 +150,25 @@ void CPackage::loadFiles (FILE* fp)
|
|||||||
// get current baseOffset, this is where the files start
|
// get current baseOffset, this is where the files start
|
||||||
long baseOffset = ftell (fp);
|
long baseOffset = ftell (fp);
|
||||||
|
|
||||||
// read file contents now
|
for (const auto& cur : list)
|
||||||
auto cur = list.begin ();
|
|
||||||
auto end = list.end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
{
|
||||||
long offset = (*cur).offset + baseOffset;
|
long offset = cur.offset + baseOffset;
|
||||||
|
|
||||||
// with all the data we can jump to the offset and read the content
|
// with all the data we can jump to the offset and read the content
|
||||||
if (fseek (fp, offset, SEEK_SET) != 0)
|
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
|
// 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;
|
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
|
// add the file to the map
|
||||||
this->m_contents.insert (std::make_pair <std::string, CFileEntry> (
|
this->m_contents.insert_or_assign (cur.filename, CFileEntry (fileContents, cur.length));
|
||||||
std::move((*cur).filename),
|
|
||||||
CFileEntry (fileContents, (*cur).length))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,3 @@
|
|||||||
//
|
|
||||||
// Created by almamu on 8/8/21.
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -10,6 +6,7 @@
|
|||||||
#include <exception>
|
#include <exception>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
#include "CContainer.h"
|
#include "CContainer.h"
|
||||||
#include "CFileEntry.h"
|
#include "CFileEntry.h"
|
||||||
@ -19,7 +16,7 @@ namespace WallpaperEngine::Assets
|
|||||||
class CPackage : public CContainer
|
class CPackage : public CContainer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CPackage (const std::string& path);
|
CPackage (std::filesystem::path path);
|
||||||
~CPackage ();
|
~CPackage ();
|
||||||
|
|
||||||
const void* readFile (std::string filename, uint32_t* length) const override;
|
const void* readFile (std::string filename, uint32_t* length) const override;
|
||||||
@ -62,7 +59,7 @@ namespace WallpaperEngine::Assets
|
|||||||
uint32_t readInteger (FILE* fp);
|
uint32_t readInteger (FILE* fp);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_path;
|
std::filesystem::path m_path;
|
||||||
std::map <std::string, CFileEntry> m_contents;
|
std::map <std::string, CFileEntry> m_contents;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -322,16 +322,10 @@ CTexture::TextureHeader::TextureHeader ()
|
|||||||
|
|
||||||
CTexture::TextureHeader::~TextureHeader ()
|
CTexture::TextureHeader::~TextureHeader ()
|
||||||
{
|
{
|
||||||
auto imgCur = this->images.begin ();
|
for (const auto& imgCur : this->images)
|
||||||
auto imgEnd = this->images.end ();
|
|
||||||
|
|
||||||
for (; imgCur != imgEnd; imgCur ++)
|
|
||||||
{
|
{
|
||||||
auto cur = (*imgCur).second.begin ();
|
for (auto cur : imgCur.second)
|
||||||
auto end = (*imgCur).second.end ();
|
delete cur;
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
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)
|
if (effects_it != data.end () && (*effects_it).is_array () == true)
|
||||||
{
|
{
|
||||||
auto cur = (*effects_it).begin ();
|
for (const auto& cur : *effects_it)
|
||||||
auto end = (*effects_it).end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
{
|
||||||
auto effectVisible = jsonFindUserConfig <CUserSettingBoolean, bool> (data, "visible", true);
|
auto effectVisible = jsonFindUserConfig <CUserSettingBoolean, bool> (data, "visible", true);
|
||||||
|
|
||||||
object->insertEffect (
|
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)
|
if (dependencies_it != data.end () && (*dependencies_it).is_array () == true)
|
||||||
{
|
{
|
||||||
auto cur = (*dependencies_it).begin ();
|
for (const auto& cur : *dependencies_it)
|
||||||
auto end = (*dependencies_it).end ();
|
object->insertDependency (cur);
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
|
||||||
object->insertDependency (*cur);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return object;
|
return object;
|
||||||
|
@ -56,12 +56,9 @@ CProject* CProject::fromFile (const std::string& filename, CContainer* container
|
|||||||
|
|
||||||
if (properties != (*general).end ())
|
if (properties != (*general).end ())
|
||||||
{
|
{
|
||||||
auto cur = (*properties).begin ();
|
for (const auto& cur : (*properties).items ())
|
||||||
auto end = (*properties).end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
{
|
||||||
Projects::CProperty* property = Projects::CProperty::fromJSON (*cur, cur.key ());
|
Projects::CProperty* property = Projects::CProperty::fromJSON (cur.value (), cur.key ());
|
||||||
|
|
||||||
if (property != nullptr)
|
if (property != nullptr)
|
||||||
project->insertProperty (property);
|
project->insertProperty (property);
|
||||||
|
@ -101,15 +101,8 @@ CScene* CScene::fromFile (const std::string& filename, CContainer* container)
|
|||||||
WallpaperEngine::Core::aToColorf(skylightcolor)
|
WallpaperEngine::Core::aToColorf(skylightcolor)
|
||||||
);
|
);
|
||||||
|
|
||||||
auto cur = (*objects_it).begin ();
|
for (const auto& cur : *objects_it)
|
||||||
auto end = (*objects_it).end ();
|
scene->insertObject (CObject::fromJSON (cur, scene, container));
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
|
||||||
scene->insertObject (
|
|
||||||
CObject::fromJSON (*cur, scene, container)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return scene;
|
return scene;
|
||||||
}
|
}
|
||||||
|
@ -84,21 +84,17 @@ CEffect* CEffect::fromJSON (json data, CUserSettingBoolean* visible, Core::CObje
|
|||||||
|
|
||||||
Images::CMaterial* material = effect->getMaterials ().at (passNumber);
|
Images::CMaterial* material = effect->getMaterials ().at (passNumber);
|
||||||
|
|
||||||
auto passCur = material->getPasses ().begin ();
|
for (const auto& passCur : material->getPasses ())
|
||||||
auto passEnd = material->getPasses ().end ();
|
|
||||||
|
|
||||||
for (; passCur != passEnd; passCur ++)
|
|
||||||
{
|
{
|
||||||
if (textures_it != (*cur).end ())
|
if (textures_it != (*cur).end ())
|
||||||
{
|
{
|
||||||
auto texturesCur = (*textures_it).begin ();
|
int textureNumber = 0;
|
||||||
auto texturesEnd = (*textures_it).end ();
|
|
||||||
|
|
||||||
for (int textureNumber = 0; texturesCur != texturesEnd; texturesCur ++)
|
for (const auto& texturesCur : (*textures_it))
|
||||||
{
|
{
|
||||||
std::string texture;
|
std::string texture;
|
||||||
|
|
||||||
if ((*texturesCur).is_null () == true)
|
if (texturesCur.is_null () == true)
|
||||||
{
|
{
|
||||||
if (textureNumber == 0)
|
if (textureNumber == 0)
|
||||||
{
|
{
|
||||||
@ -113,15 +109,15 @@ CEffect* CEffect::fromJSON (json data, CUserSettingBoolean* visible, Core::CObje
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
texture = *texturesCur;
|
texture = texturesCur;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> passTextures = (*passCur)->getTextures ();
|
std::vector<std::string> passTextures = passCur->getTextures ();
|
||||||
|
|
||||||
if (textureNumber < passTextures.size ())
|
if (textureNumber < passTextures.size ())
|
||||||
(*passCur)->setTexture (textureNumber, texture);
|
passCur->setTexture (textureNumber, texture);
|
||||||
else
|
else
|
||||||
(*passCur)->insertTexture (texture);
|
passCur->insertTexture (texture);
|
||||||
|
|
||||||
textureNumber ++;
|
textureNumber ++;
|
||||||
}
|
}
|
||||||
@ -129,12 +125,12 @@ CEffect* CEffect::fromJSON (json data, CUserSettingBoolean* visible, Core::CObje
|
|||||||
|
|
||||||
if (combos_it != (*cur).end ())
|
if (combos_it != (*cur).end ())
|
||||||
{
|
{
|
||||||
CEffect::combosFromJSON (combos_it, *passCur);
|
CEffect::combosFromJSON (combos_it, passCur);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (constants_it != (*cur).end ())
|
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)
|
void CEffect::combosFromJSON (json::const_iterator combos_it, Core::Objects::Images::Materials::CPass* pass)
|
||||||
{
|
{
|
||||||
auto cur = (*combos_it).begin ();
|
for (const auto& cur : (*combos_it).items ())
|
||||||
auto end = (*combos_it).end ();
|
pass->insertCombo (cur.key (), cur.value ());
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
|
||||||
pass->insertCombo (cur.key (), *cur);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEffect::constantsFromJSON (json::const_iterator constants_it, Core::Objects::Images::Materials::CPass* pass)
|
void CEffect::constantsFromJSON (json::const_iterator constants_it, Core::Objects::Images::Materials::CPass* pass)
|
||||||
{
|
{
|
||||||
auto cur = (*constants_it).begin ();
|
for (auto& cur : (*constants_it).items ())
|
||||||
auto end = (*constants_it).end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
{
|
||||||
json::const_iterator val = cur;
|
auto val = cur.value ();
|
||||||
|
|
||||||
Effects::Constants::CShaderConstant* constant = nullptr;
|
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
|
// for the UI, take the value, which is what we need
|
||||||
|
|
||||||
// TODO: SUPPORT USER SETTINGS HERE
|
// 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");
|
sLog.error ("Found object for shader constant without \"value\" member");
|
||||||
continue;
|
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
|
// 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
|
else
|
||||||
{
|
{
|
||||||
sLog.exception ("unknown shader constant type ", *val);
|
sLog.exception ("unknown shader constant type ", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
pass->insertConstant (cur.key (), constant);
|
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)
|
void CEffect::fbosFromJSON (json::const_iterator fbos_it, CEffect* effect)
|
||||||
{
|
{
|
||||||
auto cur = (*fbos_it).begin ();
|
for (const auto& cur : (*fbos_it))
|
||||||
auto end = (*fbos_it).end ();
|
effect->insertFBO (Effects::CFBO::fromJSON (cur));
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
|
||||||
effect->insertFBO (
|
|
||||||
Effects::CFBO::fromJSON (*cur)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEffect::dependencyFromJSON (json::const_iterator dependencies_it, CEffect* effect)
|
void CEffect::dependencyFromJSON (json::const_iterator dependencies_it, CEffect* effect)
|
||||||
{
|
{
|
||||||
auto cur = (*dependencies_it).begin ();
|
for (const auto& cur : (*dependencies_it))
|
||||||
auto end = (*dependencies_it).end ();
|
effect->insertDependency (cur);
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
|
||||||
effect->insertDependency (*cur);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEffect::materialsFromJSON (json::const_iterator passes_it, CEffect* effect, const CContainer* container)
|
void CEffect::materialsFromJSON (json::const_iterator passes_it, CEffect* effect, const CContainer* container)
|
||||||
{
|
{
|
||||||
auto cur = (*passes_it).begin ();
|
for (const auto& cur : (*passes_it))
|
||||||
auto end = (*passes_it).end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
{
|
||||||
auto materialfile = (*cur).find ("material");
|
auto materialfile = cur.find ("material");
|
||||||
auto target = (*cur).find ("target");
|
auto target = cur.find ("target");
|
||||||
auto bind = (*cur).find ("bind");
|
auto bind = cur.find ("bind");
|
||||||
|
|
||||||
if (materialfile == (*cur).end ())
|
if (materialfile == cur.end ())
|
||||||
sLog.exception ("Found an effect ", effect->m_name, " without material");
|
sLog.exception ("Found an effect ", effect->m_name, " without material");
|
||||||
|
|
||||||
Images::CMaterial* material = nullptr;
|
Images::CMaterial* material = nullptr;
|
||||||
|
|
||||||
if (target == (*cur).end ())
|
if (target == cur.end ())
|
||||||
{
|
|
||||||
material = Images::CMaterial::fromFile ((*materialfile).get <std::string> (), container);
|
material = Images::CMaterial::fromFile ((*materialfile).get <std::string> (), container);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
material = Images::CMaterial::fromFile ((*materialfile).get <std::string> (), *target, container);
|
material = Images::CMaterial::fromFile ((*materialfile).get <std::string> (), *target, container);
|
||||||
}
|
|
||||||
|
|
||||||
if (bind != (*cur).end ())
|
if (bind != cur.end ())
|
||||||
{
|
{
|
||||||
auto bindCur = (*bind).begin ();
|
for (const auto& bindCur : (*bind))
|
||||||
auto bindEnd = (*bind).end ();
|
material->insertTextureBind (Effects::CBind::fromJSON (bindCur));
|
||||||
|
|
||||||
for (; bindCur != bindEnd; bindCur ++)
|
|
||||||
{
|
|
||||||
material->insertTextureBind (
|
|
||||||
Effects::CBind::fromJSON (*bindCur)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
effect->insertMaterial (material);
|
effect->insertMaterial (material);
|
||||||
@ -290,16 +254,9 @@ bool CEffect::isVisible () const
|
|||||||
|
|
||||||
Effects::CFBO* CEffect::findFBO (const std::string& name)
|
Effects::CFBO* CEffect::findFBO (const std::string& name)
|
||||||
{
|
{
|
||||||
auto cur = this->m_fbos.begin ();
|
for (const auto& cur : this->m_fbos)
|
||||||
auto end = this->m_fbos.end ();
|
if (cur->getName () == name)
|
||||||
|
return cur;
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
|
||||||
if ((*cur)->getName () == name)
|
|
||||||
{
|
|
||||||
return (*cur);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sLog.exception ("cannot find fbo ", name);
|
sLog.exception ("cannot find fbo ", name);
|
||||||
}
|
}
|
||||||
|
@ -33,36 +33,14 @@ CParticle* CParticle::fromFile (
|
|||||||
|
|
||||||
if (controlpoint_it != data.end ())
|
if (controlpoint_it != data.end ())
|
||||||
{
|
{
|
||||||
auto cur = (*controlpoint_it).begin ();
|
for (const auto& cur : (*controlpoint_it))
|
||||||
auto end = (*controlpoint_it).end ();
|
particle->insertControlPoint (Particles::CControlPoint::fromJSON (cur));
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
|
||||||
particle->insertControlPoint (
|
|
||||||
Particles::CControlPoint::fromJSON (*cur)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cur = (*emitter_it).begin ();
|
for (const auto& cur : (*emitter_it))
|
||||||
auto end = (*emitter_it).end ();
|
particle->insertEmitter (Particles::CEmitter::fromJSON (cur));
|
||||||
|
for (const auto&cur : (*initializer_it))
|
||||||
for (; cur != end; cur ++)
|
particle->insertInitializer (Particles::CInitializer::fromJSON (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)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return particle;
|
return particle;
|
||||||
}
|
}
|
||||||
|
@ -42,13 +42,8 @@ WallpaperEngine::Core::CObject* CSound::fromJSON (
|
|||||||
angles
|
angles
|
||||||
);
|
);
|
||||||
|
|
||||||
auto cur = (*sound_it).begin ();
|
for (const auto& cur : (*sound_it))
|
||||||
auto end = (*sound_it).end ();
|
sound->insertSound (cur);
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
|
||||||
sound->insertSound (*cur);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
@ -43,15 +43,8 @@ CMaterial* CMaterial::fromJSON (const std::string& name, json data)
|
|||||||
|
|
||||||
CMaterial* material = new CMaterial (name);
|
CMaterial* material = new CMaterial (name);
|
||||||
|
|
||||||
auto cur = (*passes_it).begin ();
|
for (const auto& cur : (*passes_it))
|
||||||
auto end = (*passes_it).end ();
|
material->insertPass (Materials::CPass::fromJSON (cur));
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
|
||||||
material->insertPass (
|
|
||||||
Materials::CPass::fromJSON (*cur)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return material;
|
return material;
|
||||||
}
|
}
|
||||||
|
@ -41,39 +41,29 @@ CPass* CPass::fromJSON (json data)
|
|||||||
|
|
||||||
if (textures_it != data.end ())
|
if (textures_it != data.end ())
|
||||||
{
|
{
|
||||||
auto cur = (*textures_it).begin ();
|
for (const auto& cur : (*textures_it))
|
||||||
auto end = (*textures_it).end ();
|
|
||||||
|
|
||||||
for (;cur != end; cur ++)
|
|
||||||
{
|
{
|
||||||
if ((*cur).is_null () == true)
|
if (cur.is_null () == true)
|
||||||
{
|
{
|
||||||
pass->insertTexture ("");
|
pass->insertTexture ("");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pass->insertTexture (*cur);
|
pass->insertTexture (cur);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (combos_it != data.end ())
|
if (combos_it != data.end ())
|
||||||
{
|
{
|
||||||
auto cur = (*combos_it).begin ();
|
for (const auto& cur : (*combos_it).items ())
|
||||||
auto end = (*combos_it).end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
{
|
||||||
std::string name = cur.key ();
|
std::string name = cur.key ();
|
||||||
|
|
||||||
if ((*cur).is_number_integer () == true)
|
if (cur.value ().is_number_integer () == true)
|
||||||
{
|
pass->insertCombo (name, cur.value ());
|
||||||
pass->insertCombo (name, *cur);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
sLog.exception ("unexpected non-integer combo on pass");
|
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)
|
if (options->is_array () == false)
|
||||||
sLog.exception ("Property combo options should be an array");
|
sLog.exception ("Property combo options should be an array");
|
||||||
|
|
||||||
auto cur = (*options).begin ();
|
for (auto& cur : (*options))
|
||||||
auto end = (*options).end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
{
|
||||||
if ((*cur).is_object () == false)
|
// TODO: PROPERLY REPORT THESE ISSUES
|
||||||
{
|
if (cur.is_object () == false)
|
||||||
// TODO: PROPERLY REPORT THESE ISSUES
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
// check for label and value to ensure they're there
|
// check for label and value to ensure they're there
|
||||||
auto label = jsonFindRequired (*cur, "label", "Label 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");
|
auto value = jsonFindRequired (cur, "value", "Value is required for a property combo option");
|
||||||
|
|
||||||
combo->addValue (*label, *value);
|
combo->addValue (*label, *value);
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,9 @@
|
|||||||
#include "CRenderContext.h"
|
#include "CRenderContext.h"
|
||||||
#include "CVideo.h"
|
#include "CVideo.h"
|
||||||
|
|
||||||
|
#define DEFAULT_WINDOW_WIDTH 1280
|
||||||
|
#define DEFAULT_WINDOW_HEIGHT 720
|
||||||
|
|
||||||
using namespace WallpaperEngine::Render;
|
using namespace WallpaperEngine::Render;
|
||||||
|
|
||||||
XErrorHandler originalErrorHandler;
|
XErrorHandler originalErrorHandler;
|
||||||
@ -25,7 +28,7 @@ void CustomXIOErrorExitHandler (Display* dsp, void* userdata)
|
|||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
|
||||||
// refetch all the resources
|
// refetch all the resources
|
||||||
context->initializeViewports ();
|
context->initialize ();
|
||||||
}
|
}
|
||||||
|
|
||||||
int CustomXErrorHandler (Display* dpy, XErrorEvent* event)
|
int CustomXErrorHandler (Display* dpy, XErrorEvent* event)
|
||||||
@ -49,24 +52,32 @@ int CustomXIOErrorHandler (Display* dsp)
|
|||||||
return 0;
|
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_wallpaper (nullptr),
|
||||||
m_screens (std::move (screens)),
|
m_screens (std::move (screens)),
|
||||||
m_isRootWindow (m_screens.empty () == false),
|
m_driver (driver),
|
||||||
m_defaultViewport ({0, 0, 1920, 1080}),
|
|
||||||
m_window (window),
|
|
||||||
m_container (container),
|
m_container (container),
|
||||||
m_textureCache (new CTextureCache (this))
|
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)
|
if (this->m_screens.empty () == true)
|
||||||
return;
|
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_viewports.clear ();
|
||||||
|
|
||||||
this->m_display = XOpenDisplay (nullptr);
|
this->m_display = XOpenDisplay (nullptr);
|
||||||
@ -86,9 +97,6 @@ void CRenderContext::initializeViewports ()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// hide the glfw window if the viewports are to be detected
|
|
||||||
glfwHideWindow (this->m_window);
|
|
||||||
|
|
||||||
Window root = DefaultRootWindow (this->m_display);
|
Window root = DefaultRootWindow (this->m_display);
|
||||||
int fullWidth = DisplayWidth (this->m_display, DefaultScreen (this->m_display));
|
int fullWidth = DisplayWidth (this->m_display, DefaultScreen (this->m_display));
|
||||||
int fullHeight = DisplayHeight (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]);
|
XRROutputInfo* info = XRRGetOutputInfo (this->m_display, screenResources, screenResources->outputs [i]);
|
||||||
|
|
||||||
// there are some situations where xrandr returns null (like screen not using the extension)
|
// 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;
|
continue;
|
||||||
|
|
||||||
auto cur = this->m_screens.begin ();
|
for (const auto& cur : this->m_screens)
|
||||||
auto end = this->m_screens.end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
{
|
||||||
if (info->connection == RR_Connected && strcmp (info->name, (*cur).c_str ()) == 0)
|
if (strcmp (info->name, cur.c_str ()) != 0)
|
||||||
{
|
continue;
|
||||||
XRRCrtcInfo* crtc = XRRGetCrtcInfo (this->m_display, screenResources, info->crtc);
|
|
||||||
|
|
||||||
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 = {
|
sLog.out ("Found requested screen: ", info->name, " -> ", crtc->x, "x", crtc->y, ":", crtc->width, "x", crtc->height);
|
||||||
crtc->x, crtc->y, crtc->width, 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);
|
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 ()
|
void CRenderContext::render ()
|
||||||
{
|
{
|
||||||
if (this->m_wallpaper == nullptr)
|
if (this->m_wallpaper == nullptr)
|
||||||
@ -178,54 +231,11 @@ void CRenderContext::render ()
|
|||||||
this->m_mouse->update ();
|
this->m_mouse->update ();
|
||||||
|
|
||||||
if (this->m_viewports.empty () == false)
|
if (this->m_viewports.empty () == false)
|
||||||
{
|
this->renderScreens ();
|
||||||
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);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
this->m_wallpaper->render (this->m_defaultViewport, true);
|
this->renderWindow ();
|
||||||
|
|
||||||
|
this->m_driver.swapBuffers ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRenderContext::setWallpaper (CWallpaper* wallpaper)
|
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
|
CMouseInput* CRenderContext::getMouse () const
|
||||||
{
|
{
|
||||||
return this->m_mouse;
|
return this->m_mouse;
|
||||||
|
@ -4,11 +4,19 @@
|
|||||||
#include <glm/vec4.hpp>
|
#include <glm/vec4.hpp>
|
||||||
|
|
||||||
#include "WallpaperEngine/Input/CMouseInput.h"
|
#include "WallpaperEngine/Input/CMouseInput.h"
|
||||||
|
#include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
|
||||||
#include "CTextureCache.h"
|
#include "CTextureCache.h"
|
||||||
#include "CWallpaper.h"
|
#include "CWallpaper.h"
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
|
using namespace WallpaperEngine::Assets;
|
||||||
using namespace WallpaperEngine::Input;
|
using namespace WallpaperEngine::Input;
|
||||||
|
using namespace WallpaperEngine::Render::Drivers;
|
||||||
|
|
||||||
|
namespace WallpaperEngine::Render::Drivers
|
||||||
|
{
|
||||||
|
class CVideoDriver;
|
||||||
|
}
|
||||||
|
|
||||||
namespace WallpaperEngine::Render
|
namespace WallpaperEngine::Render
|
||||||
{
|
{
|
||||||
@ -18,13 +26,12 @@ namespace WallpaperEngine::Render
|
|||||||
class CRenderContext
|
class CRenderContext
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CRenderContext (std::vector <std::string> screens, GLFWwindow* window, CContainer* container);
|
CRenderContext (std::vector <std::string> screens, CVideoDriver& driver, CContainer* container);
|
||||||
~CRenderContext ();
|
~CRenderContext ();
|
||||||
|
|
||||||
void initializeViewports ();
|
void initialize ();
|
||||||
void render ();
|
void render ();
|
||||||
void setWallpaper (CWallpaper* wallpaper);
|
void setWallpaper (CWallpaper* wallpaper);
|
||||||
void setDefaultViewport (glm::vec4 defaultViewport);
|
|
||||||
CMouseInput* getMouse () const;
|
CMouseInput* getMouse () const;
|
||||||
void setMouse (CMouseInput* mouse);
|
void setMouse (CMouseInput* mouse);
|
||||||
CWallpaper* getWallpaper () const;
|
CWallpaper* getWallpaper () const;
|
||||||
@ -32,6 +39,12 @@ namespace WallpaperEngine::Render
|
|||||||
const ITexture* resolveTexture (const std::string& name);
|
const ITexture* resolveTexture (const std::string& name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void setupScreens ();
|
||||||
|
void setupWindow ();
|
||||||
|
|
||||||
|
void renderScreens ();
|
||||||
|
void renderWindow ();
|
||||||
|
|
||||||
struct viewport
|
struct viewport
|
||||||
{
|
{
|
||||||
glm::ivec4 viewport;
|
glm::ivec4 viewport;
|
||||||
@ -42,15 +55,13 @@ namespace WallpaperEngine::Render
|
|||||||
Pixmap m_pixmap;
|
Pixmap m_pixmap;
|
||||||
GC m_gc;
|
GC m_gc;
|
||||||
XImage* m_image;
|
XImage* m_image;
|
||||||
GLFWwindow* m_window;
|
CVideoDriver& m_driver;
|
||||||
char* m_imageData;
|
char* m_imageData;
|
||||||
CFBO* m_fbo;
|
CFBO* m_fbo;
|
||||||
std::vector <std::string> m_screens;
|
std::vector <std::string> m_screens;
|
||||||
std::vector <viewport> m_viewports;
|
std::vector <viewport> m_viewports;
|
||||||
glm::vec4 m_defaultViewport;
|
|
||||||
CWallpaper* m_wallpaper;
|
CWallpaper* m_wallpaper;
|
||||||
CMouseInput* m_mouse;
|
CMouseInput* m_mouse;
|
||||||
bool m_isRootWindow;
|
|
||||||
CContainer* m_container;
|
CContainer* m_container;
|
||||||
CTextureCache* m_textureCache;
|
CTextureCache* m_textureCache;
|
||||||
};
|
};
|
||||||
|
@ -24,15 +24,12 @@ CScene::CScene (Core::CScene* scene, CRenderContext* context) :
|
|||||||
if (scene->getOrthogonalProjection ()->isAuto () == true)
|
if (scene->getOrthogonalProjection ()->isAuto () == true)
|
||||||
{
|
{
|
||||||
// calculate the size of the projection based on the size of everything
|
// calculate the size of the projection based on the size of everything
|
||||||
auto cur = scene->getObjects ().begin ();
|
for (const auto& cur : scene->getObjects ())
|
||||||
auto end = scene->getObjects ().end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
{
|
||||||
if ((*cur).second->is<Core::Objects::CImage> () == false)
|
if (cur.second->is<Core::Objects::CImage> () == false)
|
||||||
continue;
|
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 ()->setWidth (size.x);
|
||||||
scene->getOrthogonalProjection ()->setHeight (size.y);
|
scene->getOrthogonalProjection ()->setHeight (size.y);
|
||||||
@ -55,21 +52,13 @@ CScene::CScene (Core::CScene* scene, CRenderContext* context) :
|
|||||||
this->setupFramebuffers ();
|
this->setupFramebuffers ();
|
||||||
|
|
||||||
// create all objects based off their dependencies
|
// 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 obj = this->m_objects.find (cur->getId ());
|
||||||
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 ());
|
|
||||||
|
|
||||||
// ignores not created objects like particle systems
|
// ignores not created objects like particle systems
|
||||||
if (obj == this->m_objects.end ())
|
if (obj == this->m_objects.end ())
|
||||||
@ -183,16 +172,13 @@ Render::CObject* CScene::createObject (Core::CObject* object)
|
|||||||
return (*current).second;
|
return (*current).second;
|
||||||
|
|
||||||
// check dependencies too!
|
// check dependencies too!
|
||||||
auto depCur = object->getDependencies ().begin ();
|
for (const auto& cur : object->getDependencies ())
|
||||||
auto depEnd = object->getDependencies ().end ();
|
|
||||||
|
|
||||||
for (; depCur != depEnd; depCur ++)
|
|
||||||
{
|
{
|
||||||
// self-dependency is a possibility...
|
// self-dependency is a possibility...
|
||||||
if ((*depCur) == object->getId ())
|
if (cur == object->getId ())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto dep = this->getScene ()->getObjects ().find (*depCur);
|
auto dep = this->getScene ()->getObjects ().find (cur);
|
||||||
|
|
||||||
if (dep != this->getScene ()->getObjects ().end ())
|
if (dep != this->getScene ()->getObjects ().end ())
|
||||||
this->createObject ((*dep).second);
|
this->createObject ((*dep).second);
|
||||||
@ -232,10 +218,6 @@ CCamera* CScene::getCamera () const
|
|||||||
|
|
||||||
void CScene::renderFrame (glm::ivec4 viewport)
|
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
|
// ensure the virtual mouse position is up to date
|
||||||
this->updateMouse (viewport);
|
this->updateMouse (viewport);
|
||||||
|
|
||||||
@ -256,8 +238,8 @@ void CScene::renderFrame (glm::ivec4 viewport)
|
|||||||
|
|
||||||
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
for (const auto& cur : this->m_objectsByRenderOrder)
|
||||||
(*cur)->render ();
|
cur->render ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CScene::updateMouse (glm::ivec4 viewport)
|
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
|
const CFBO* CEffect::findFBO (const std::string& name) const
|
||||||
{
|
{
|
||||||
auto cur = this->m_fbos.begin ();
|
for (const auto& cur : this->m_fbos)
|
||||||
auto end = this->m_fbos.end ();
|
if (cur->getName () == name)
|
||||||
|
return cur;
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
|
||||||
if ((*cur)->getName () == name)
|
|
||||||
{
|
|
||||||
return *cur;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEffect::generatePasses ()
|
void CEffect::generatePasses ()
|
||||||
{
|
{
|
||||||
auto cur = this->m_effect->getMaterials ().begin ();
|
for (const auto& cur : this->m_effect->getMaterials ())
|
||||||
auto end = this->m_effect->getMaterials ().end ();
|
this->m_materials.emplace_back (new Effects::CMaterial (this, cur));
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
this->m_materials.emplace_back (new Effects::CMaterial (this, *cur));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEffect::generateFBOs ()
|
void CEffect::generateFBOs ()
|
||||||
{
|
{
|
||||||
auto cur = this->m_effect->getFbos ().begin ();
|
for (const auto& cur : this->m_effect->getFbos ())
|
||||||
auto end = this->m_effect->getFbos ().end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
{
|
||||||
this->m_fbos.push_back (
|
this->m_fbos.push_back (
|
||||||
new CFBO (
|
new CFBO (
|
||||||
(*cur)->getName (),
|
cur->getName (),
|
||||||
ITexture::TextureFormat::ARGB8888, // TODO: CHANGE
|
ITexture::TextureFormat::ARGB8888, // TODO: CHANGE
|
||||||
this->m_image->getTexture ()->getFlags (), // TODO: CHANGE
|
this->m_image->getTexture ()->getFlags (), // TODO: CHANGE
|
||||||
(*cur)->getScale (),
|
cur->getScale (),
|
||||||
this->m_image->getSize ().x / (*cur)->getScale (),
|
this->m_image->getSize ().x / cur->getScale (),
|
||||||
this->m_image->getSize ().y / (*cur)->getScale (),
|
this->m_image->getSize ().y / cur->getScale (),
|
||||||
this->m_image->getSize ().x / (*cur)->getScale (),
|
this->m_image->getSize ().x / cur->getScale (),
|
||||||
this->m_image->getSize ().y / (*cur)->getScale ()
|
this->m_image->getSize ().y / cur->getScale ()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -242,34 +242,21 @@ void CImage::setup ()
|
|||||||
);
|
);
|
||||||
|
|
||||||
// add blendmode to the combos
|
// add blendmode to the combos
|
||||||
auto cur = this->m_material->getPasses ().begin ();
|
for (const auto& cur : this->m_material->getPasses ())
|
||||||
auto end = this->m_material->getPasses ().end ();
|
this->m_passes.push_back (cur);
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
this->m_passes.push_back (*cur);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare the passes list
|
// prepare the passes list
|
||||||
if (this->getImage ()->getEffects ().empty () == false)
|
if (this->getImage ()->getEffects ().empty () == false)
|
||||||
{
|
{
|
||||||
// generate the effects used by this material
|
// generate the effects used by this material
|
||||||
auto cur = this->getImage ()->getEffects ().begin ();
|
for (const auto& cur : this->getImage ()->getEffects ())
|
||||||
auto end = this->getImage ()->getEffects ().end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
{
|
||||||
auto effect = new CEffect (this, *cur);
|
auto effect = new CEffect (this, cur);
|
||||||
auto materialCur = effect->getMaterials ().begin ();
|
|
||||||
auto materialEnd = effect->getMaterials ().end ();
|
|
||||||
|
|
||||||
for (; materialCur != materialEnd; materialCur ++)
|
for (const auto& material : effect->getMaterials ())
|
||||||
{
|
for (const auto& pass : material->getPasses ())
|
||||||
auto passCur = (*materialCur)->getPasses ().begin ();
|
this->m_passes.push_back (pass);
|
||||||
auto passEnd = (*materialCur)->getPasses ().end ();
|
|
||||||
|
|
||||||
for (; passCur != passEnd; passCur ++)
|
|
||||||
this->m_passes.push_back (*passCur);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->m_effects.push_back (effect);
|
this->m_effects.push_back (effect);
|
||||||
}
|
}
|
||||||
@ -289,11 +276,8 @@ void CImage::setup ()
|
|||||||
);
|
);
|
||||||
|
|
||||||
// add blendmode to the combos
|
// add blendmode to the combos
|
||||||
auto cur = this->m_colorBlendMaterial->getPasses ().begin ();
|
for (const auto& cur : this->m_colorBlendMaterial->getPasses ())
|
||||||
auto end = this->m_colorBlendMaterial->getPasses ().end ();
|
this->m_passes.push_back (cur);
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
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
|
// 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");
|
(*first)->getPass ()->setBlendingMode ("normal");
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
// calculate full animation time (if any)
|
||||||
// calculate full animation time (if any)
|
this->m_animationTime = 0.0f;
|
||||||
this->m_animationTime = 0.0f;
|
|
||||||
|
|
||||||
auto cur = this->getTexture ()->getFrames ().begin ();
|
for (const auto& cur : this->getTexture ()->getFrames ())
|
||||||
auto end = this->getTexture ()->getFrames ().end ();
|
this->m_animationTime += cur->frametime;
|
||||||
|
|
||||||
for (; cur != end; cur++)
|
|
||||||
this->m_animationTime += (*cur)->frametime;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->setupPasses ();
|
this->setupPasses ();
|
||||||
this->m_initialized = true;
|
this->m_initialized = true;
|
||||||
|
@ -13,13 +13,10 @@ CSound::CSound (CScene* scene, Core::Objects::CSound* sound) :
|
|||||||
|
|
||||||
void CSound::load ()
|
void CSound::load ()
|
||||||
{
|
{
|
||||||
auto cur = this->m_sound->getSounds ().begin ();
|
for (const auto& cur : this->m_sound->getSounds ())
|
||||||
auto end = this->m_sound->getSounds ().end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
{
|
||||||
uint32_t filesize = 0;
|
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_audioStreams.push_back (new Audio::CAudioStream (filebuffer, filesize));
|
||||||
this->m_soundBuffer.push_back (filebuffer);
|
this->m_soundBuffer.push_back (filebuffer);
|
||||||
|
@ -23,12 +23,9 @@ CImage* CMaterial::getImage () const
|
|||||||
|
|
||||||
void CMaterial::generatePasses ()
|
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
|
// these are simple now, just create the entries and done
|
||||||
for (; cur != end; cur ++)
|
for (const auto& cur : this->m_material->getPasses ())
|
||||||
this->m_passes.emplace_back (new CPass (this, *cur));
|
this->m_passes.emplace_back (new CPass (this, cur));
|
||||||
}
|
}
|
||||||
|
|
||||||
const Core::Objects::Images::CMaterial* CMaterial::getMaterial () const
|
const Core::Objects::Images::CMaterial* CMaterial::getMaterial () const
|
||||||
|
@ -136,26 +136,22 @@ void CPass::render ()
|
|||||||
// calculate current texture and frame
|
// calculate current texture and frame
|
||||||
double currentRenderTime = fmod (static_cast <double> (g_Time), this->m_material->getImage ()->getAnimationTime ());
|
double currentRenderTime = fmod (static_cast <double> (g_Time), this->m_material->getImage ()->getAnimationTime ());
|
||||||
|
|
||||||
// find the right frame now
|
for (const auto& frameCur : texture->getFrames ())
|
||||||
auto frameCur = texture->getFrames ().begin ();
|
|
||||||
auto frameEnd = texture->getFrames ().end ();
|
|
||||||
|
|
||||||
for (; frameCur != frameEnd; frameCur ++)
|
|
||||||
{
|
{
|
||||||
currentRenderTime -= (*frameCur)->frametime;
|
currentRenderTime -= frameCur->frametime;
|
||||||
|
|
||||||
if (currentRenderTime <= 0.0f)
|
if (currentRenderTime <= 0.0f)
|
||||||
{
|
{
|
||||||
// frame found, store coordinates and done
|
// frame found, store coordinates and done
|
||||||
currentTexture = (*frameCur)->frameNumber;
|
currentTexture = frameCur->frameNumber;
|
||||||
|
|
||||||
translation.x = (*frameCur)->x / texture->getTextureWidth (currentTexture);
|
translation.x = frameCur->x / texture->getTextureWidth (currentTexture);
|
||||||
translation.y = (*frameCur)->y / texture->getTextureHeight (currentTexture);
|
translation.y = frameCur->y / texture->getTextureHeight (currentTexture);
|
||||||
|
|
||||||
rotation.x = (*frameCur)->width1 / static_cast<float> (texture->getTextureWidth (currentTexture));
|
rotation.x = frameCur->width1 / static_cast<float> (texture->getTextureWidth (currentTexture));
|
||||||
rotation.y = (*frameCur)->width2 / 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.z = frameCur->height2 / static_cast<float> (texture->getTextureHeight (currentTexture));
|
||||||
rotation.w = (*frameCur)->height1 / static_cast<float> (texture->getTextureHeight (currentTexture));
|
rotation.w = frameCur->height1 / static_cast<float> (texture->getTextureHeight (currentTexture));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,118 +164,97 @@ void CPass::render ()
|
|||||||
// continue on the map from the second texture
|
// continue on the map from the second texture
|
||||||
if (this->m_finalTextures.empty () == false)
|
if (this->m_finalTextures.empty () == false)
|
||||||
{
|
{
|
||||||
auto cur = this->m_finalTextures.begin ();
|
for (const auto& cur : this->m_finalTextures)
|
||||||
auto end = this->m_finalTextures.end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
{
|
||||||
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));
|
glBindTexture (GL_TEXTURE_2D, texture->getTextureID (0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add uniforms
|
// add uniforms
|
||||||
|
for (const auto& cur : this->m_uniforms)
|
||||||
{
|
{
|
||||||
auto cur = this->m_uniforms.begin ();
|
UniformEntry* entry = cur.second;
|
||||||
auto end = this->m_uniforms.end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
switch (entry->type)
|
||||||
{
|
{
|
||||||
UniformEntry* entry = (*cur).second;
|
case Double:
|
||||||
|
glUniform1d (entry->id, *reinterpret_cast <const double*> (entry->value));
|
||||||
switch (entry->type)
|
break;
|
||||||
{
|
case Float:
|
||||||
case Double:
|
glUniform1f (entry->id, *reinterpret_cast <const float*> (entry->value));
|
||||||
glUniform1d (entry->id, *reinterpret_cast <const double*> (entry->value));
|
break;
|
||||||
break;
|
case Integer:
|
||||||
case Float:
|
glUniform1i (entry->id, *reinterpret_cast <const int*> (entry->value));
|
||||||
glUniform1f (entry->id, *reinterpret_cast <const float*> (entry->value));
|
break;
|
||||||
break;
|
case Vector4:
|
||||||
case Integer:
|
glUniform4fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec4*> (entry->value)));
|
||||||
glUniform1i (entry->id, *reinterpret_cast <const int*> (entry->value));
|
break;
|
||||||
break;
|
case Vector3:
|
||||||
case Vector4:
|
glUniform3fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec3*> (entry->value)));
|
||||||
glUniform4fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec4*> (entry->value)));
|
break;
|
||||||
break;
|
case Vector2:
|
||||||
case Vector3:
|
glUniform2fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec2*> (entry->value)));
|
||||||
glUniform3fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec3*> (entry->value)));
|
break;
|
||||||
break;
|
case Matrix4:
|
||||||
case Vector2:
|
glUniformMatrix4fv (entry->id, 1, GL_FALSE, glm::value_ptr (*reinterpret_cast <const glm::mat4*> (entry->value)));
|
||||||
glUniform2fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec2*> (entry->value)));
|
break;
|
||||||
break;
|
|
||||||
case Matrix4:
|
|
||||||
glUniformMatrix4fv (entry->id, 1, GL_FALSE, glm::value_ptr (*reinterpret_cast <const glm::mat4*> (entry->value)));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// add reference uniforms
|
// add reference uniforms
|
||||||
|
for (const auto& cur : this->m_referenceUniforms)
|
||||||
{
|
{
|
||||||
auto cur = this->m_referenceUniforms.begin ();
|
ReferenceUniformEntry* entry = cur.second;
|
||||||
auto end = this->m_referenceUniforms.end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
switch (entry->type)
|
||||||
{
|
{
|
||||||
ReferenceUniformEntry* entry = (*cur).second;
|
case Double:
|
||||||
|
glUniform1d (entry->id, *reinterpret_cast <const double*> (*entry->value));
|
||||||
switch (entry->type)
|
break;
|
||||||
{
|
case Float:
|
||||||
case Double:
|
glUniform1f (entry->id, *reinterpret_cast <const float*> (*entry->value));
|
||||||
glUniform1d (entry->id, *reinterpret_cast <const double*> (*entry->value));
|
break;
|
||||||
break;
|
case Integer:
|
||||||
case Float:
|
glUniform1i (entry->id, *reinterpret_cast <const int*> (*entry->value));
|
||||||
glUniform1f (entry->id, *reinterpret_cast <const float*> (*entry->value));
|
break;
|
||||||
break;
|
case Vector4:
|
||||||
case Integer:
|
glUniform4fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec4*> (*entry->value)));
|
||||||
glUniform1i (entry->id, *reinterpret_cast <const int*> (*entry->value));
|
break;
|
||||||
break;
|
case Vector3:
|
||||||
case Vector4:
|
glUniform3fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec3*> (*entry->value)));
|
||||||
glUniform4fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec4*> (*entry->value)));
|
break;
|
||||||
break;
|
case Vector2:
|
||||||
case Vector3:
|
glUniform2fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec2*> (*entry->value)));
|
||||||
glUniform3fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec3*> (*entry->value)));
|
break;
|
||||||
break;
|
case Matrix4:
|
||||||
case Vector2:
|
glUniformMatrix4fv (entry->id, 1, GL_FALSE, glm::value_ptr (*reinterpret_cast <const glm::mat4*> (*entry->value)));
|
||||||
glUniform2fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec2*> (*entry->value)));
|
break;
|
||||||
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)
|
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);
|
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)
|
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);
|
glUniform2f (this->g_Texture0Translation, translation.x, translation.y);
|
||||||
}
|
|
||||||
|
for (const auto& cur : this->m_attribs)
|
||||||
{
|
{
|
||||||
auto cur = this->m_attribs.begin ();
|
glEnableVertexAttribArray (cur->id);
|
||||||
auto end = this->m_attribs.end ();
|
glBindBuffer (GL_ARRAY_BUFFER, *cur->value);
|
||||||
|
glVertexAttribPointer (cur->id, cur->elements, cur->type, GL_FALSE, 0, nullptr);
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
if (DEBUG)
|
||||||
{
|
glObjectLabel (GL_BUFFER, *cur->value, -1, (
|
||||||
glEnableVertexAttribArray ((*cur)->id);
|
"Image " + std::to_string (this->getMaterial ()->getImage ()->getId ()) +
|
||||||
glBindBuffer (GL_ARRAY_BUFFER, *(*cur)->value);
|
" Pass " + this->m_pass->getShader() +
|
||||||
glVertexAttribPointer ((*cur)->id, (*cur)->elements, (*cur)->type, GL_FALSE, 0, nullptr);
|
" " + 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
|
// start actual rendering now
|
||||||
@ -287,13 +262,8 @@ void CPass::render ()
|
|||||||
glDrawArrays (GL_TRIANGLES, 0, 6);
|
glDrawArrays (GL_TRIANGLES, 0, 6);
|
||||||
|
|
||||||
// disable vertex attribs array and textures
|
// disable vertex attribs array and textures
|
||||||
{
|
for (const auto& cur : this->m_attribs)
|
||||||
auto cur = this->m_attribs.begin ();
|
glDisableVertexAttribArray (cur->id);
|
||||||
auto end = this->m_attribs.end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
glDisableVertexAttribArray ((*cur)->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// unbind all the used textures
|
// unbind all the used textures
|
||||||
glActiveTexture (GL_TEXTURE0);
|
glActiveTexture (GL_TEXTURE0);
|
||||||
@ -302,12 +272,9 @@ void CPass::render ()
|
|||||||
// continue on the map from the second texture
|
// continue on the map from the second texture
|
||||||
if (this->m_finalTextures.empty () == false)
|
if (this->m_finalTextures.empty () == false)
|
||||||
{
|
{
|
||||||
auto cur = this->m_finalTextures.begin ();
|
for (const auto& cur : this->m_finalTextures)
|
||||||
auto end = this->m_finalTextures.end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
{
|
||||||
glActiveTexture (GL_TEXTURE0 + (*cur).first);
|
glActiveTexture (GL_TEXTURE0 + cur.first);
|
||||||
glBindTexture (GL_TEXTURE_2D, 0);
|
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 ();
|
std::ostringstream namestream;
|
||||||
auto end = this->m_finalTextures.end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
namestream << "g_Texture" << cur.first << "Resolution";
|
||||||
{
|
|
||||||
std::ostringstream namestream;
|
|
||||||
|
|
||||||
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 ();
|
auto projection = this->getMaterial ()->getImage ()->getScene ()->getScene ()->getOrthogonalProjection ();
|
||||||
@ -744,128 +706,113 @@ void CPass::setupTextures ()
|
|||||||
|
|
||||||
void CPass::setupShaderVariables ()
|
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
|
CShaderVariable* vertexVar = this->m_vertShader->findParameter (cur.first);
|
||||||
auto cur = this->m_pass->getConstants ().begin ();
|
CShaderVariable* pixelVar = this->m_fragShader->findParameter (cur.first);
|
||||||
auto end = this->m_pass->getConstants ().end ();
|
|
||||||
|
|
||||||
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);
|
if (vertexVar->getType () != pixelVar->getType ())
|
||||||
CShaderVariable* pixelVar = this->m_fragShader->findParameter ((*cur).first);
|
throw std::runtime_error ("Pixel and vertex shader variable types do not match");
|
||||||
|
}*/
|
||||||
|
|
||||||
// variable not found, can be ignored
|
// get one instance of it
|
||||||
if (vertexVar == nullptr && pixelVar == nullptr)
|
CShaderVariable* var = vertexVar == nullptr ? pixelVar : vertexVar;
|
||||||
continue;
|
|
||||||
|
|
||||||
// if both can be found, ensure they're the correct type
|
// ensure the shader's and the constant are of the same type
|
||||||
/*if (vertexVar != nullptr && pixelVar != nullptr)
|
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 ())
|
// create an integer value from a float
|
||||||
throw std::runtime_error ("Pixel and vertex shader variable types do not match");
|
this->addUniform (var->getName (), static_cast <int> (*cur.second->as <CShaderConstantFloat> ()->getValue ()));
|
||||||
}*/
|
}
|
||||||
|
else if (cur.second->is <CShaderConstantInteger> () == true && var->is <CShaderVariableFloat> () == true)
|
||||||
// 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 ())
|
|
||||||
{
|
{
|
||||||
// there's situations where this type mismatch is actually expected
|
// create a float value from an integer
|
||||||
// integers and floats are equivalent, this could be detected at load time
|
this->addUniform (var->getName (), static_cast <float> (*cur.second->as <CShaderConstantInteger> ()->getValue ()));
|
||||||
// but that'd mean to compile the shader in the load, and not on the render stage
|
}
|
||||||
// so take into account these conversions here
|
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 a new vector2 with the first two values
|
||||||
{
|
this->addUniform (var->getName (), {val->getValue ()->x, val->getValue ()->y});
|
||||||
// create an integer value from a float
|
}
|
||||||
this->addUniform (var->getName (), static_cast <int> (*(*cur).second->as <CShaderConstantFloat> ()->getValue ()));
|
else if (cur.second->is <CShaderConstantVector4> () == true && var->is <CShaderVariableVector3> () == true)
|
||||||
}
|
{
|
||||||
else if ((*cur).second->is <CShaderConstantInteger> () == true && var->is <CShaderVariableFloat> () == true)
|
CShaderConstantVector4* val = cur.second->as <CShaderConstantVector4> ();
|
||||||
{
|
|
||||||
// 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, val->getValue ()->z});
|
||||||
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 ()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// now determine the constant's type and register the correct uniform for it
|
sLog.exception (
|
||||||
if ((*cur).second->is <CShaderConstantFloat> ())
|
"Constant ",
|
||||||
this->addUniform (var->getName (), (*cur).second->as <CShaderConstantFloat> ()->getValue ());
|
cur.first,
|
||||||
else if ((*cur).second->is <CShaderConstantInteger> ())
|
" type does not match pixel/vertex shader variable and cannot be converted (",
|
||||||
this->addUniform (var->getName (), (*cur).second->as <CShaderConstantInteger> ()->getValue ());
|
cur.second->getType (),
|
||||||
else if ((*cur).second->is <CShaderConstantVector4> ())
|
" to ",
|
||||||
this->addUniform (var->getName (), (*cur).second->as <CShaderConstantVector4> ()->getValue ());
|
var->getType ()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
|
||||||
{
|
|
||||||
auto cur = this->m_vertShader->getParameters ().begin ();
|
|
||||||
auto end = this->m_vertShader->getParameters ().end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
{
|
||||||
if (this->m_uniforms.find ((*cur)->getName ()) != this->m_uniforms.end ())
|
// now determine the constant's type and register the correct uniform for it
|
||||||
continue;
|
if (cur.second->is <CShaderConstantFloat> ())
|
||||||
|
this->addUniform (var->getName (), cur.second->as <CShaderConstantFloat> ()->getValue ());
|
||||||
if ((*cur)->is <CShaderVariableFloat> ())
|
else if (cur.second->is <CShaderConstantInteger> ())
|
||||||
this->addUniform ((*cur)->getName (), const_cast <float*> (reinterpret_cast <const float*> ((*cur)->as <CShaderVariableFloat> ()->getValue ())));
|
this->addUniform (var->getName (), cur.second->as <CShaderConstantInteger> ()->getValue ());
|
||||||
else if ((*cur)->is <CShaderVariableInteger> ())
|
else if (cur.second->is <CShaderConstantVector4> ())
|
||||||
this->addUniform ((*cur)->getName (), const_cast <int*> (reinterpret_cast <const int*> ((*cur)->as <CShaderVariableInteger> ()->getValue ())));
|
this->addUniform (var->getName (), cur.second->as <CShaderConstantVector4> ()->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_vertShader->getParameters ())
|
||||||
{
|
{
|
||||||
auto cur = this->m_fragShader->getParameters ().begin ();
|
if (this->m_uniforms.find (cur->getName ()) != this->m_uniforms.end ())
|
||||||
auto end = this->m_fragShader->getParameters ().end ();
|
continue;
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
if (cur->is <CShaderVariableFloat> ())
|
||||||
{
|
this->addUniform (cur->getName (), const_cast <float*> (reinterpret_cast <const float*> (cur->as <CShaderVariableFloat> ()->getValue ())));
|
||||||
if (this->m_uniforms.find ((*cur)->getName ()) != this->m_uniforms.end ())
|
else if (cur->is <CShaderVariableInteger> ())
|
||||||
continue;
|
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> ())
|
for (const auto& cur : this->m_fragShader->getParameters ())
|
||||||
this->addUniform ((*cur)->getName (), const_cast <float*> (reinterpret_cast <const float*> ((*cur)->as <CShaderVariableFloat> ()->getValue ())));
|
{
|
||||||
else if ((*cur)->is <CShaderVariableInteger> ())
|
if (this->m_uniforms.find (cur->getName ()) != this->m_uniforms.end ())
|
||||||
this->addUniform ((*cur)->getName (), const_cast <int*> (reinterpret_cast <const int*> ((*cur)->as <CShaderVariableInteger> ()->getValue ())));
|
continue;
|
||||||
else if ((*cur)->is <CShaderVariableVector2> ())
|
|
||||||
this->addUniform ((*cur)->getName (), const_cast <glm::vec2*> (reinterpret_cast <const glm::vec2*> ((*cur)->as <CShaderVariableVector2> ()->getValue ())));
|
if (cur->is <CShaderVariableFloat> ())
|
||||||
else if ((*cur)->is <CShaderVariableVector3> ())
|
this->addUniform (cur->getName (), const_cast <float*> (reinterpret_cast <const float*> (cur->as <CShaderVariableFloat> ()->getValue ())));
|
||||||
this->addUniform ((*cur)->getName (), const_cast <glm::vec3*> (reinterpret_cast <const glm::vec3*> ((*cur)->as <CShaderVariableVector3> ()->getValue ())));
|
else if (cur->is <CShaderVariableInteger> ())
|
||||||
else if ((*cur)->is <CShaderVariableVector4> ())
|
this->addUniform (cur->getName (), const_cast <int*> (reinterpret_cast <const int*> (cur->as <CShaderVariableInteger> ()->getValue ())));
|
||||||
this->addUniform ((*cur)->getName (), const_cast <glm::vec4*> (reinterpret_cast <const glm::vec4*> ((*cur)->as <CShaderVariableVector4> ()->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);
|
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
|
// clone the combos into the baseCombos to keep track of values that must be embedded no matter what
|
||||||
auto cur = this->m_combos->begin ();
|
for (const auto& cur : *this->m_combos)
|
||||||
auto end = this->m_combos->end ();
|
this->m_baseCombos.insert (std::make_pair (cur.first, cur.second));
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
|
||||||
this->m_baseCombos.insert (std::make_pair ((*cur).first, (*cur).second));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Compiler::peekString(std::string str, std::string::const_iterator& it)
|
bool Compiler::peekString(std::string str, std::string::const_iterator& it)
|
||||||
@ -526,36 +523,26 @@ namespace WallpaperEngine::Render::Shaders
|
|||||||
"// Shader combo parameter definitions\n"
|
"// Shader combo parameter definitions\n"
|
||||||
"// ======================================================\n";
|
"// ======================================================\n";
|
||||||
|
|
||||||
|
// add combo values
|
||||||
|
for (const auto& cur : *this->m_foundCombos)
|
||||||
{
|
{
|
||||||
// add combo values
|
// find the right value for the combo in the combos map
|
||||||
auto cur = this->m_foundCombos->begin ();
|
auto combo = this->m_combos->find (cur.first);
|
||||||
auto end = this->m_foundCombos->end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur++)
|
if (combo == this->m_combos->end ())
|
||||||
{
|
continue;
|
||||||
// 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 ())
|
finalCode += "#define " + cur.first + " " + std::to_string ((*combo).second) + "\n";
|
||||||
continue;
|
|
||||||
|
|
||||||
finalCode += "#define " + (*cur).first + " " + std::to_string ((*combo).second) + "\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// add base combos that come from the pass change that MUST be added
|
// 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 alreadyFound = this->m_foundCombos->find (cur.first);
|
||||||
auto end = this->m_baseCombos.end ();
|
|
||||||
|
|
||||||
for (; cur != end; cur ++)
|
if (alreadyFound != this->m_foundCombos->end ())
|
||||||
{
|
continue;
|
||||||
auto alreadyFound = this->m_foundCombos->find ((*cur).first);
|
|
||||||
|
|
||||||
if (alreadyFound != this->m_foundCombos->end ())
|
finalCode += "#define " + cur.first + " " + std::to_string (cur.second) + "\n";
|
||||||
continue;
|
|
||||||
|
|
||||||
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)
|
Variables::CShaderVariable* Compiler::findParameter (const std::string& identifier)
|
||||||
{
|
{
|
||||||
auto cur = this->m_parameters.begin ();
|
for (const auto& cur : this->m_parameters)
|
||||||
auto end = this->m_parameters.end ();
|
if (cur->getIdentifierName () == identifier)
|
||||||
|
return cur;
|
||||||
for (; cur != end; cur ++)
|
|
||||||
{
|
|
||||||
if ((*cur)->getIdentifierName () == identifier)
|
|
||||||
{
|
|
||||||
return (*cur);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user