diff --git a/.gitmodules b/.gitmodules index 3140c97..2f3be04 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "src/External/kissfft"] path = src/External/kissfft url = https://github.com/mborgerding/kissfft.git +[submodule "src/External/argparse"] + path = src/External/argparse + url = https://github.com/p-ranav/argparse.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 59d72ef..94b14d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,6 +110,7 @@ add_subdirectory(${CEF_LIBCEF_DLL_WRAPPER_PATH} libcef_dll_wrapper) add_subdirectory(src/External/glslang-WallpaperEngine glslang) add_subdirectory(src/External/SPIRV-Cross-WallpaperEngine spirv-cross) add_subdirectory(src/External/kissfft kissfft) +add_subdirectory(src/External/argparse argparse) # try to enable wayland builds when possible pkg_check_modules(WAYLAND_SUPPORT wayland-cursor wayland-protocols egl wayland-egl) @@ -516,7 +517,8 @@ target_link_libraries (linux-wallpaperengine PUBLIC spirv-cross-glsl glfw libcef_lib - libcef_dll_wrapper) + libcef_dll_wrapper + argparse) COPY_FILES(linux-wallpaperengine "${CEF_BINARY_FILES}" "${CEF_BINARY_DIR}" "${TARGET_OUTPUT_DIRECTORY}") COPY_FILES(linux-wallpaperengine "${CEF_RESOURCE_FILES}" "${CEF_RESOURCE_DIR}" "${TARGET_OUTPUT_DIRECTORY}") diff --git a/src/External/argparse b/src/External/argparse new file mode 160000 index 0000000..d924b84 --- /dev/null +++ b/src/External/argparse @@ -0,0 +1 @@ +Subproject commit d924b84eba1f0f0adf38b20b7b4829f6f65b6570 diff --git a/src/WallpaperEngine/Application/CApplicationContext.cpp b/src/WallpaperEngine/Application/CApplicationContext.cpp index 988d385..6cfaf8c 100644 --- a/src/WallpaperEngine/Application/CApplicationContext.cpp +++ b/src/WallpaperEngine/Application/CApplicationContext.cpp @@ -5,98 +5,289 @@ #include #include -#include #include +#include + #define WORKSHOP_APP_ID 431960 #define APP_DIRECTORY "wallpaper_engine" using namespace WallpaperEngine::Application; -struct option long_options [] = { - {"screen-root", required_argument, nullptr, 'r'}, {"bg", required_argument, nullptr, 'b'}, - {"window", required_argument, nullptr, 'w'}, {"pkg", required_argument, nullptr, 'p'}, - {"dir", required_argument, nullptr, 'd'}, {"silent", no_argument, nullptr, 's'}, - {"volume", required_argument, nullptr, 'v'}, {"help", no_argument, nullptr, 'h'}, - {"fps", required_argument, nullptr, 'f'}, {"assets-dir", required_argument, nullptr, 'a'}, - {"screenshot", required_argument, nullptr, 'c'}, {"list-properties", no_argument, nullptr, 'l'}, - {"set-property", required_argument, nullptr, 'o'}, {"noautomute", no_argument, nullptr, 'm'}, - {"no-audio-processing", no_argument, nullptr, 'g'}, {"no-fullscreen-pause", no_argument, nullptr, 'n'}, - {"disable-mouse", no_argument, nullptr, 'e'}, {"scaling", required_argument, nullptr, 't'}, - {"clamping", required_argument, nullptr, 't'}, {"screenshot-delay", required_argument, nullptr, 'y'}, - {"dump-structure", no_argument, nullptr, 'z'}, {nullptr, 0, nullptr, 0} -}; - -/* std::hash::operator() isn't constexpr, so it can't be used to get hash values as compile-time constants - * So here is customHash. It skips all spaces, so hashes for " find " and "fi nd" are the same - * Basicly got it from here: https://stackoverflow.com/questions/8317508/hash-function-for-a-string - */ -constexpr size_t customHash (const char* str) { - constexpr size_t A = 54059; /* a prime */ - constexpr size_t B = 76963; /* another prime */ - constexpr size_t C = 86969; /* yet another prime */ - constexpr size_t FIRSTH = 37; /* also prime */ - size_t hash = FIRSTH; - while (*str) { - if (*str != ' ') // Skip spaces - hash = (hash * A) ^ (*str * B); - ++str; - } - return hash % C; -} - -std::string stringPathFixes (const std::string& s) { - if (s.empty ()) - 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 str; -} - CApplicationContext::CApplicationContext (int argc, char* argv []) : m_argc (argc), - m_argv (argv) { - // setup structs with sane default values for now - this->settings = { - .general = - { - .onlyListProperties = false, - .dumpStructure = false, - .assets = "", - .defaultBackground = "", - .screenBackgrounds = {}, - .properties = {}, - }, - .render = - { - .mode = NORMAL_WINDOW, - .maximumFPS = 30, - .pauseOnFullscreen = true, - .window = - { - .geometry = {}, - .clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs, - .scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::DefaultUVs, - }, - }, - .audio = {.enabled = true, .volume = 15, .automute = true, .audioprocessing = true}, - .mouse = - { - .enabled = true, - }, - .screenshot = - { - .take = false, - .path = "", - }, - }; + m_argv (argv), + settings ({ + .general = { + .onlyListProperties = false, + .dumpStructure = false, + .assets = "", + .defaultBackground = "", + .screenBackgrounds = {}, + .properties = {}, + .screenScalings = {}, + .screenClamps = {}, + }, + .render = { + .mode = NORMAL_WINDOW, + .maximumFPS = 30, + .pauseOnFullscreen = true, + .window = + { + .geometry = {}, + .clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs, + .scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::DefaultUVs, + }, + }, + .audio = { + .enabled = true, + .volume = 15, + .automute = true, + .audioprocessing = true, + }, + .mouse = { + .enabled = true, + }, + .screenshot = { + .take = false, + .delay = 5, + .path = "", + }, + }) { + std::string lastScreen; - // use std::out on this in case logging is disabled, this way it's easy to look at what is running + argparse::ArgumentParser program ("linux-wallpaperengine", "0.0", argparse::default_arguments::help); + + auto& backgroundGroup = program.add_group ("Background options"); + auto& backgroundMode = backgroundGroup.add_mutually_exclusive_group (false); + + backgroundGroup.add_argument ("background id") + .help ("The background to use as default for screens with no background specified") + .action([this](const std::string& value) -> void { + this->settings.general.defaultBackground = translateBackground (value); + }); + + backgroundMode.add_argument ("-w", "--window") + .help ("Window geometry to use for the given screen") + .action ([this](const std::string& value) -> void { + if (this->settings.render.mode == DESKTOP_BACKGROUND) { + sLog.exception ("Cannot run in both background and window mode"); + } + if (this->settings.render.mode == EXPLICIT_WINDOW) { + sLog.exception ("Only one window at a time can be specified in explicit window mode"); + } + + this->settings.render.mode = EXPLICIT_WINDOW; + + if (value.empty ()) { + sLog.exception ("Window geometry cannot be empty"); + } + + const char* str = value.c_str (); + const char* delim1 = strchr (str, 'x'); + const char* delim2 = strchr (str, 'x'); + const char* delim3 = strchr (str, 'x'); + + if (delim1 == nullptr || delim2 == nullptr || delim3 == nullptr) { + sLog.exception ("Window geometry must be in the format: XxYxWxH"); + } + + this->settings.render.window.geometry.x = strtol(str, nullptr, 10); + this->settings.render.window.geometry.y = strtol (delim1 + 1, nullptr, 10); + this->settings.render.window.geometry.z = strtol (delim2 + 1, nullptr, 10); + this->settings.render.window.geometry.w = strtol (delim3 + 1, nullptr, 10); + + }) + .append (); + backgroundMode.add_argument ("-r", "--screen-root") + .help ("The screen the following settings will have an effect on") + .action([this, &lastScreen](const std::string& value) -> void { + if (this->settings.general.screenBackgrounds.find (value) != this->settings.general.screenBackgrounds.end ()) { + sLog.exception ("Cannot specify the same screen more than once: ", value); + } + if (this->settings.render.mode == EXPLICIT_WINDOW) { + sLog.exception ("Cannot run in both background and window mode"); + } + + this->settings.render.mode = DESKTOP_BACKGROUND; + lastScreen = value; + this->settings.general.screenBackgrounds [lastScreen] = ""; + this->settings.general.screenScalings [lastScreen] = this->settings.render.window.scalingMode; + this->settings.general.screenClamps [lastScreen] = this->settings.render.window.clamp; + }) + .append (); + backgroundGroup.add_argument ("-b", "--bg") + .help ("After --screen-root, specifies the background to use for the given screen") + .action ([this, &lastScreen](const std::string& value) -> void { + this->settings.general.screenBackgrounds [lastScreen] = translateBackground (value); + // set the default background to the last one used + this->settings.general.defaultBackground = translateBackground (value); + }) + .append (); + backgroundGroup.add_argument ("--scaling") + .help ("Scaling mode to use when rendering the background, this applies to the previous --window or --screen-root output, or the default background if no other background is specified") + .choices ("stretch", "fit", "fill", "default") + .action([this, &lastScreen](const std::string& value) -> void { + WallpaperEngine::Render::CWallpaperState::TextureUVsScaling mode; + + if (value == "stretch") { + mode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::StretchUVs; + } else if (value == "fit") { + mode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::ZoomFitUVs; + } else if (value == "fill") { + mode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::ZoomFillUVs; + } else if (value == "default") { + mode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::DefaultUVs; + } else { + sLog.exception ("Invalid scaling mode: ", value); + } + + if (this->settings.render.mode == DESKTOP_BACKGROUND) { + this->settings.general.screenScalings [lastScreen] = mode; + } else { + this->settings.render.window.scalingMode = mode; + } + }) + .append (); + backgroundGroup.add_argument ("--clamp") + .help ("Clamp mode to use when rendering the background, this applies to the previous --window or --screen-root output, or the default background if no other background is specified") + .choices("clamp", "border", "repeat") + .action([this, &lastScreen](const std::string& value) -> void { + WallpaperEngine::Assets::ITexture::TextureFlags flags; + + if (value == "clamp") { + flags = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs; + } else if (value == "border") { + flags = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVsBorder; + } else if (value == "repeat") { + flags = WallpaperEngine::Assets::ITexture::TextureFlags::NoFlags; + } else { + sLog.exception ("Invalid clamp mode: ", value); + } + + if (this->settings.render.mode == DESKTOP_BACKGROUND) { + this->settings.general.screenClamps [lastScreen] = flags; + } else { + this->settings.render.window.clamp = flags; + } + }); + + auto& performanceGroup = program.add_group ("Performance options"); + + performanceGroup.add_argument ("-f", "--fps") + .help ("Limits the FPS to the given number, useful to keep battery consumption low") + .default_value (30) + .scan<'i', int> (); + + performanceGroup.add_argument ("--no-fullscreen-pause") + .help ("Prevents the background pausing when an app is fullscreen") + .default_value (true) + .implicit_value (false) + .store_into (this->settings.render.pauseOnFullscreen); + + auto& audioGroup = program.add_group ("Sound settings"); + auto& audioSettingsGroup = audioGroup.add_mutually_exclusive_group (false); + + audioSettingsGroup.add_argument ("-v", "--volume") + .help ("Volume for all the sounds in the background") + .default_value (15) + .store_into (this->settings.audio.volume); + + audioSettingsGroup.add_argument ("-s", "--silent") + .help ("Mutes all the sound the wallpaper might produce") + .default_value (true) + .implicit_value (false) + .store_into (this->settings.audio.enabled); + + audioGroup.add_argument ("--noautomute") + .help ("Disables the automute when an app is playing sound") + .default_value (true) + .implicit_value (false) + .store_into (this->settings.audio.automute); + + audioGroup.add_argument ("--no-audio-processing") + .help ("Disables audio processing for backgrounds") + .default_value (true) + .implicit_value (false) + .store_into (this->settings.audio.audioprocessing); + + auto& screenshotGroup = program.add_group ("Screenshot options"); + + screenshotGroup.add_argument ("--screenshot") + .help ("Takes a screenshot of the background for it's use with tools like PyWAL") + .default_value ("") + .action ([this](const std::string& value) -> void { + this->settings.screenshot.take = true; + this->settings.screenshot.path = value; + }); + + screenshotGroup.add_argument ("--screenshot-delay") + .help ("Frames to wait before taking the screenshot") + .default_value (5) + .store_into (this->settings.screenshot.delay); + + auto& contentGroup = program.add_group ("Content options"); + + contentGroup.add_argument ("--assets-dir") + .help ("Folder where the assets are stored") + .default_value ("") + .action ([this](const std::string& value) -> void { + this->settings.general.assets = value; + }); + + auto& configurationGroup = program.add_group ("Wallpaper configuration options"); + + configurationGroup.add_argument ("--disable-mouse") + .help ("Disables mouse interaction with the backgrounds") + .default_value (true) + .implicit_value (false) + .store_into (this->settings.mouse.enabled); + + configurationGroup.add_argument ("-l", "--list-properties") + .help ("List all the available properties and their configuration") + .default_value (false) + .implicit_value (true) + .store_into (this->settings.general.onlyListProperties); + + configurationGroup.add_argument ("--set-property", "--property") + .help ("Overrides the default value of the given property") + .action([this](const std::string& value) -> void { + const std::string::size_type equals = value.find ('='); + + // properties without value are treated as booleans for now + if (equals == std::string::npos) + this->settings.general.properties [value] = "1"; + else + this->settings.general.properties [value.substr (0, equals)] = value.substr (equals + 1); + }); + + auto& debuggingGroup = program.add_group ("Debugging options"); + + debuggingGroup.add_argument ("-z", "--dump-structure") + .help ("Dumps the structure of the backgrounds") + .default_value (false) + .implicit_value (true) + .store_into (this->settings.general.dumpStructure); + + program.add_epilog ( + "Usage examples:\n" + " linux-wallpaperengine --screen-root HDMI-1 --bg 2317494988 --scaling fill --clamp border\n" + " Runs the background 2317494988 on screen HDMI-1, scaling it to fill the screen and clamping the UVs to the border\n\n" + " linux-wallpaperengine 2317494988\n" + " Previews the background 2317494988 on a window\n\n" + " linux-wallpaperengine --screen-root HDMI-1 --bg 2317494988 --screen-root HDMI-2 --bg 1108150151\n" + " Runs two backgrounds on two screens, one on HDMI-1 and the other on HDMI-2\n\n" + " linux-wallpaperengine --screen-root HDMI-1 --screen-root HDMI-2 2317494988\n" + " Runs the background 2317494988 on two screens, one on HDMI-1 and the other on HDMI-2\n\n" + ); + + program.parse_args (argc, argv); + sLog.out(program.help ().str ()); + + this->settings.audio.volume = std::max(0, std::min (this->settings.audio.volume, 128)); + this->settings.screenshot.delay = std::max (0, std::min (this->settings.screenshot.delay, 5)); + + // use std::cout on this in case logging is disabled, this way it's easy to look at what is running std::stringbuf buffer; std::ostream bufferStream (&buffer); @@ -108,157 +299,6 @@ CApplicationContext::CApplicationContext (int argc, char* argv []) : } std::cout << buffer.str() << std::endl; - - int c; - - std::string lastScreen; - - while ((c = getopt_long (argc, argv, "b:r:p:d:shf:a:w:mnt:", long_options, nullptr)) != -1) { - switch (c) { - case 'z': this->settings.general.dumpStructure = true; break; - case 'n': this->settings.render.pauseOnFullscreen = false; break; - - case 'b': - if (lastScreen.empty ()) - sLog.exception ("--bg has to go after a --screen-root argument"); - - // no need to check for previous screen being in the list, as it's the only way for this variable - // to have any value - this->settings.general.screenBackgrounds [lastScreen] = translateBackground (optarg); - this->settings.general.screenScalings [lastScreen] = this->settings.render.window.scalingMode; - - // update default background if not set - if (this->settings.general.defaultBackground.empty()) { - this->settings.general.defaultBackground = translateBackground (optarg); - } - break; - - case 'o': { - std::string value = optarg; - const std::string::size_type equals = value.find ('='); - - // properties without value are treated as booleans for now - if (equals == std::string::npos) - this->settings.general.properties [value] = "1"; - else - this->settings.general.properties [value.substr (0, equals)] = value.substr (equals + 1); - } break; - - case 'l': this->settings.general.onlyListProperties = true; break; - - case 'r': - if (this->settings.general.screenBackgrounds.find (optarg) != - this->settings.general.screenBackgrounds.end ()) - sLog.exception ("Cannot specify the same screen more than once: ", optarg); - if (this->settings.render.mode == EXPLICIT_WINDOW) - sLog.exception ("Cannot run in both background and window mode"); - - this->settings.render.mode = DESKTOP_BACKGROUND; - lastScreen = optarg; - this->settings.general.screenBackgrounds [lastScreen] = ""; - this->settings.general.screenScalings [lastScreen] = this->settings.render.window.scalingMode; - break; - - case 'w': - if (this->settings.render.mode == DESKTOP_BACKGROUND) - sLog.exception ("Cannot run in both background and window mode"); - - if (optarg != nullptr) { - this->settings.render.mode = EXPLICIT_WINDOW; - // read window geometry - char* pos = optarg; - - if (pos != nullptr) - this->settings.render.window.geometry.x = atoi (pos); - if ((pos = strchr (pos, 'x')) != nullptr) - this->settings.render.window.geometry.y = atoi (pos + 1); - if ((pos = strchr (pos + 1, 'x')) != nullptr) - this->settings.render.window.geometry.z = atoi (pos + 1); - if ((pos = strchr (pos + 1, 'x')) != nullptr) - this->settings.render.window.geometry.w = atoi (pos + 1); - } - break; - - case 'p': - case 'd': - sLog.error ("--dir/--pkg is deprecated and not used anymore"); - this->settings.general.defaultBackground = translateBackground (stringPathFixes (optarg)); - break; - - case 's': this->settings.audio.enabled = false; break; - - case 'h': - printHelp (argv [0]); - std::exit (0); - break; - - case 'f': this->settings.render.maximumFPS = atoi (optarg); break; - - case 'a': this->settings.general.assets = stringPathFixes (optarg); break; - - case 'v': this->settings.audio.volume = std::max (atoi (optarg), 128); break; - - case 'c': - this->settings.screenshot.take = true; - this->settings.screenshot.path = stringPathFixes (optarg); - break; - case 'y': this->settings.screenshot.delay = std::min (atoi (optarg), 5); break; - - case 'm': this->settings.audio.automute = false; break; - - case 'g': this->settings.audio.audioprocessing = false; break; - - case 'e': this->settings.mouse.enabled = false; break; - - case 't': { - size_t hash = customHash (optarg); - // Use a switch statement with the hash - switch (hash) { - // --scale options - case customHash ("stretch"): - this->settings.render.window.scalingMode = - WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::StretchUVs; - break; - case customHash ("fit"): - this->settings.render.window.scalingMode = - WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::ZoomFitUVs; - break; - case customHash ("fill"): - this->settings.render.window.scalingMode = - WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::ZoomFillUVs; - break; - case customHash ("default"): - this->settings.render.window.scalingMode = - WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::DefaultUVs; - break; - // --clamp options - case customHash ("clamp"): - this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs; - break; - case customHash ("border"): - this->settings.render.window.clamp = - WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVsBorder; - break; - case customHash ("repeat"): - this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::NoFlags; - break; - default: - sLog.error ("Wrong argument:"); - sLog.error (optarg); - sLog.exception ("Wrong argument provided for --scale or --clamp option."); - break; - } - } break; - default: sLog.out ("Default on path parsing: ", optarg); break; - } - } - - if (this->settings.general.defaultBackground.empty ()) { - if (optind < argc && strlen (argv [optind]) > 0) { - this->settings.general.defaultBackground = translateBackground (argv [optind]); - } - } - // perform some extra validation on the inputs this->validateAssets (); this->validateScreenshot (); @@ -267,6 +307,7 @@ CApplicationContext::CApplicationContext (int argc, char* argv []) : this->state.general.keepRunning = true; this->state.audio.enabled = this->settings.audio.enabled; this->state.audio.volume = this->settings.audio.volume; + this->state.mouse.enabled = this->settings.mouse.enabled; } int CApplicationContext::getArgc () const { @@ -311,38 +352,3 @@ void CApplicationContext::validateScreenshot () const { if (extension != ".bmp" && extension != ".png" && extension != ".jpeg" && extension != ".jpg") 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 \t\t\tSets the volume for all the sounds in the background"); - sLog.out ("\t--noautomute\t\t\t\tDisables the automute when an app is playing sound"); - sLog.out ("\t--no-audio-processing\t\t\t\tDisables audio processing for backgrounds"); - sLog.out ("\t--screen-root \tDisplay as screen's background"); - sLog.out ( - "\t--window \tRuns in window mode, geometry has to be XxYxWxH and sets the position and size of the window"); - sLog.out ("\t--fps \t\t\tLimits the FPS to the given number, useful to keep battery consumption low"); - sLog.out ("\t--assets-dir \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 \tOverrides the default value of the given property"); - sLog.out ("\t--no-fullscreen-pause\tPrevents the background pausing when an app is fullscreen"); - sLog.out ("\t--disable-mouse\tDisables mouse interactions"); - sLog.out ( - "\t--bg \tAfter --screen-root uses the specified background only on that screen"); - sLog.out ( - "\t--scaling \t Scaling mode for wallpaper. Can be stretch, fit, fill, default. Must be used before wallpaper provided.\n\ - \t\t For default wallpaper last specified value will be used.\n\ - \t\t Example: ./wallengine --scaling stretch --screen-root eDP-1 --bg 2667198601 --scaling fill --screen-root eDP-2 2667198602"); - sLog.out ( - "\t--clamping \t Clamping mode for all wallpapers. Can be clamp, border, repeat. Enables GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, GL_REPEAT accordingly. Default is clamp."); - sLog.out ("\t--screenshot-delay \t\tFrames to wait until the screenshot is taken"); - sLog.out ("\t--dump-structure\t\t\tDumps the structure of the wallpaper"); - sLog.out ("\t--help\t\t\t\t\tPrints this help"); -} diff --git a/src/WallpaperEngine/Application/CApplicationContext.h b/src/WallpaperEngine/Application/CApplicationContext.h index 6bc0840..54cdf6a 100644 --- a/src/WallpaperEngine/Application/CApplicationContext.h +++ b/src/WallpaperEngine/Application/CApplicationContext.h @@ -48,6 +48,8 @@ class CApplicationContext { std::map properties; /** The scaling mode for different screens */ std::map screenScalings; + /** The clamping mode for different screens */ + std::map screenClamps; } general; /** @@ -98,7 +100,7 @@ class CApplicationContext { /** If an screenshot should be taken */ bool take; /** The frames to wait until the screenshot is taken */ - uint32_t delay; + int delay; /** The path to where the screenshot must be saved */ std::filesystem::path path; } screenshot; @@ -132,10 +134,5 @@ class CApplicationContext { * @return */ static std::filesystem::path translateBackground (const std::string& bgIdOrPath); - - /** - * Prints the normal help message - */ - static void printHelp (const char* route); }; } // namespace WallpaperEngine::Application \ No newline at end of file diff --git a/src/WallpaperEngine/Application/CWallpaperApplication.cpp b/src/WallpaperEngine/Application/CWallpaperApplication.cpp index ff45582..4ee7b63 100644 --- a/src/WallpaperEngine/Application/CWallpaperApplication.cpp +++ b/src/WallpaperEngine/Application/CWallpaperApplication.cpp @@ -436,7 +436,8 @@ void CWallpaperApplication::prepareOutputs () { background, WallpaperEngine::Render::CWallpaper::fromWallpaper ( info->getWallpaper (), *m_renderContext, *m_audioContext, *m_browserContext, - this->m_context.settings.general.screenScalings [background] + this->m_context.settings.general.screenScalings [background], + this->m_context.settings.general.screenClamps [background] ) ); } diff --git a/src/WallpaperEngine/Render/CWallpaper.cpp b/src/WallpaperEngine/Render/CWallpaper.cpp index 172a574..a7084a1 100644 --- a/src/WallpaperEngine/Render/CWallpaper.cpp +++ b/src/WallpaperEngine/Render/CWallpaper.cpp @@ -10,8 +10,11 @@ using namespace WallpaperEngine::Render; -CWallpaper::CWallpaper (const Core::CWallpaper* wallpaperData, std::string type, CRenderContext& context, - CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode) : +CWallpaper::CWallpaper ( + const Core::CWallpaper* wallpaperData, std::string type, CRenderContext& context,CAudioContext& audioContext, + const CWallpaperState::TextureUVsScaling& scalingMode, + const WallpaperEngine::Assets::ITexture::TextureFlags& clampMode +) : CContextAware (context), m_wallpaperData (wallpaperData), m_sceneFBO (nullptr), @@ -25,7 +28,7 @@ CWallpaper::CWallpaper (const Core::CWallpaper* wallpaperData, std::string type, m_destFramebuffer (GL_NONE), m_type (std::move (type)), m_audioContext (audioContext), - m_state (scalingMode) { + m_state (scalingMode, clampMode) { // generate the VAO to stop opengl from complaining glGenVertexArrays (1, &this->m_vaoBuffer); glBindVertexArray (this->m_vaoBuffer); @@ -237,11 +240,12 @@ void CWallpaper::setPause (bool newState) {} void CWallpaper::setupFramebuffers () { const uint32_t width = this->getWidth (); const uint32_t height = this->getHeight (); - const ITexture::TextureFlags clamp = this->getContext ().getApp ().getContext ().settings.render.window.clamp; + const ITexture::TextureFlags clamp = this->m_state.getClampingMode (); // create framebuffer for the scene - this->m_sceneFBO = this->createFBO ("_rt_FullFrameBuffer", ITexture::TextureFormat::ARGB8888, clamp, 1.0, width, - height, width, height); + this->m_sceneFBO = this->createFBO ( + "_rt_FullFrameBuffer", ITexture::TextureFormat::ARGB8888, clamp, 1.0, width, + height, width, height); this->aliasFBO ("_rt_MipMappedFrameBuffer", this->m_sceneFBO); } @@ -281,16 +285,20 @@ CFBO* CWallpaper::getFBO () const { return this->m_sceneFBO; } -CWallpaper* CWallpaper::fromWallpaper (const Core::CWallpaper* wallpaper, CRenderContext& context, - CAudioContext& audioContext, WebBrowser::CWebBrowserContext& browserContext, - const CWallpaperState::TextureUVsScaling& scalingMode) { - if (wallpaper->is ()) - return new WallpaperEngine::Render::Wallpapers::CScene (wallpaper->as (), context, audioContext, scalingMode); - if (wallpaper->is ()) - return new WallpaperEngine::Render::Wallpapers::CVideo (wallpaper->as (), context, audioContext, scalingMode); - else if (wallpaper->is ()) - return new WallpaperEngine::Render::Wallpapers::CWeb (wallpaper->as (), context, audioContext, browserContext, - scalingMode); - else +CWallpaper* CWallpaper::fromWallpaper ( + const Core::CWallpaper* wallpaper, CRenderContext& context, CAudioContext& audioContext, + WebBrowser::CWebBrowserContext& browserContext, const CWallpaperState::TextureUVsScaling& scalingMode, + const WallpaperEngine::Assets::ITexture::TextureFlags& clampMode +) { + if (wallpaper->is ()) { + return new WallpaperEngine::Render::Wallpapers::CScene ( + wallpaper->as (), context, audioContext, scalingMode, clampMode); + } else if (wallpaper->is ()) { + return new WallpaperEngine::Render::Wallpapers::CVideo ( + wallpaper->as (), context, audioContext, scalingMode, clampMode); + } else if (wallpaper->is ()) { + return new WallpaperEngine::Render::Wallpapers::CWeb ( + wallpaper->as (), context, audioContext, browserContext, scalingMode, clampMode); + } else sLog.exception ("Unsupported wallpaper type"); } diff --git a/src/WallpaperEngine/Render/CWallpaper.h b/src/WallpaperEngine/Render/CWallpaper.h index 96440b0..ba3cedc 100644 --- a/src/WallpaperEngine/Render/CWallpaper.h +++ b/src/WallpaperEngine/Render/CWallpaper.h @@ -30,17 +30,17 @@ class CContextAware; class CWallpaper : public Helpers::CContextAware { public: - template const T* as () const { + template [[nodiscard]]const T* as () const { assert (is ()); return reinterpret_cast (this); } - template T* as () { + template [[nodiscard]] T* as () { assert (is ()); return reinterpret_cast (this); } - template bool is () const { + template [[nodiscard]] bool is () const { return this->m_type == T::Type; } @@ -87,8 +87,9 @@ class CWallpaper : public Helpers::CContextAware { * @param textureHeight * @return */ - CFBO* createFBO (const std::string& name, ITexture::TextureFormat format, ITexture::TextureFlags flags, float scale, - uint32_t realWidth, uint32_t realHeight, uint32_t textureWidth, uint32_t textureHeight); + CFBO* createFBO ( + const std::string& name, ITexture::TextureFormat format, ITexture::TextureFlags flags, float scale, + uint32_t realWidth, uint32_t realHeight, uint32_t textureWidth, uint32_t textureHeight); /** * Creates an alias of an existing fbo @@ -146,13 +147,16 @@ class CWallpaper : public Helpers::CContextAware { * * @return */ - static CWallpaper* fromWallpaper (const Core::CWallpaper* wallpaper, CRenderContext& context, CAudioContext& audioContext, - WebBrowser::CWebBrowserContext& browserContext, - const CWallpaperState::TextureUVsScaling& scalingMode); + static CWallpaper* fromWallpaper ( + const Core::CWallpaper* wallpaper, CRenderContext& context, CAudioContext& audioContext, + WebBrowser::CWebBrowserContext& browserContext, const CWallpaperState::TextureUVsScaling& scalingMode, + const WallpaperEngine::Assets::ITexture::TextureFlags& clampMode); protected: - CWallpaper (const Core::CWallpaper* wallpaperData, std::string type, CRenderContext& context, CAudioContext& audioContext, - const CWallpaperState::TextureUVsScaling& scalingMode); + CWallpaper ( + const Core::CWallpaper* wallpaperData, std::string type, CRenderContext& context, CAudioContext& audioContext, + const CWallpaperState::TextureUVsScaling& scalingMode, + const WallpaperEngine::Assets::ITexture::TextureFlags& clampMode); /** * Renders a frame of the wallpaper diff --git a/src/WallpaperEngine/Render/CWallpaperState.cpp b/src/WallpaperEngine/Render/CWallpaperState.cpp index c22572c..fd21f3a 100644 --- a/src/WallpaperEngine/Render/CWallpaperState.cpp +++ b/src/WallpaperEngine/Render/CWallpaperState.cpp @@ -1,9 +1,22 @@ #include "CWallpaperState.h" +#include "WallpaperEngine/Assets/ITexture.h" #include "WallpaperEngine/Logging/CLog.h" #include using namespace WallpaperEngine::Render; +CWallpaperState::CWallpaperState ( + const TextureUVsScaling& textureUVsMode, const WallpaperEngine::Assets::ITexture::TextureFlags& clampMode) : + m_textureUVsMode (textureUVsMode) {} + +bool CWallpaperState::hasChanged ( + const glm::ivec4& viewport, const bool& vflip, const int& projectionWidth,const int& projectionHeight +) const { + return this->viewport.width != viewport.z || this->viewport.height != viewport.w || + this->projection.width != projectionWidth || this->projection.height != projectionHeight || + this->vflip != vflip; +} + // Reset UVs to 0/1 values void CWallpaperState::resetUVs () { this->UVs.ustart = 0; @@ -123,6 +136,34 @@ template void CWallpaperState::updateText This message is for developers, if you are just user it's a bug."); } +CWallpaperState::TextureUVsScaling CWallpaperState::getTextureUVsScaling () const { + return this->m_textureUVsMode; +} + +WallpaperEngine::Assets::ITexture::TextureFlags CWallpaperState::getClampingMode () const { + return this->m_clampingMode; +} + +void CWallpaperState::setTextureUVsStrategy (CWallpaperState::TextureUVsScaling strategy) { + this->m_textureUVsMode = strategy; +} + +int CWallpaperState::getViewportWidth () const { + return this->viewport.width; +} + +int CWallpaperState::getViewportHeight () const { + return this->viewport.height; +} + +int CWallpaperState::getProjectionWidth () const { + return this->projection.width; +} + +int CWallpaperState::getProjectionHeight () const { + return this->projection.height; +} + void CWallpaperState::updateState (const glm::ivec4& viewport, const bool& vflip, const int& projectionWidth, const int& projectionHeight) { this->viewport.width = viewport.z; diff --git a/src/WallpaperEngine/Render/CWallpaperState.h b/src/WallpaperEngine/Render/CWallpaperState.h index 86b8cb3..59ceb33 100644 --- a/src/WallpaperEngine/Render/CWallpaperState.h +++ b/src/WallpaperEngine/Render/CWallpaperState.h @@ -4,6 +4,8 @@ #include #include +#include "WallpaperEngine/Assets/ITexture.h" + namespace WallpaperEngine::Render { /** * Represents current wallpaper state @@ -18,66 +20,93 @@ class CWallpaperState { StretchUVs, }; - CWallpaperState (const TextureUVsScaling& textureUVsMode) : m_textureUVsMode (textureUVsMode) {}; + CWallpaperState ( + const TextureUVsScaling& textureUVsMode, const WallpaperEngine::Assets::ITexture::TextureFlags& clampMode); - // Compares saved state values with passed arguments - bool hasChanged (const glm::ivec4& viewport, const bool& vflip, const int& projectionWidth, - const int& projectionHeight) const { - return this->viewport.width != viewport.z || this->viewport.height != viewport.w || - this->projection.width != projectionWidth || this->projection.height != projectionHeight || - this->vflip != vflip; - } + /** + * Checks if any of the given values has changed + * @param viewport + * @param vflip + * @param projectionWidth + * @param projectionHeight + * @return + */ + [[nodiscard]] bool hasChanged ( + const glm::ivec4& viewport, const bool& vflip, const int& projectionWidth, const int& projectionHeight) const; - // Reset UVs to 0/1 values + /** + * Resets UVs to 0/1 values. + */ void resetUVs (); - // Update Us coordinates for current viewport and projection + /** + * Updates UVs coordinates for current viewport and projection + * + * @param projectionWidth + * @param projectionHeight + */ void updateUs (const int& projectionWidth, const int& projectionHeight); - // Update Vs coordinates for current viewport and projection + /** + * Updates Vs coordinates for current viewport and projection + * + * @param projectionWidth + * @param projectionHeight + */ void updateVs (const int& projectionWidth, const int& projectionHeight); - // Get texture UV coordinates - auto getTextureUVs () const { + /** + * @return Texture UV coordinates for current viewport and projection + */ + [[nodiscard]] auto getTextureUVs () const { return UVs; }; - // Set texture UV coordinates according to texture scaling mode + /** + * Updates UVs coordinates for current viewport and projection + */ template void updateTextureUVs (); // Updates state with provided values void updateState (const glm::ivec4& viewport, const bool& vflip, const int& projectionWidth, const int& projectionHeight); - // @return The texture scaling mode - TextureUVsScaling getTextureUVsScaling () const { - return m_textureUVsMode; - }; + /** + * @return The texture scaling mode + */ + [[nodiscard]] TextureUVsScaling getTextureUVsScaling () const; - // Set texture scaling mode - void setTextureUVsStrategy (const TextureUVsScaling strategy) { - m_textureUVsMode = strategy; - }; + /** + * @return The texture clamping mode. + */ + [[nodiscard]] WallpaperEngine::Assets::ITexture::TextureFlags getClampingMode () const; - // @return The width of viewport - int getViewportWidth () const { - return viewport.width; - }; + /** + * Sets the texture scaling mode + * + * @param strategy + */ + void setTextureUVsStrategy (TextureUVsScaling strategy); - // @return The height of viewport - int getViewportHeight () const { - return viewport.height; - }; + /** + * @return The width of viewport + */ + [[nodiscard]] int getViewportWidth () const; - // @return The width of viewport - int getProjectionWidth () const { - return projection.width; - }; + /** + * @return The height of viewport + */ + [[nodiscard]] int getViewportHeight () const; - // @return The height of viewport - int getProjectionHeight () const { - return projection.height; - }; + /** + * @return The width of the projection + */ + [[nodiscard]] int getProjectionWidth () const; + + /** + * @return The height of the projection + */ + [[nodiscard]] int getProjectionHeight () const; private: // Cached UVs value for texture coordinates. No need to recalculate if viewport and projection haven't changed. @@ -105,5 +134,6 @@ class CWallpaperState { // Texture scaling mode TextureUVsScaling m_textureUVsMode = TextureUVsScaling::DefaultUVs; + WallpaperEngine::Assets::ITexture::TextureFlags m_clampingMode = WallpaperEngine::Assets::ITexture::TextureFlags::NoFlags; }; } // namespace WallpaperEngine::Render \ No newline at end of file diff --git a/src/WallpaperEngine/Render/Wallpapers/CScene.cpp b/src/WallpaperEngine/Render/Wallpapers/CScene.cpp index 399e86a..652fff2 100644 --- a/src/WallpaperEngine/Render/Wallpapers/CScene.cpp +++ b/src/WallpaperEngine/Render/Wallpapers/CScene.cpp @@ -16,9 +16,12 @@ using namespace WallpaperEngine; using namespace WallpaperEngine::Render; using namespace WallpaperEngine::Render::Wallpapers; -CScene::CScene (const Core::Wallpapers::CScene* scene, CRenderContext& context, CAudioContext& audioContext, - const CWallpaperState::TextureUVsScaling& scalingMode) : - CWallpaper (scene, Type, context, audioContext, scalingMode), +CScene::CScene ( + const Core::Wallpapers::CScene* scene, CRenderContext& context, CAudioContext& audioContext, + const CWallpaperState::TextureUVsScaling& scalingMode, + const WallpaperEngine::Assets::ITexture::TextureFlags& clampMode +) : + CWallpaper (scene, Type, context, audioContext, scalingMode, clampMode), m_mousePosition (), m_mousePositionLast (), m_parallaxDisplacement () { diff --git a/src/WallpaperEngine/Render/Wallpapers/CScene.h b/src/WallpaperEngine/Render/Wallpapers/CScene.h index 84fef29..0f25f72 100644 --- a/src/WallpaperEngine/Render/Wallpapers/CScene.h +++ b/src/WallpaperEngine/Render/Wallpapers/CScene.h @@ -14,8 +14,10 @@ class CObject; namespace WallpaperEngine::Render::Wallpapers { class CScene final : public CWallpaper { public: - CScene (const Core::Wallpapers::CScene* scene, CRenderContext& context, CAudioContext& audioContext, - const CWallpaperState::TextureUVsScaling& scalingMode); + CScene ( + const Core::Wallpapers::CScene* scene, CRenderContext& context, CAudioContext& audioContext, + const CWallpaperState::TextureUVsScaling& scalingMode, + const WallpaperEngine::Assets::ITexture::TextureFlags& clampMode); CCamera* getCamera () const; diff --git a/src/WallpaperEngine/Render/Wallpapers/CVideo.cpp b/src/WallpaperEngine/Render/Wallpapers/CVideo.cpp index a427891..963e519 100644 --- a/src/WallpaperEngine/Render/Wallpapers/CVideo.cpp +++ b/src/WallpaperEngine/Render/Wallpapers/CVideo.cpp @@ -11,9 +11,12 @@ void* get_proc_address (void* ctx, const char* name) { return static_cast (ctx)->getContext ().getDriver ().getProcAddress (name); } -CVideo::CVideo (const Core::Wallpapers::CVideo* video, CRenderContext& context, CAudioContext& audioContext, - const CWallpaperState::TextureUVsScaling& scalingMode) : - CWallpaper (video, Type, context, audioContext, scalingMode), +CVideo::CVideo ( + const Core::Wallpapers::CVideo* video, CRenderContext& context, CAudioContext& audioContext, + const CWallpaperState::TextureUVsScaling& scalingMode, + const WallpaperEngine::Assets::ITexture::TextureFlags& clampMode +) : + CWallpaper (video, Type, context, audioContext, scalingMode, clampMode), m_mpvGl (nullptr), m_paused (false), m_width (16), diff --git a/src/WallpaperEngine/Render/Wallpapers/CVideo.h b/src/WallpaperEngine/Render/Wallpapers/CVideo.h index 2dd4442..0a44271 100644 --- a/src/WallpaperEngine/Render/Wallpapers/CVideo.h +++ b/src/WallpaperEngine/Render/Wallpapers/CVideo.h @@ -10,8 +10,10 @@ namespace WallpaperEngine::Render::Wallpapers { class CVideo final : public CWallpaper { public: - CVideo (const Core::Wallpapers::CVideo* video, CRenderContext& context, CAudioContext& audioContext, - const CWallpaperState::TextureUVsScaling& scalingMode); + CVideo ( + const Core::Wallpapers::CVideo* video, CRenderContext& context, CAudioContext& audioContext, + const CWallpaperState::TextureUVsScaling& scalingMode, + const WallpaperEngine::Assets::ITexture::TextureFlags& clampMode); const Core::Wallpapers::CVideo* getVideo () const; diff --git a/src/WallpaperEngine/Render/Wallpapers/CWeb.cpp b/src/WallpaperEngine/Render/Wallpapers/CWeb.cpp index b0c3f94..b667d94 100644 --- a/src/WallpaperEngine/Render/Wallpapers/CWeb.cpp +++ b/src/WallpaperEngine/Render/Wallpapers/CWeb.cpp @@ -10,9 +10,12 @@ using namespace WallpaperEngine::Render::Wallpapers; using namespace WallpaperEngine::WebBrowser; using namespace WallpaperEngine::WebBrowser::CEF; -CWeb::CWeb (const Core::Wallpapers::CWeb* web, CRenderContext& context, CAudioContext& audioContext, CWebBrowserContext& browserContext, - const CWallpaperState::TextureUVsScaling& scalingMode) : - CWallpaper (web, Type, context, audioContext, scalingMode), +CWeb::CWeb ( + const Core::Wallpapers::CWeb* web, CRenderContext& context, CAudioContext& audioContext, + CWebBrowserContext& browserContext, const CWallpaperState::TextureUVsScaling& scalingMode, + const WallpaperEngine::Assets::ITexture::TextureFlags& clampMode +) : + CWallpaper (web, Type, context, audioContext, scalingMode, clampMode), m_browserContext (browserContext), m_browser (), m_client (), diff --git a/src/WallpaperEngine/Render/Wallpapers/CWeb.h b/src/WallpaperEngine/Render/Wallpapers/CWeb.h index 4f8b4ff..0f6f4e0 100644 --- a/src/WallpaperEngine/Render/Wallpapers/CWeb.h +++ b/src/WallpaperEngine/Render/Wallpapers/CWeb.h @@ -21,41 +21,45 @@ class CRenderHandler; } namespace WallpaperEngine::Render::Wallpapers { - class CWeb : public CWallpaper - { - public: - CWeb (const Core::Wallpapers::CWeb* scene, CRenderContext& context, CAudioContext& audioContext, WallpaperEngine::WebBrowser::CWebBrowserContext& browserContext, const CWallpaperState::TextureUVsScaling& scalingMode); - ~CWeb() override; - [[nodiscard]] int getWidth () const override { return this->m_width; } +class CWeb : public CWallpaper +{ + public: + CWeb ( + const Core::Wallpapers::CWeb* scene, CRenderContext& context, CAudioContext& audioContext, + WallpaperEngine::WebBrowser::CWebBrowserContext& browserContext, + const CWallpaperState::TextureUVsScaling& scalingMode, + const WallpaperEngine::Assets::ITexture::TextureFlags& clampMode); + ~CWeb() override; + [[nodiscard]] int getWidth () const override { return this->m_width; } - [[nodiscard]] int getHeight () const override { return this->m_height; } + [[nodiscard]] int getHeight () const override { return this->m_height; } - void setSize (int width, int height); + void setSize (int width, int height); - protected: - void renderFrame (glm::ivec4 viewport) override; - void updateMouse (glm::ivec4 viewport); - const Core::Wallpapers::CWeb* getWeb () const { - return this->getWallpaperData ()->as (); - } + protected: + void renderFrame (glm::ivec4 viewport) override; + void updateMouse (glm::ivec4 viewport); + const Core::Wallpapers::CWeb* getWeb () const { + return this->getWallpaperData ()->as (); + } - friend class CWallpaper; + friend class CWallpaper; - static const std::string Type; + static const std::string Type; - private: - WallpaperEngine::WebBrowser::CWebBrowserContext& m_browserContext; - CefRefPtr m_browser; - CefRefPtr m_client; - WallpaperEngine::WebBrowser::CEF::CRenderHandler* m_renderHandler = nullptr; + private: + WallpaperEngine::WebBrowser::CWebBrowserContext& m_browserContext; + CefRefPtr m_browser; + CefRefPtr m_client; + WallpaperEngine::WebBrowser::CEF::CRenderHandler* m_renderHandler = nullptr; - int m_width; - int m_height; + int m_width; + int m_height; - WallpaperEngine::Input::MouseClickStatus m_leftClick; - WallpaperEngine::Input::MouseClickStatus m_rightClick; + WallpaperEngine::Input::MouseClickStatus m_leftClick; + WallpaperEngine::Input::MouseClickStatus m_rightClick; - glm::vec2 m_mousePosition; - glm::vec2 m_mousePositionLast; - }; + glm::vec2 m_mousePosition; + glm::vec2 m_mousePositionLast; +}; }