mirror of
https://github.com/Almamu/linux-wallpaperengine.git
synced 2025-09-14 13:56:48 +08:00
More code cleanup:
- Separated program args parsing and validation from initialization code - Application's main body in it's own class Signed-off-by: Alexis Maiquez <almamu@almamu.com>
This commit is contained in:
parent
476d45be0a
commit
55760aee4d
@ -43,6 +43,11 @@ add_executable(
|
|||||||
src/WallpaperEngine/Logging/CLog.cpp
|
src/WallpaperEngine/Logging/CLog.cpp
|
||||||
src/WallpaperEngine/Logging/CLog.h
|
src/WallpaperEngine/Logging/CLog.h
|
||||||
|
|
||||||
|
src/WallpaperEngine/Application/CApplicationContext.cpp
|
||||||
|
src/WallpaperEngine/Application/CApplicationContext.h
|
||||||
|
src/WallpaperEngine/Application/CWallpaperApplication.cpp
|
||||||
|
src/WallpaperEngine/Application/CWallpaperApplication.h
|
||||||
|
|
||||||
src/WallpaperEngine/Assets/CPackageLoadException.cpp
|
src/WallpaperEngine/Assets/CPackageLoadException.cpp
|
||||||
src/WallpaperEngine/Assets/CPackageLoadException.h
|
src/WallpaperEngine/Assets/CPackageLoadException.h
|
||||||
src/WallpaperEngine/Assets/CAssetLoadException.cpp
|
src/WallpaperEngine/Assets/CAssetLoadException.cpp
|
||||||
|
459
main.cpp
459
main.cpp
@ -23,227 +23,21 @@
|
|||||||
#include "WallpaperEngine/Assets/CPackageLoadException.h"
|
#include "WallpaperEngine/Assets/CPackageLoadException.h"
|
||||||
|
|
||||||
#include "Steam/FileSystem/FileSystem.h"
|
#include "Steam/FileSystem/FileSystem.h"
|
||||||
|
#include "WallpaperEngine/Application/CApplicationContext.h"
|
||||||
|
#include "WallpaperEngine/Application/CWallpaperApplication.h"
|
||||||
#include "WallpaperEngine/Audio/CAudioContext.h"
|
#include "WallpaperEngine/Audio/CAudioContext.h"
|
||||||
#include "WallpaperEngine/Audio/Drivers/CSDLAudioDriver.h"
|
#include "WallpaperEngine/Audio/Drivers/CSDLAudioDriver.h"
|
||||||
#include "WallpaperEngine/Render/Drivers/COpenGLDriver.h"
|
#include "WallpaperEngine/Render/Drivers/COpenGLDriver.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#define WORKSHOP_APP_ID 431960
|
WallpaperEngine::Application::CWallpaperApplication* appPointer;
|
||||||
#define APP_DIRECTORY "wallpaper_engine"
|
|
||||||
|
|
||||||
float g_Time;
|
|
||||||
float g_TimeLast;
|
|
||||||
bool g_KeepRunning = true;
|
|
||||||
bool g_AudioEnabled = true;
|
|
||||||
int g_AudioVolume = 128;
|
|
||||||
|
|
||||||
void print_help (const char* route)
|
|
||||||
{
|
|
||||||
sLog.out ("Usage: ", route, " [options] background_path/background_id");
|
|
||||||
sLog.out ("");
|
|
||||||
sLog.out ("where background_path/background_id can be:");
|
|
||||||
sLog.out ("\tthe ID of the background (for autodetection on your steam installation)");
|
|
||||||
sLog.out ("\ta full path to the background's folder");
|
|
||||||
sLog.out ("");
|
|
||||||
sLog.out ("options:");
|
|
||||||
sLog.out ("\t--silent\t\t\t\t\tMutes all the sound the wallpaper might produce");
|
|
||||||
sLog.out ("\t--volume <amount>\t\t\tSets the volume for all the sounds in the background");
|
|
||||||
sLog.out ("\t--screen-root <screen name>\tDisplay as screen's background");
|
|
||||||
sLog.out ("\t--fps <maximum-fps>\t\t\tLimits the FPS to the given number, useful to keep battery consumption low");
|
|
||||||
sLog.out ("\t--assets-dir <path>\t\t\tFolder where the assets are stored");
|
|
||||||
sLog.out ("\t--screenshot\t\t\t\tTakes a screenshot of the background");
|
|
||||||
sLog.out ("\t--list-properties\t\t\tList all the available properties and their possible values");
|
|
||||||
sLog.out ("\t--set-property <name=value>\tOverrides the default value of the given property");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string stringPathFixes(const std::string& s)
|
|
||||||
{
|
|
||||||
if (s.empty () == true)
|
|
||||||
return s;
|
|
||||||
|
|
||||||
std::string str (s);
|
|
||||||
|
|
||||||
// remove single-quotes from the arguments
|
|
||||||
if (str [0] == '\'' && str [str.size() - 1] == '\'')
|
|
||||||
str
|
|
||||||
.erase (str.size() - 1, 1)
|
|
||||||
.erase (0, 1);
|
|
||||||
|
|
||||||
return std::move (str);
|
|
||||||
}
|
|
||||||
|
|
||||||
void signalhandler(int sig)
|
void signalhandler(int sig)
|
||||||
{
|
{
|
||||||
g_KeepRunning = false;
|
if (appPointer == nullptr)
|
||||||
}
|
return;
|
||||||
|
|
||||||
void addPkg (CCombinedContainer* containers, const std::filesystem::path& path, std::string pkgfile)
|
appPointer->signal (sig);
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
auto scene_path = std::filesystem::path (path) / pkgfile;
|
|
||||||
|
|
||||||
// add the package to the list
|
|
||||||
containers->add (new WallpaperEngine::Assets::CPackage (scene_path));
|
|
||||||
sLog.out ("Detected ", pkgfile, " file at ", scene_path, ". Adding to list of searchable paths");
|
|
||||||
}
|
|
||||||
catch (CPackageLoadException& ex)
|
|
||||||
{
|
|
||||||
// ignore this error, the package file was not found
|
|
||||||
sLog.out ("No ", pkgfile, " file found at ", path, ". Defaulting to normal folder storage");
|
|
||||||
}
|
|
||||||
catch (std::runtime_error& ex)
|
|
||||||
{
|
|
||||||
// the package was found but there was an error loading it (wrong header or something)
|
|
||||||
sLog.exception ("Failed to load scene.pkg file: ", ex.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CVirtualContainer* buildVirtualContainer ()
|
|
||||||
{
|
|
||||||
CVirtualContainer* container = new WallpaperEngine::Assets::CVirtualContainer ();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Had to get a little creative with the effects to achieve the same bloom effect without any custom code
|
|
||||||
// these virtual files are loaded by an image in the scene that takes current _rt_FullFrameBuffer and
|
|
||||||
// applies the bloom effect to render it out to the screen
|
|
||||||
//
|
|
||||||
|
|
||||||
// add the effect file for screen bloom
|
|
||||||
container->add (
|
|
||||||
"effects/wpenginelinux/bloomeffect.json",
|
|
||||||
"{"
|
|
||||||
"\t\"name\":\"camerabloom_wpengine_linux\","
|
|
||||||
"\t\"group\":\"wpengine_linux_camera\","
|
|
||||||
"\t\"dependencies\":[],"
|
|
||||||
"\t\"passes\":"
|
|
||||||
"\t["
|
|
||||||
"\t\t{"
|
|
||||||
"\t\t\t\"material\": \"materials/util/downsample_quarter_bloom.json\","
|
|
||||||
"\t\t\t\"target\": \"_rt_4FrameBuffer\","
|
|
||||||
"\t\t\t\"bind\":"
|
|
||||||
"\t\t\t["
|
|
||||||
"\t\t\t\t{"
|
|
||||||
"\t\t\t\t\t\"name\": \"_rt_FullFrameBuffer\","
|
|
||||||
"\t\t\t\t\t\"index\": 0"
|
|
||||||
"\t\t\t\t}"
|
|
||||||
"\t\t\t]"
|
|
||||||
"\t\t},"
|
|
||||||
"\t\t{"
|
|
||||||
"\t\t\t\"material\": \"materials/util/downsample_eighth_blur_v.json\","
|
|
||||||
"\t\t\t\"target\": \"_rt_8FrameBuffer\","
|
|
||||||
"\t\t\t\"bind\":"
|
|
||||||
"\t\t\t["
|
|
||||||
"\t\t\t\t{"
|
|
||||||
"\t\t\t\t\t\"name\": \"_rt_4FrameBuffer\","
|
|
||||||
"\t\t\t\t\t\"index\": 0"
|
|
||||||
"\t\t\t\t}"
|
|
||||||
"\t\t\t]"
|
|
||||||
"\t\t},"
|
|
||||||
"\t\t{"
|
|
||||||
"\t\t\t\"material\": \"materials/util/blur_h_bloom.json\","
|
|
||||||
"\t\t\t\"target\": \"_rt_Bloom\","
|
|
||||||
"\t\t\t\"bind\":"
|
|
||||||
"\t\t\t["
|
|
||||||
"\t\t\t\t{"
|
|
||||||
"\t\t\t\t\t\"name\": \"_rt_8FrameBuffer\","
|
|
||||||
"\t\t\t\t\t\"index\": 0"
|
|
||||||
"\t\t\t\t}"
|
|
||||||
"\t\t\t]"
|
|
||||||
"\t\t},"
|
|
||||||
"\t\t{"
|
|
||||||
"\t\t\t\"material\": \"materials/util/combine.json\","
|
|
||||||
"\t\t\t\"target\": \"_rt_FullFrameBuffer\","
|
|
||||||
"\t\t\t\"bind\":"
|
|
||||||
"\t\t\t["
|
|
||||||
"\t\t\t\t{"
|
|
||||||
"\t\t\t\t\t\"name\": \"_rt_imageLayerComposite_-1_a\","
|
|
||||||
"\t\t\t\t\t\"index\": 0"
|
|
||||||
"\t\t\t\t},"
|
|
||||||
"\t\t\t\t{"
|
|
||||||
"\t\t\t\t\t\"name\": \"_rt_Bloom\","
|
|
||||||
"\t\t\t\t\t\"index\": 1"
|
|
||||||
"\t\t\t\t}"
|
|
||||||
"\t\t\t]"
|
|
||||||
"\t\t}"
|
|
||||||
"\t]"
|
|
||||||
"}"
|
|
||||||
);
|
|
||||||
|
|
||||||
// add some model for the image element even if it's going to waste rendering cycles
|
|
||||||
container->add (
|
|
||||||
"models/wpenginelinux.json",
|
|
||||||
"{"
|
|
||||||
"\t\"material\":\"materials/wpenginelinux.json\""
|
|
||||||
"}"
|
|
||||||
);
|
|
||||||
|
|
||||||
// models require materials, so add that too
|
|
||||||
container->add (
|
|
||||||
"materials/wpenginelinux.json",
|
|
||||||
"{"
|
|
||||||
"\t\"passes\":"
|
|
||||||
"\t\t["
|
|
||||||
"\t\t\t{"
|
|
||||||
"\t\t\t\t\"blending\": \"normal\","
|
|
||||||
"\t\t\t\t\"cullmode\": \"nocull\","
|
|
||||||
"\t\t\t\t\"depthtest\": \"disabled\","
|
|
||||||
"\t\t\t\t\"depthwrite\": \"disabled\","
|
|
||||||
"\t\t\t\t\"shader\": \"genericimage2\","
|
|
||||||
"\t\t\t\t\"textures\": [\"_rt_FullFrameBuffer\"]"
|
|
||||||
"\t\t\t}"
|
|
||||||
"\t\t]"
|
|
||||||
"}"
|
|
||||||
);
|
|
||||||
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
|
|
||||||
void takeScreenshot (WallpaperEngine::Render::CWallpaper* wp, const std::filesystem::path& filename, FREE_IMAGE_FORMAT format)
|
|
||||||
{
|
|
||||||
GLint width, height;
|
|
||||||
|
|
||||||
// bind texture and get the size
|
|
||||||
glBindFramebuffer (GL_FRAMEBUFFER, wp->getWallpaperFramebuffer ());
|
|
||||||
glBindTexture (GL_TEXTURE_2D, wp->getWallpaperTexture ());
|
|
||||||
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
|
|
||||||
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
|
|
||||||
|
|
||||||
// make room for storing the pixel data
|
|
||||||
uint8_t* buffer = new uint8_t [width * height * sizeof (uint8_t) * 3];
|
|
||||||
uint8_t* pixel = buffer;
|
|
||||||
|
|
||||||
// read the image into the buffer
|
|
||||||
glReadPixels (0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
|
|
||||||
|
|
||||||
// build the output file with FreeImage
|
|
||||||
FIBITMAP* bitmap = FreeImage_Allocate (width, height, 24);
|
|
||||||
RGBQUAD color;
|
|
||||||
|
|
||||||
// now get access to the pixels
|
|
||||||
for (int y = height; y > 0; y --)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < width; x ++)
|
|
||||||
{
|
|
||||||
color.rgbRed = *pixel ++;
|
|
||||||
color.rgbGreen = *pixel ++;
|
|
||||||
color.rgbBlue = *pixel ++;
|
|
||||||
|
|
||||||
// set the pixel in the destination
|
|
||||||
FreeImage_SetPixelColor (bitmap, x, y, &color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// finally save the file
|
|
||||||
FreeImage_Save (format, bitmap, filename.c_str (), 0);
|
|
||||||
|
|
||||||
// free all the used memory
|
|
||||||
delete[] buffer;
|
|
||||||
|
|
||||||
FreeImage_Unload (bitmap);
|
|
||||||
|
|
||||||
// unbind the textures
|
|
||||||
glBindTexture (GL_TEXTURE_2D, GL_NONE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void initLogging ()
|
void initLogging ()
|
||||||
@ -256,244 +50,21 @@ int main (int argc, char* argv[])
|
|||||||
{
|
{
|
||||||
initLogging ();
|
initLogging ();
|
||||||
|
|
||||||
std::vector <std::string> screens;
|
WallpaperEngine::Application::CApplicationContext appContext (argc, argv);
|
||||||
std::map <std::string, std::string> propertyOverrides;
|
WallpaperEngine::Application::CWallpaperApplication app (appContext);
|
||||||
|
|
||||||
int maximumFPS = 30;
|
|
||||||
bool shouldTakeScreenshot = false;
|
|
||||||
bool shouldListPropertiesAndStop = false;
|
|
||||||
FREE_IMAGE_FORMAT screenshotFormat = FIF_UNKNOWN;
|
|
||||||
std::string path;
|
|
||||||
std::filesystem::path assetsPath;
|
|
||||||
std::filesystem::path screenshotPath;
|
|
||||||
|
|
||||||
static struct option long_options [] = {
|
|
||||||
{"screen-root", required_argument, 0, 'r'},
|
|
||||||
{"pkg", required_argument, 0, 'p'},
|
|
||||||
{"dir", required_argument, 0, 'd'},
|
|
||||||
{"silent", no_argument, 0, 's'},
|
|
||||||
{"volume", required_argument, 0, 'v'},
|
|
||||||
{"help", no_argument, 0, 'h'},
|
|
||||||
{"fps", required_argument, 0, 'f'},
|
|
||||||
{"assets-dir", required_argument, 0, 'a'},
|
|
||||||
{"screenshot", required_argument, 0, 'c'},
|
|
||||||
{"list-properties", no_argument, 0, 'l'},
|
|
||||||
{"set-property", required_argument, 0, 'o'},
|
|
||||||
{nullptr, 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
int c = getopt_long (argc, argv, "r:p:d:shf:a:", long_options, nullptr);
|
|
||||||
|
|
||||||
if (c == -1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case 'o':
|
|
||||||
{
|
|
||||||
std::string value = optarg;
|
|
||||||
std::string::size_type equals = value.find ('=');
|
|
||||||
|
|
||||||
// properties without value are treated as booleans for now
|
|
||||||
if (equals == std::string::npos)
|
|
||||||
propertyOverrides.insert_or_assign (value, "1");
|
|
||||||
else
|
|
||||||
propertyOverrides.insert_or_assign (
|
|
||||||
value.substr (0, equals),
|
|
||||||
value.substr (equals + 1)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'l':
|
|
||||||
shouldListPropertiesAndStop = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'r':
|
|
||||||
screens.emplace_back (optarg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'p':
|
|
||||||
case 'd':
|
|
||||||
sLog.error ("--dir/--pkg is deprecated and not used anymore");
|
|
||||||
path = stringPathFixes (optarg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 's':
|
|
||||||
g_AudioEnabled = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'h':
|
|
||||||
print_help (argv [0]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'f':
|
|
||||||
maximumFPS = atoi (optarg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'a': assetsPath = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'v':
|
|
||||||
g_AudioVolume = atoi (optarg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'c':
|
|
||||||
shouldTakeScreenshot = true;
|
|
||||||
screenshotPath = stringPathFixes (optarg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path.empty () == true)
|
|
||||||
{
|
|
||||||
if (optind < argc && strlen (argv [optind]) > 0)
|
|
||||||
{
|
|
||||||
path = argv [optind];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
print_help (argv [0]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate screenshot file just to make sure
|
|
||||||
if (shouldTakeScreenshot == true)
|
|
||||||
{
|
|
||||||
if (screenshotPath.has_extension () == false)
|
|
||||||
sLog.exception ("Cannot determine screenshot format");
|
|
||||||
|
|
||||||
std::string extension = screenshotPath.extension ();
|
|
||||||
|
|
||||||
if (extension == ".bmp")
|
|
||||||
screenshotFormat = FIF_BMP;
|
|
||||||
else if (extension == ".png")
|
|
||||||
screenshotFormat = FIF_PNG;
|
|
||||||
else if (extension == ".jpg" || extension == ".jpeg")
|
|
||||||
screenshotFormat = FIF_JPEG;
|
|
||||||
else
|
|
||||||
sLog.exception ("Cannot determine screenshot format, unknown extension ", extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
path = Steam::FileSystem::workshopDirectory (WORKSHOP_APP_ID, path);
|
|
||||||
|
|
||||||
WallpaperEngine::Assets::CCombinedContainer containers;
|
|
||||||
// the background's path is required to load project.json regardless of the type of background we're using
|
|
||||||
containers.add (new WallpaperEngine::Assets::CDirectory (path));
|
|
||||||
// add the virtual container for mocked up files
|
|
||||||
containers.add (buildVirtualContainer ());
|
|
||||||
// try to add the common packages
|
|
||||||
addPkg (&containers, path, "scene.pkg");
|
|
||||||
addPkg (&containers, path, "gifscene.pkg");
|
|
||||||
|
|
||||||
if (assetsPath.empty () == true)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
assetsPath = Steam::FileSystem::appDirectory (APP_DIRECTORY, "assets");
|
|
||||||
}
|
|
||||||
catch (std::runtime_error)
|
|
||||||
{
|
|
||||||
// set current path as assets' folder
|
|
||||||
std::filesystem::path directory = std::filesystem::canonical ("/proc/self/exe")
|
|
||||||
.parent_path () / "assets";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sLog.out ("Found wallpaper engine's assets at ", assetsPath, " based on --assets-dir parameter");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (assetsPath.empty () == true)
|
|
||||||
sLog.exception ("Cannot determine a valid path for the wallpaper engine assets");
|
|
||||||
|
|
||||||
// add containers to the list
|
|
||||||
containers.add (new WallpaperEngine::Assets::CDirectory (assetsPath));
|
|
||||||
|
|
||||||
// parse the project.json file
|
|
||||||
auto project = WallpaperEngine::Core::CProject::fromFile ("project.json", &containers);
|
|
||||||
// go to the right folder so the videos will play
|
|
||||||
if (project->getWallpaper ()->is <WallpaperEngine::Core::CVideo> () == true)
|
|
||||||
chdir (path.c_str ());
|
|
||||||
|
|
||||||
// show properties if required
|
|
||||||
for (auto cur : project->getProperties ())
|
|
||||||
{
|
|
||||||
// update the value of the property
|
|
||||||
auto override = propertyOverrides.find (cur->getName ());
|
|
||||||
|
|
||||||
if (override != propertyOverrides.end ())
|
|
||||||
{
|
|
||||||
sLog.out ("Applying override value for ", cur->getName ());
|
|
||||||
|
|
||||||
cur->update (override->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldListPropertiesAndStop)
|
|
||||||
sLog.out (cur->dump ());
|
|
||||||
}
|
|
||||||
|
|
||||||
// halt if the list-properties option was specified
|
// halt if the list-properties option was specified
|
||||||
if (shouldListPropertiesAndStop)
|
if (appContext.onlyListProperties)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// attach signals so if a stop is requested the X11 resources are freed and the program shutsdown gracefully
|
appPointer = &app;
|
||||||
std::signal(SIGINT, signalhandler);
|
|
||||||
std::signal(SIGTERM, signalhandler);
|
|
||||||
|
|
||||||
// initialize sdl audio driver
|
// attach signals to gracefully stop
|
||||||
WallpaperEngine::Audio::Drivers::CSDLAudioDriver audioDriver;
|
std::signal (SIGINT, signalhandler);
|
||||||
// initialize audio context
|
std::signal (SIGTERM, signalhandler);
|
||||||
WallpaperEngine::Audio::CAudioContext audioContext (&audioDriver);
|
|
||||||
// initialize OpenGL driver
|
|
||||||
WallpaperEngine::Render::Drivers::COpenGLDriver videoDriver ("Wallpaper Engine");
|
|
||||||
// initialize render context
|
|
||||||
WallpaperEngine::Render::CRenderContext context (screens, videoDriver, &containers);
|
|
||||||
// initialize mouse support
|
|
||||||
context.setMouse (new CMouseInput (videoDriver.getWindow ()));
|
|
||||||
// ensure the context knows what wallpaper to render
|
|
||||||
context.setWallpaper (
|
|
||||||
WallpaperEngine::Render::CWallpaper::fromWallpaper (project->getWallpaper (), &context, &audioContext)
|
|
||||||
);
|
|
||||||
|
|
||||||
float startTime, endTime, minimumTime = 1.0f / maximumFPS;
|
// show the wallpaper application
|
||||||
|
app.show ();
|
||||||
while (videoDriver.closeRequested () == false && g_KeepRunning == true)
|
|
||||||
{
|
|
||||||
// keep track of the previous frame's time
|
|
||||||
g_TimeLast = g_Time;
|
|
||||||
// calculate the current time value
|
|
||||||
g_Time = videoDriver.getRenderTime ();
|
|
||||||
// get the start time of the frame
|
|
||||||
startTime = g_Time;
|
|
||||||
// render the scene
|
|
||||||
context.render ();
|
|
||||||
// get the end time of the frame
|
|
||||||
endTime = videoDriver.getRenderTime ();
|
|
||||||
|
|
||||||
// ensure the frame time is correct to not overrun FPS
|
|
||||||
if ((endTime - startTime) < minimumTime)
|
|
||||||
usleep ((minimumTime - (endTime - startTime)) * CLOCKS_PER_SEC);
|
|
||||||
|
|
||||||
if (shouldTakeScreenshot == true && videoDriver.getFrameCounter () == 5)
|
|
||||||
{
|
|
||||||
takeScreenshot (context.getWallpaper (), screenshotPath, screenshotFormat);
|
|
||||||
// disable screenshot just in case the counter overflows
|
|
||||||
shouldTakeScreenshot = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure this is updated as sometimes it might not come from a signal
|
|
||||||
g_KeepRunning = false;
|
|
||||||
|
|
||||||
sLog.out ("Stop requested");
|
|
||||||
|
|
||||||
SDL_Quit ();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
199
src/WallpaperEngine/Application/CApplicationContext.cpp
Normal file
199
src/WallpaperEngine/Application/CApplicationContext.cpp
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
#include "CApplicationContext.h"
|
||||||
|
|
||||||
|
#include "Steam/FileSystem/FileSystem.h"
|
||||||
|
#include "WallpaperEngine/Logging/CLog.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
#define WORKSHOP_APP_ID 431960
|
||||||
|
#define APP_DIRECTORY "wallpaper_engine"
|
||||||
|
|
||||||
|
using namespace WallpaperEngine::Application;
|
||||||
|
|
||||||
|
struct option long_options [] = {
|
||||||
|
{"screen-root", required_argument, 0, 'r'},
|
||||||
|
{"pkg", required_argument, 0, 'p'},
|
||||||
|
{"dir", required_argument, 0, 'd'},
|
||||||
|
{"silent", no_argument, 0, 's'},
|
||||||
|
{"volume", required_argument, 0, 'v'},
|
||||||
|
{"help", no_argument, 0, 'h'},
|
||||||
|
{"fps", required_argument, 0, 'f'},
|
||||||
|
{"assets-dir", required_argument, 0, 'a'},
|
||||||
|
{"screenshot", required_argument, 0, 'c'},
|
||||||
|
{"list-properties", no_argument, 0, 'l'},
|
||||||
|
{"set-property", required_argument, 0, 'o'},
|
||||||
|
{nullptr, 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string stringPathFixes(const std::string& s)
|
||||||
|
{
|
||||||
|
if (s.empty () == true)
|
||||||
|
return s;
|
||||||
|
|
||||||
|
std::string str (s);
|
||||||
|
|
||||||
|
// remove single-quotes from the arguments
|
||||||
|
if (str [0] == '\'' && str [str.size() - 1] == '\'')
|
||||||
|
str
|
||||||
|
.erase (str.size() - 1, 1)
|
||||||
|
.erase (0, 1);
|
||||||
|
|
||||||
|
return std::move (str);
|
||||||
|
}
|
||||||
|
|
||||||
|
CApplicationContext::CApplicationContext (int argc, char* argv[]) :
|
||||||
|
takeScreenshot (false),
|
||||||
|
maximumFPS (30),
|
||||||
|
audioVolume (128),
|
||||||
|
audioEnabled (true),
|
||||||
|
onlyListProperties (false)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
while ((c = getopt_long (argc, argv, "r:p:d:shf:a:", long_options, nullptr)) != -1)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'o':
|
||||||
|
{
|
||||||
|
std::string value = optarg;
|
||||||
|
std::string::size_type equals = value.find ('=');
|
||||||
|
|
||||||
|
// properties without value are treated as booleans for now
|
||||||
|
if (equals == std::string::npos)
|
||||||
|
this->properties.insert_or_assign (value, "1");
|
||||||
|
else
|
||||||
|
this->properties.insert_or_assign (
|
||||||
|
value.substr (0, equals),
|
||||||
|
value.substr (equals + 1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'l':
|
||||||
|
this->onlyListProperties = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'r':
|
||||||
|
screens.emplace_back (optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
case 'd':
|
||||||
|
sLog.error ("--dir/--pkg is deprecated and not used anymore");
|
||||||
|
this->background = stringPathFixes (optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
this->audioEnabled = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
this->printHelp (argv [0]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
maximumFPS = atoi (optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'a':
|
||||||
|
this->assets = stringPathFixes (optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'v':
|
||||||
|
this->audioVolume = std::max (atoi (optarg), 128);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
this->takeScreenshot = true;
|
||||||
|
this->screenshot = stringPathFixes (optarg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->background.empty () == true)
|
||||||
|
{
|
||||||
|
if (optind < argc && strlen (argv [optind]) > 0)
|
||||||
|
{
|
||||||
|
this->background = argv [optind];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->printHelp (argv [0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// perform some extra validation on the inputs
|
||||||
|
this->validatePath ();
|
||||||
|
this->validateAssets ();
|
||||||
|
this->validateScreenshot ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CApplicationContext::validatePath ()
|
||||||
|
{
|
||||||
|
if (this->background.find ('/') != std::string::npos)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this->background = Steam::FileSystem::workshopDirectory (WORKSHOP_APP_ID, this->background);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CApplicationContext::validateAssets ()
|
||||||
|
{
|
||||||
|
if (this->assets.empty () == false)
|
||||||
|
{
|
||||||
|
sLog.out ("Using wallpaper engine's assets at ", this->assets, " based on --assets-dir parameter");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this->assets = Steam::FileSystem::appDirectory (APP_DIRECTORY, "assets");
|
||||||
|
}
|
||||||
|
catch (std::runtime_error&)
|
||||||
|
{
|
||||||
|
// set current path as assets' folder
|
||||||
|
std::filesystem::path directory = std::filesystem::canonical ("/proc/self/exe")
|
||||||
|
.parent_path () / "assets";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CApplicationContext::validateScreenshot ()
|
||||||
|
{
|
||||||
|
if (this->takeScreenshot == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this->screenshot.has_extension () == false)
|
||||||
|
sLog.exception ("Cannot determine screenshot format");
|
||||||
|
|
||||||
|
std::string extension = this->screenshot.extension ();
|
||||||
|
|
||||||
|
if (extension == ".bmp")
|
||||||
|
this->screenshotFormat = FIF_BMP;
|
||||||
|
else if (extension == ".png")
|
||||||
|
this->screenshotFormat = FIF_PNG;
|
||||||
|
else if (extension == ".jpg" || extension == ".jpeg")
|
||||||
|
this->screenshotFormat = FIF_JPEG;
|
||||||
|
else
|
||||||
|
sLog.exception ("Cannot determine screenshot format, unknown extension ", extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CApplicationContext::printHelp (const char* route)
|
||||||
|
{
|
||||||
|
sLog.out ("Usage: ", route, " [options] background_path/background_id");
|
||||||
|
sLog.out ("");
|
||||||
|
sLog.out ("where background_path/background_id can be:");
|
||||||
|
sLog.out ("\tthe ID of the background (for autodetection on your steam installation)");
|
||||||
|
sLog.out ("\ta full path to the background's folder");
|
||||||
|
sLog.out ("");
|
||||||
|
sLog.out ("options:");
|
||||||
|
sLog.out ("\t--silent\t\t\t\t\tMutes all the sound the wallpaper might produce");
|
||||||
|
sLog.out ("\t--volume <amount>\t\t\tSets the volume for all the sounds in the background");
|
||||||
|
sLog.out ("\t--screen-root <screen name>\tDisplay as screen's background");
|
||||||
|
sLog.out ("\t--fps <maximum-fps>\t\t\tLimits the FPS to the given number, useful to keep battery consumption low");
|
||||||
|
sLog.out ("\t--assets-dir <path>\t\t\tFolder where the assets are stored");
|
||||||
|
sLog.out ("\t--screenshot\t\t\t\tTakes a screenshot of the background");
|
||||||
|
sLog.out ("\t--list-properties\t\t\tList all the available properties and their possible values");
|
||||||
|
sLog.out ("\t--set-property <name=value>\tOverrides the default value of the given property");
|
||||||
|
}
|
34
src/WallpaperEngine/Application/CApplicationContext.h
Normal file
34
src/WallpaperEngine/Application/CApplicationContext.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <FreeImage.h>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace WallpaperEngine::Application
|
||||||
|
{
|
||||||
|
class CApplicationContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CApplicationContext (int argc, char* argv[]);
|
||||||
|
|
||||||
|
std::vector <std::string> screens;
|
||||||
|
std::map <std::string, std::string> properties;
|
||||||
|
std::string background;
|
||||||
|
std::filesystem::path assets;
|
||||||
|
std::filesystem::path screenshot;
|
||||||
|
bool takeScreenshot;
|
||||||
|
int maximumFPS;
|
||||||
|
int audioVolume;
|
||||||
|
bool audioEnabled;
|
||||||
|
bool onlyListProperties;
|
||||||
|
FREE_IMAGE_FORMAT screenshotFormat;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void validatePath ();
|
||||||
|
void validateAssets ();
|
||||||
|
void validateScreenshot ();
|
||||||
|
void printHelp (const char* route);
|
||||||
|
};
|
||||||
|
}
|
265
src/WallpaperEngine/Application/CWallpaperApplication.cpp
Normal file
265
src/WallpaperEngine/Application/CWallpaperApplication.cpp
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
#include "CWallpaperApplication.h"
|
||||||
|
#include "WallpaperEngine/Assets/CDirectory.h"
|
||||||
|
#include "WallpaperEngine/Assets/CVirtualContainer.h"
|
||||||
|
#include "WallpaperEngine/Audio/Drivers/CSDLAudioDriver.h"
|
||||||
|
#include "WallpaperEngine/Core/CVideo.h"
|
||||||
|
#include "WallpaperEngine/Logging/CLog.h"
|
||||||
|
#include "WallpaperEngine/Render/CRenderContext.h"
|
||||||
|
#include "WallpaperEngine/Render/Drivers/COpenGLDriver.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
float g_Time;
|
||||||
|
float g_TimeLast;
|
||||||
|
bool g_KeepRunning = true;
|
||||||
|
bool g_AudioEnabled = true;
|
||||||
|
int g_AudioVolume = 128;
|
||||||
|
|
||||||
|
using namespace WallpaperEngine::Application;
|
||||||
|
|
||||||
|
CWallpaperApplication::CWallpaperApplication (CApplicationContext& context) :
|
||||||
|
m_context (context)
|
||||||
|
{
|
||||||
|
this->setupContainer ();
|
||||||
|
this->loadProject ();
|
||||||
|
this->setupProperties ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWallpaperApplication::setupContainer ()
|
||||||
|
{
|
||||||
|
this->m_vfs.add (new CDirectory (this->m_context.background));
|
||||||
|
this->m_vfs.addPkg (std::filesystem::path (this->m_context.background) / "scene.pkg");
|
||||||
|
this->m_vfs.addPkg (std::filesystem::path (this->m_context.background) / "gifscene.pkg");
|
||||||
|
this->m_vfs.add (new CDirectory (this->m_context.assets));
|
||||||
|
|
||||||
|
// TODO: move this somewhere else?
|
||||||
|
CVirtualContainer* container = new CVirtualContainer ();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Had to get a little creative with the effects to achieve the same bloom effect without any custom code
|
||||||
|
// these virtual files are loaded by an image in the scene that takes current _rt_FullFrameBuffer and
|
||||||
|
// applies the bloom effect to render it out to the screen
|
||||||
|
//
|
||||||
|
|
||||||
|
// add the effect file for screen bloom
|
||||||
|
container->add (
|
||||||
|
"effects/wpenginelinux/bloomeffect.json",
|
||||||
|
"{"
|
||||||
|
"\t\"name\":\"camerabloom_wpengine_linux\","
|
||||||
|
"\t\"group\":\"wpengine_linux_camera\","
|
||||||
|
"\t\"dependencies\":[],"
|
||||||
|
"\t\"passes\":"
|
||||||
|
"\t["
|
||||||
|
"\t\t{"
|
||||||
|
"\t\t\t\"material\": \"materials/util/downsample_quarter_bloom.json\","
|
||||||
|
"\t\t\t\"target\": \"_rt_4FrameBuffer\","
|
||||||
|
"\t\t\t\"bind\":"
|
||||||
|
"\t\t\t["
|
||||||
|
"\t\t\t\t{"
|
||||||
|
"\t\t\t\t\t\"name\": \"_rt_FullFrameBuffer\","
|
||||||
|
"\t\t\t\t\t\"index\": 0"
|
||||||
|
"\t\t\t\t}"
|
||||||
|
"\t\t\t]"
|
||||||
|
"\t\t},"
|
||||||
|
"\t\t{"
|
||||||
|
"\t\t\t\"material\": \"materials/util/downsample_eighth_blur_v.json\","
|
||||||
|
"\t\t\t\"target\": \"_rt_8FrameBuffer\","
|
||||||
|
"\t\t\t\"bind\":"
|
||||||
|
"\t\t\t["
|
||||||
|
"\t\t\t\t{"
|
||||||
|
"\t\t\t\t\t\"name\": \"_rt_4FrameBuffer\","
|
||||||
|
"\t\t\t\t\t\"index\": 0"
|
||||||
|
"\t\t\t\t}"
|
||||||
|
"\t\t\t]"
|
||||||
|
"\t\t},"
|
||||||
|
"\t\t{"
|
||||||
|
"\t\t\t\"material\": \"materials/util/blur_h_bloom.json\","
|
||||||
|
"\t\t\t\"target\": \"_rt_Bloom\","
|
||||||
|
"\t\t\t\"bind\":"
|
||||||
|
"\t\t\t["
|
||||||
|
"\t\t\t\t{"
|
||||||
|
"\t\t\t\t\t\"name\": \"_rt_8FrameBuffer\","
|
||||||
|
"\t\t\t\t\t\"index\": 0"
|
||||||
|
"\t\t\t\t}"
|
||||||
|
"\t\t\t]"
|
||||||
|
"\t\t},"
|
||||||
|
"\t\t{"
|
||||||
|
"\t\t\t\"material\": \"materials/util/combine.json\","
|
||||||
|
"\t\t\t\"target\": \"_rt_FullFrameBuffer\","
|
||||||
|
"\t\t\t\"bind\":"
|
||||||
|
"\t\t\t["
|
||||||
|
"\t\t\t\t{"
|
||||||
|
"\t\t\t\t\t\"name\": \"_rt_imageLayerComposite_-1_a\","
|
||||||
|
"\t\t\t\t\t\"index\": 0"
|
||||||
|
"\t\t\t\t},"
|
||||||
|
"\t\t\t\t{"
|
||||||
|
"\t\t\t\t\t\"name\": \"_rt_Bloom\","
|
||||||
|
"\t\t\t\t\t\"index\": 1"
|
||||||
|
"\t\t\t\t}"
|
||||||
|
"\t\t\t]"
|
||||||
|
"\t\t}"
|
||||||
|
"\t]"
|
||||||
|
"}"
|
||||||
|
);
|
||||||
|
|
||||||
|
// add some model for the image element even if it's going to waste rendering cycles
|
||||||
|
container->add (
|
||||||
|
"models/wpenginelinux.json",
|
||||||
|
"{"
|
||||||
|
"\t\"material\":\"materials/wpenginelinux.json\""
|
||||||
|
"}"
|
||||||
|
);
|
||||||
|
|
||||||
|
// models require materials, so add that too
|
||||||
|
container->add (
|
||||||
|
"materials/wpenginelinux.json",
|
||||||
|
"{"
|
||||||
|
"\t\"passes\":"
|
||||||
|
"\t\t["
|
||||||
|
"\t\t\t{"
|
||||||
|
"\t\t\t\t\"blending\": \"normal\","
|
||||||
|
"\t\t\t\t\"cullmode\": \"nocull\","
|
||||||
|
"\t\t\t\t\"depthtest\": \"disabled\","
|
||||||
|
"\t\t\t\t\"depthwrite\": \"disabled\","
|
||||||
|
"\t\t\t\t\"shader\": \"genericimage2\","
|
||||||
|
"\t\t\t\t\"textures\": [\"_rt_FullFrameBuffer\"]"
|
||||||
|
"\t\t\t}"
|
||||||
|
"\t\t]"
|
||||||
|
"}"
|
||||||
|
);
|
||||||
|
|
||||||
|
this->m_vfs.add (container);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWallpaperApplication::loadProject ()
|
||||||
|
{
|
||||||
|
this->m_project = CProject::fromFile ("project.json", &this->m_vfs);
|
||||||
|
// go to the right folder so the videos will play
|
||||||
|
// TODO: stop doing chdir and use full path
|
||||||
|
if (this->m_project->getWallpaper ()->is <WallpaperEngine::Core::CVideo> () == true)
|
||||||
|
chdir (this->m_context.background.c_str ());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWallpaperApplication::setupProperties ()
|
||||||
|
{
|
||||||
|
// show properties if required
|
||||||
|
for (auto cur : this->m_project->getProperties ())
|
||||||
|
{
|
||||||
|
// update the value of the property
|
||||||
|
auto override = this->m_context.properties.find (cur->getName ());
|
||||||
|
|
||||||
|
if (override != this->m_context.properties.end ())
|
||||||
|
{
|
||||||
|
sLog.out ("Applying override value for ", cur->getName ());
|
||||||
|
|
||||||
|
cur->update (override->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->m_context.onlyListProperties)
|
||||||
|
sLog.out (cur->dump ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWallpaperApplication::takeScreenshot (WallpaperEngine::Render::CWallpaper* wp, const std::filesystem::path& filename, FREE_IMAGE_FORMAT format)
|
||||||
|
{
|
||||||
|
GLint width, height;
|
||||||
|
|
||||||
|
// bind texture and get the size
|
||||||
|
glBindFramebuffer (GL_FRAMEBUFFER, wp->getWallpaperFramebuffer ());
|
||||||
|
glBindTexture (GL_TEXTURE_2D, wp->getWallpaperTexture ());
|
||||||
|
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
|
||||||
|
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
|
||||||
|
|
||||||
|
// make room for storing the pixel data
|
||||||
|
uint8_t* buffer = new uint8_t [width * height * sizeof (uint8_t) * 3];
|
||||||
|
uint8_t* pixel = buffer;
|
||||||
|
|
||||||
|
// read the image into the buffer
|
||||||
|
glReadPixels (0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
|
||||||
|
|
||||||
|
// build the output file with FreeImage
|
||||||
|
FIBITMAP* bitmap = FreeImage_Allocate (width, height, 24);
|
||||||
|
RGBQUAD color;
|
||||||
|
|
||||||
|
// now get access to the pixels
|
||||||
|
for (int y = height; y > 0; y --)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < width; x ++)
|
||||||
|
{
|
||||||
|
color.rgbRed = *pixel ++;
|
||||||
|
color.rgbGreen = *pixel ++;
|
||||||
|
color.rgbBlue = *pixel ++;
|
||||||
|
|
||||||
|
// set the pixel in the destination
|
||||||
|
FreeImage_SetPixelColor (bitmap, x, y, &color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// finally save the file
|
||||||
|
FreeImage_Save (format, bitmap, filename.c_str (), 0);
|
||||||
|
|
||||||
|
// free all the used memory
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
FreeImage_Unload (bitmap);
|
||||||
|
|
||||||
|
// unbind the textures
|
||||||
|
glBindTexture (GL_TEXTURE_2D, GL_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWallpaperApplication::show ()
|
||||||
|
{
|
||||||
|
// initialize sdl audio driver
|
||||||
|
WallpaperEngine::Audio::Drivers::CSDLAudioDriver audioDriver;
|
||||||
|
// initialize audio context
|
||||||
|
WallpaperEngine::Audio::CAudioContext audioContext (&audioDriver);
|
||||||
|
// initialize OpenGL driver
|
||||||
|
WallpaperEngine::Render::Drivers::COpenGLDriver videoDriver (this->m_project->getTitle ().c_str ());
|
||||||
|
// initialize render context
|
||||||
|
WallpaperEngine::Render::CRenderContext context (this->m_context.screens, videoDriver, &this->m_vfs);
|
||||||
|
// initialize mouse support
|
||||||
|
context.setMouse (new CMouseInput (videoDriver.getWindow ()));
|
||||||
|
// ensure the context knows what wallpaper to render
|
||||||
|
context.setWallpaper (
|
||||||
|
WallpaperEngine::Render::CWallpaper::fromWallpaper (this->m_project->getWallpaper (), &context, &audioContext)
|
||||||
|
);
|
||||||
|
|
||||||
|
float startTime, endTime, minimumTime = 1.0f / this->m_context.maximumFPS;
|
||||||
|
|
||||||
|
while (videoDriver.closeRequested () == false && g_KeepRunning == true)
|
||||||
|
{
|
||||||
|
// keep track of the previous frame's time
|
||||||
|
g_TimeLast = g_Time;
|
||||||
|
// calculate the current time value
|
||||||
|
g_Time = videoDriver.getRenderTime ();
|
||||||
|
// get the start time of the frame
|
||||||
|
startTime = g_Time;
|
||||||
|
// render the scene
|
||||||
|
context.render ();
|
||||||
|
// get the end time of the frame
|
||||||
|
endTime = videoDriver.getRenderTime ();
|
||||||
|
|
||||||
|
// ensure the frame time is correct to not overrun FPS
|
||||||
|
if ((endTime - startTime) < minimumTime)
|
||||||
|
usleep ((minimumTime - (endTime - startTime)) * CLOCKS_PER_SEC);
|
||||||
|
|
||||||
|
if (this->m_context.takeScreenshot == true && videoDriver.getFrameCounter () == 5)
|
||||||
|
{
|
||||||
|
this->takeScreenshot (context.getWallpaper (), this->m_context.screenshot, this->m_context.screenshotFormat);
|
||||||
|
// disable screenshot just in case the counter overflows
|
||||||
|
this->m_context.takeScreenshot = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure this is updated as sometimes it might not come from a signal
|
||||||
|
g_KeepRunning = false;
|
||||||
|
|
||||||
|
sLog.out ("Stop requested");
|
||||||
|
|
||||||
|
SDL_Quit ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWallpaperApplication::signal (int signal)
|
||||||
|
{
|
||||||
|
g_KeepRunning = false;
|
||||||
|
}
|
31
src/WallpaperEngine/Application/CWallpaperApplication.h
Normal file
31
src/WallpaperEngine/Application/CWallpaperApplication.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CApplicationContext.h"
|
||||||
|
#include "WallpaperEngine/Assets/CCombinedContainer.h"
|
||||||
|
#include "WallpaperEngine/Core/CProject.h"
|
||||||
|
#include "WallpaperEngine/Render/CWallpaper.h"
|
||||||
|
|
||||||
|
namespace WallpaperEngine::Application
|
||||||
|
{
|
||||||
|
using namespace WallpaperEngine::Core;
|
||||||
|
using namespace WallpaperEngine::Assets;
|
||||||
|
|
||||||
|
class CWallpaperApplication
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CWallpaperApplication (CApplicationContext& context);
|
||||||
|
|
||||||
|
void show ();
|
||||||
|
void signal (int signal);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupContainer ();
|
||||||
|
void loadProject ();
|
||||||
|
void setupProperties ();
|
||||||
|
void takeScreenshot (WallpaperEngine::Render::CWallpaper* wp, const std::filesystem::path& filename, FREE_IMAGE_FORMAT format);
|
||||||
|
|
||||||
|
CProject* m_project;
|
||||||
|
CApplicationContext& m_context;
|
||||||
|
CCombinedContainer m_vfs;
|
||||||
|
};
|
||||||
|
}
|
@ -1,5 +1,8 @@
|
|||||||
#include "CCombinedContainer.h"
|
#include "CCombinedContainer.h"
|
||||||
#include "CAssetLoadException.h"
|
#include "CAssetLoadException.h"
|
||||||
|
#include "CPackage.h"
|
||||||
|
#include "CPackageLoadException.h"
|
||||||
|
#include "WallpaperEngine/Logging/CLog.h"
|
||||||
|
|
||||||
using namespace WallpaperEngine::Assets;
|
using namespace WallpaperEngine::Assets;
|
||||||
|
|
||||||
@ -8,6 +11,26 @@ void CCombinedContainer::add (CContainer* container)
|
|||||||
this->m_containers.emplace_back (container);
|
this->m_containers.emplace_back (container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CCombinedContainer::addPkg (const std::filesystem::path& path)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// add the package to the list
|
||||||
|
this->add (new CPackage (path));
|
||||||
|
sLog.out ("Detected ", path.filename (), " file at ", path, ". Adding to list of searchable paths");
|
||||||
|
}
|
||||||
|
catch (CPackageLoadException& ex)
|
||||||
|
{
|
||||||
|
// ignore this error, the package file was not found
|
||||||
|
sLog.out ("No ", path.filename (), " file found at ", path, ". Defaulting to normal folder storage");
|
||||||
|
}
|
||||||
|
catch (std::runtime_error& ex)
|
||||||
|
{
|
||||||
|
// the package was found but there was an error loading it (wrong header or something)
|
||||||
|
sLog.exception ("Failed to load scene.pkg file: ", ex.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const void* CCombinedContainer::readFile (std::string filename, uint32_t* length) const
|
const void* CCombinedContainer::readFile (std::string filename, uint32_t* length) const
|
||||||
{
|
{
|
||||||
for (auto cur : this->m_containers)
|
for (auto cur : this->m_containers)
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
//
|
|
||||||
// Created by almamu on 8/8/21.
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
#include "CContainer.h"
|
#include "CContainer.h"
|
||||||
|
|
||||||
@ -20,6 +17,7 @@ namespace WallpaperEngine::Assets
|
|||||||
* @param container
|
* @param container
|
||||||
*/
|
*/
|
||||||
void add (CContainer* container);
|
void add (CContainer* container);
|
||||||
|
void addPkg (const std::filesystem::path& path);
|
||||||
|
|
||||||
const void* readFile (std::string filename, uint32_t* length) const override;
|
const void* readFile (std::string filename, uint32_t* length) const override;
|
||||||
|
|
||||||
|
@ -716,24 +716,20 @@ void CPass::setupShaderVariables ()
|
|||||||
if (vertexVar == nullptr && pixelVar == nullptr)
|
if (vertexVar == nullptr && pixelVar == nullptr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// if both can be found, ensure they're the correct type
|
|
||||||
/*if (vertexVar != nullptr && pixelVar != nullptr)
|
|
||||||
{
|
|
||||||
if (vertexVar->getType () != pixelVar->getType ())
|
|
||||||
throw std::runtime_error ("Pixel and vertex shader variable types do not match");
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// get one instance of it
|
// get one instance of it
|
||||||
CShaderVariable* var = vertexVar == nullptr ? pixelVar : vertexVar;
|
CShaderVariable* var = vertexVar == nullptr ? pixelVar : vertexVar;
|
||||||
|
|
||||||
// ensure the shader's and the constant are of the same type
|
// ensure the shader's and the constant are of the same type
|
||||||
if (cur.second->getType () != var->getType ())
|
if (cur.second->getType () == var->getType ())
|
||||||
{
|
{
|
||||||
|
this->addUniform (var->getName (), cur.second);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// there's situations where this type mismatch is actually expected
|
// there's situations where this type mismatch is actually expected
|
||||||
// integers and floats are equivalent, this could be detected at load time
|
// 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
|
// but that'd mean to compile the shader in the load, and not on the render stage
|
||||||
// so take into account these conversions here
|
// so take into account these conversions here
|
||||||
|
|
||||||
if (cur.second->is <CShaderConstantFloat> () == true && var->is <CShaderVariableInteger> () == true)
|
if (cur.second->is <CShaderConstantFloat> () == true && var->is <CShaderVariableInteger> () == true)
|
||||||
{
|
{
|
||||||
// create an integer value from a float
|
// create an integer value from a float
|
||||||
@ -769,17 +765,6 @@ void CPass::setupShaderVariables ()
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// now determine the constant's type and register the correct uniform for it
|
|
||||||
if (cur.second->is <CShaderConstantFloat> ())
|
|
||||||
this->addUniform (var->getName (), cur.second->as <CShaderConstantFloat> ()->getValue ());
|
|
||||||
else if (cur.second->is <CShaderConstantInteger> ())
|
|
||||||
this->addUniform (var->getName (), cur.second->as <CShaderConstantInteger> ()->getValue ());
|
|
||||||
else if (cur.second->is <CShaderConstantVector4> ())
|
|
||||||
this->addUniform (var->getName (), cur.second->as <CShaderConstantVector4> ()->getValue ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& cur : this->m_vertShader->getParameters ())
|
for (const auto& cur : this->m_vertShader->getParameters ())
|
||||||
if (this->m_uniforms.find (cur->getName ()) == this->m_uniforms.end ())
|
if (this->m_uniforms.find (cur->getName ()) == this->m_uniforms.end ())
|
||||||
@ -804,6 +789,16 @@ void CPass::addUniform (CShaderVariable* value)
|
|||||||
else if (value->is <CShaderVariableVector4> ())
|
else if (value->is <CShaderVariableVector4> ())
|
||||||
this->addUniform (value->getName (), const_cast <glm::vec4*> (reinterpret_cast <const glm::vec4*> (value->as <CShaderVariableVector4> ()->getValue ())));
|
this->addUniform (value->getName (), const_cast <glm::vec4*> (reinterpret_cast <const glm::vec4*> (value->as <CShaderVariableVector4> ()->getValue ())));
|
||||||
}
|
}
|
||||||
|
void CPass::addUniform (const std::string& name, CShaderConstant* value)
|
||||||
|
{
|
||||||
|
// now determine the constant's type and register the correct uniform for it
|
||||||
|
if (value->is <CShaderConstantFloat> ())
|
||||||
|
this->addUniform (name, value->as <CShaderConstantFloat> ()->getValue ());
|
||||||
|
else if (value->is <CShaderConstantInteger> ())
|
||||||
|
this->addUniform (name, value->as <CShaderConstantInteger> ()->getValue ());
|
||||||
|
else if (value->is <CShaderConstantVector4> ())
|
||||||
|
this->addUniform (name, value->as <CShaderConstantVector4> ()->getValue ());
|
||||||
|
}
|
||||||
|
|
||||||
void CPass::addUniform (const std::string& name, int value)
|
void CPass::addUniform (const std::string& name, int value)
|
||||||
{
|
{
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h"
|
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h"
|
||||||
|
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstant.h"
|
||||||
#include "WallpaperEngine/Render/Objects/Effects/CMaterial.h"
|
#include "WallpaperEngine/Render/Objects/Effects/CMaterial.h"
|
||||||
#include "WallpaperEngine/Render/Shaders/Compiler.h"
|
#include "WallpaperEngine/Render/Shaders/Compiler.h"
|
||||||
#include "WallpaperEngine/Assets/ITexture.h"
|
#include "WallpaperEngine/Assets/ITexture.h"
|
||||||
@ -13,6 +14,7 @@ namespace WallpaperEngine::Render::Objects::Effects
|
|||||||
{
|
{
|
||||||
using namespace WallpaperEngine::Assets;
|
using namespace WallpaperEngine::Assets;
|
||||||
using namespace WallpaperEngine::Render::Shaders::Variables;
|
using namespace WallpaperEngine::Render::Shaders::Variables;
|
||||||
|
using namespace WallpaperEngine::Core::Objects::Effects::Constants;
|
||||||
|
|
||||||
class CMaterial;
|
class CMaterial;
|
||||||
|
|
||||||
@ -90,6 +92,7 @@ namespace WallpaperEngine::Render::Objects::Effects
|
|||||||
void setupAttributes ();
|
void setupAttributes ();
|
||||||
void addAttribute (const std::string& name, GLint type, GLint elements, const GLuint* value);
|
void addAttribute (const std::string& name, GLint type, GLint elements, const GLuint* value);
|
||||||
void addUniform (CShaderVariable* value);
|
void addUniform (CShaderVariable* value);
|
||||||
|
void addUniform (const std::string& name, CShaderConstant* value);
|
||||||
void addUniform (const std::string& name, int value);
|
void addUniform (const std::string& name, int value);
|
||||||
void addUniform (const std::string& name, double value);
|
void addUniform (const std::string& name, double value);
|
||||||
void addUniform (const std::string& name, float value);
|
void addUniform (const std::string& name, float value);
|
||||||
|
Loading…
Reference in New Issue
Block a user