Compare commits

..

4 Commits

Author SHA1 Message Date
Almamu
73f716da84 refactor: new project parser 2025-08-12 03:36:44 +02:00
Almamu
be0fc25e72 chore: better error reporting for parameters, highlighting --help usage. fixess #303 and should improve #275
Some checks failed
CMake / build-x11 (ubuntu-22.04) (push) Has been cancelled
CMake / build-x11 (ubuntu-24.04) (push) Has been cancelled
CMake / build-x11-wayland (ubuntu-22.04) (push) Has been cancelled
CMake / build-x11-wayland (ubuntu-24.04) (push) Has been cancelled
CMake / build-wayland (ubuntu-22.04) (push) Has been cancelled
CMake / build-wayland (ubuntu-24.04) (push) Has been cancelled
2025-05-17 03:23:05 +02:00
Almamu
3c334aac29 chore: better error reporting after fix for #300
Some checks failed
CMake / build-x11 (ubuntu-22.04) (push) Has been cancelled
CMake / build-x11 (ubuntu-24.04) (push) Has been cancelled
CMake / build-x11-wayland (ubuntu-22.04) (push) Has been cancelled
CMake / build-x11-wayland (ubuntu-24.04) (push) Has been cancelled
CMake / build-wayland (ubuntu-22.04) (push) Has been cancelled
CMake / build-wayland (ubuntu-24.04) (push) Has been cancelled
2025-05-15 22:28:23 +02:00
Almamu
555b488951 fix: make background id optional so usages of -b, --bg do not require a fallback background (as expected) fixes #300 2025-05-15 22:20:20 +02:00
19 changed files with 501 additions and 164 deletions

View File

@ -1,31 +0,0 @@
---
name: Background doesn't load properly
about: Use this to report backgrounds that are not loading (cannot find files, black
image, effects not working, etc)
title: "[BGFIX]"
labels: bug
assignees: Almamu
---
**Wallpaper Engine Background(s)**
Link(s) to the background(s) in the steam workshop or their background ID(s).
**Console output**
When a background cannot be loaded, it's usually due to some unexpected error that is logged into the terminal. Please attach the program's output so we can properly debug it if needed.
**Screenshots**
If you have any screenshot of it working on Windows that'll help so we can compare both outputs
**Desktop (please complete the following information):**
- OS: [e.g. Arch Linux]
- Desktop Environment: [e.g. GNOME, CINNAMON, KDE...]
- Window Manager: [if in doubt, just leave it empty]
**Additional context**
Any additional information about your setup

58
.github/ISSUE_TEMPLATE/bug-report.yml vendored Normal file
View File

@ -0,0 +1,58 @@
name: "Bug Report"
description: "Report a bug or unexpected behavior."
labels: [bug]
body:
- type: markdown
attributes:
value: |
Please fill out this form to report a bug.
- type: input
id: summary
attributes:
label: Bug Summary
description: Briefly describe the bug.
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to Reproduce
description: Step-by-step instructions to reproduce the bug.
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected Behavior
validations:
required: false
- type: textarea
id: actual
attributes:
label: Actual Behavior / Logs
validations:
required: false
- type: input
id: os
attributes:
label: Operating System and Version
validations:
required: true
- type: input
id: de
attributes:
label: Desktop Environment (GNOME, KDE, etc.)
validations:
required: true
- type: input
id: x11_wayland
attributes:
label: Display Server (X11/Wayland)
validations:
required: true
- type: textarea
id: extra
attributes:
label: Additional Context or Screenshots
validations:
required: false

View File

@ -0,0 +1,46 @@
name: "Wallpaper Compatibility Issue"
description: "Report a problem with a specific Wallpaper Engine wallpaper."
labels: [compatibility, wallpaper]
body:
- type: input
id: wallpaper
attributes:
label: Wallpaper Name, URL or ID
validations:
required: true
- type: textarea
id: issue
attributes:
label: Describe the Issue
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected Behavior
validations:
required: false
- type: textarea
id: logs
attributes:
label: Logs or Crash Output
validations:
required: false
- type: input
id: os
attributes:
label: Operating System and Version
validations:
required: true
- type: input
id: de
attributes:
label: Desktop Environment (GNOME, KDE, etc.)
validations:
required: true
- type: input
id: x11_wayland
attributes:
label: Display Server (X11/Wayland)
validations:
required: true

View File

@ -0,0 +1,32 @@
name: "Feature Request"
description: "Propose a new feature or enhancement."
labels: [enhancement]
body:
- type: markdown
attributes:
value: |
Use this form to suggest new features or improvements.
- type: textarea
id: feature
attributes:
label: Describe the Feature
validations:
required: true
- type: textarea
id: problem
attributes:
label: Problem this Feature Addresses (if any)
validations:
required: false
- type: textarea
id: alternatives
attributes:
label: Alternatives Considered
validations:
required: false
- type: textarea
id: context
attributes:
label: Additional Context or Mockups
validations:
required: false

View File

@ -0,0 +1,38 @@
name: "Installation/Usage Help"
description: "Request help with installing or using linux-wallpaperengine."
labels: [question, support]
body:
- type: markdown
attributes:
value: |
Need help? Fill this out so we can assist you better.
- type: textarea
id: issue
attributes:
label: What are you trying to do, and what's the problem?
validations:
required: true
- type: textarea
id: attempted
attributes:
label: What have you tried so far?
validations:
required: false
- type: textarea
id: error_logs
attributes:
label: Errors or Log Output
validations:
required: false
- type: input
id: system
attributes:
label: OS, Desktop Environment, X11/Wayland
validations:
required: true
- type: input
id: install_method
attributes:
label: Installation Method (e.g., AUR, Flatpak, build from source)
validations:
required: true

View File

@ -1,10 +0,0 @@
---
name: Other issues
about: Use this to report general issues with the software
title: ''
labels: ''
assignees: Almamu
---

22
.github/ISSUE_TEMPLATE/refactor.yml vendored Normal file
View File

@ -0,0 +1,22 @@
name: "Code Cleanup / Refactor"
description: "Suggest internal improvements like refactoring or technical debt cleanup."
labels: [refactor, maintenance]
body:
- type: textarea
id: what
attributes:
label: What needs improvement?
validations:
required: true
- type: textarea
id: why
attributes:
label: Why is this necessary or beneficial?
validations:
required: false
- type: textarea
id: impact
attributes:
label: Potential Impact on Users
validations:
required: false

View File

@ -26,8 +26,11 @@ CApplicationContext::CApplicationContext (int argc, char* argv []) :
backgroundGroup.add_argument ("background id")
.help ("The background to use as default for screens with no background specified")
.default_value ("")
.action([this](const std::string& value) -> void {
this->settings.general.defaultBackground = translateBackground (value);
if (!value.empty()) {
this->settings.general.defaultBackground = translateBackground (value);
}
});
backgroundMode.add_argument ("-w", "--window")
@ -252,40 +255,48 @@ CApplicationContext::CApplicationContext (int argc, char* argv []) :
" Runs the background 2317494988 on two screens, one on HDMI-1 and the other on HDMI-2\n\n"
);
program.parse_known_args (argc, argv);
try {
program.parse_known_args (argc, argv);
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));
if (this->settings.general.defaultBackground.empty ()) {
throw std::runtime_error ("At least one background ID must be specified");
}
// 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);
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));
bufferStream << "Running with: ";
// 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);
for (int i = 0; i < argc; i ++) {
bufferStream << argv [i];
bufferStream << " ";
}
bufferStream << "Running with: ";
std::cout << buffer.str() << std::endl;
// perform some extra validation on the inputs
this->validateAssets ();
this->validateScreenshot ();
for (int i = 0; i < argc; i ++) {
bufferStream << argv [i];
bufferStream << " ";
}
// setup application state
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;
std::cout << buffer.str() << std::endl;
// perform some extra validation on the inputs
this->validateAssets ();
this->validateScreenshot ();
// setup application state
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;
#if DEMOMODE
sLog.error ("WARNING: RUNNING IN DEMO MODE WILL STOP WALLPAPERS AFTER 5 SECONDS SO VIDEO CAN BE RECORDED");
// special settings for demomode
this->settings.render.maximumFPS = 30;
this->settings.screenshot.take = false;
this->settings.render.pauseOnFullscreen = false;
sLog.error ("WARNING: RUNNING IN DEMO MODE WILL STOP WALLPAPERS AFTER 5 SECONDS SO VIDEO CAN BE RECORDED");
// special settings for demomode
this->settings.render.maximumFPS = 30;
this->settings.screenshot.take = false;
this->settings.render.pauseOnFullscreen = false;
#endif /* DEMOMODE */
} catch (const std::runtime_error& e) {
throw std::runtime_error (std::string (e.what()) + ". Use " + std::string (argv[0]) + " --help for more information");
}
}
int CApplicationContext::getArgc () const {

View File

@ -40,18 +40,18 @@ CWallpaperApplication::CWallpaperApplication (CApplicationContext& context) :
void CWallpaperApplication::setupContainer (const std::shared_ptr<CCombinedContainer>& container, const std::string& bg) const {
const std::filesystem::path basepath = bg;
container->add (std::make_shared<CDirectory> (basepath));
container->add (std::make_unique<CDirectory> (basepath));
container->addPkg (basepath / "scene.pkg");
container->addPkg (basepath / "gifscene.pkg");
try {
container->add (std::make_shared <CDirectory> (this->m_context.settings.general.assets));
container->add (std::make_unique <CDirectory> (this->m_context.settings.general.assets));
} catch (CAssetLoadException&) {
sLog.exception ("Cannot find a valid assets folder, resolved to ", this->m_context.settings.general.assets);
}
// TODO: move this somewhere else?
auto virtualContainer = std::make_shared <CVirtualContainer> ();
auto virtualContainer = std::make_unique <CVirtualContainer> ();
//
// Had to get a little creative with the effects to achieve the same bloom effect without any custom code
@ -184,7 +184,7 @@ void CWallpaperApplication::setupContainer (const std::shared_ptr<CCombinedConta
"}"
);
container->add (virtualContainer);
container->add (std::move(virtualContainer));
}
void CWallpaperApplication::loadBackgrounds () {

View File

@ -8,14 +8,14 @@ using namespace WallpaperEngine::Assets;
CCombinedContainer::CCombinedContainer () : CContainer () {}
void CCombinedContainer::add (const std::shared_ptr<CContainer>& container) {
this->m_containers.emplace_back (container);
void CCombinedContainer::add (std::unique_ptr<CContainer> container) {
this->m_containers.emplace_back (std::move(container));
}
void CCombinedContainer::addPkg (const std::filesystem::path& path) {
try {
// add the package to the list
this->add (std::make_shared<CPackage> (path));
this->add (std::make_unique<CPackage> (path));
sLog.out ("Detected ", path.filename (), " file at ", path, ". Adding to list of searchable paths");
} catch (CPackageLoadException&) {
// ignore this error, the package file was not found

View File

@ -19,7 +19,7 @@ class CCombinedContainer final : public CContainer {
*
* @param container
*/
void add (const std::shared_ptr<CContainer>& container);
void add (std::unique_ptr<CContainer> container);
/**
* Adds the given package to the list
*
@ -32,6 +32,6 @@ class CCombinedContainer final : public CContainer {
private:
/** The list of containers to search files off from */
std::vector<std::shared_ptr<CContainer>> m_containers {};
std::vector<std::unique_ptr<CContainer>> m_containers {};
};
}; // namespace WallpaperEngine::Assets

View File

@ -31,35 +31,75 @@ void StringPrinter::printWallpaper (const Wallpaper& wallpaper) {
this->m_out << "Scene wallpaper: ";
this->increaseIndentation ();
this->lineEnd ();
// TODO: IMPLEMENT FBO PRINTING, AS THIS WASN'T REALLY REFLECTION HOW IT ACTUALLY WORKS
this->m_out << "Objects count: " << scene->objects.size ();
this->increaseIndentation ();
for (const auto& object : scene->objects) {
if (object.second->is <Image> ()) {
this->printImage (*object.second->as <Image> ());
}
this->lineEnd ();
this->printObject (*object.second);
this->lineEnd ();
}
this->decreaseIndentation ();
}
}
void StringPrinter::printImage (const Image& image) {
this->m_out << "Image " << image.id << " " << image.name << ":";
void StringPrinter::printObject (const Object& object) {
this->m_out << "Object " << object.id << " " << object.name << ":";
this->increaseIndentation ();
this->lineEnd ();
this->m_out << "Dependencies (" << object.dependencies.size () << "): ";
for (const auto& dependency : object.dependencies) {
this->m_out << dependency << ", ";
}
if (object.is <Image> ()) {
this->lineEnd ();
this->printImage (*object.as <Image> ());
} else if (object.is <Sound> ()) {
this->lineEnd ();
this->printSound (*object.as <Sound> ());
}
this->decreaseIndentation ();
}
void StringPrinter::printImage (const Image& image) {
this->printModel (*image.model);
this->lineEnd ();
this->m_out << "Image effects count: " << image.effects.size ();
this->increaseIndentation ();
for (const auto& effect : image.effects) {
this->lineEnd ();
this->printImageEffect (*effect);
}
this->decreaseIndentation ();
}
void StringPrinter::printSound (const Sound& sound) {
this->m_out << "Sounds: " << sound.sounds.size ();
this->increaseIndentation ();
for (const auto& filename : sound.sounds) {
this->lineEnd ();
this->m_out << "Filename " << filename;
}
this->decreaseIndentation ();
}
void StringPrinter::printModel (const ModelStruct& model) {
this->m_out << "Model " << model.filename << ":";
this->increaseIndentation ();
this->lineEnd ();
this->m_out << "Autosize: " << model.autosize;
this->lineEnd ();
@ -71,10 +111,12 @@ void StringPrinter::printModel (const ModelStruct& model) {
this->lineEnd ();
this->m_out << "Solid layer: " << model.solidlayer;
this->lineEnd ();
if (model.width.has_value ()) {
this->m_out << "Width: " << model.width.value ();
this->lineEnd ();
}
if (model.height.has_value ()) {
this->m_out << "Height: " << model.height.value ();
this->lineEnd ();
@ -90,82 +132,130 @@ void StringPrinter::printImageEffect (const ImageEffect& effect) {
this->increaseIndentation ();
this->m_out << "Default visibility status: " << effect.visible->value->getBool ();
this->lineEnd ();
this->m_out << "Default visibility status: " << effect.visible->value->getBool ();
this->printEffect (*effect.effect);
this->lineEnd ();
this->m_out << "Effect overrides count: " << effect.passOverrides.size ();
this->increaseIndentation ();
for (const auto& override : effect.passOverrides) {
this->printImageEffectPassOverride (*override);
}
this->decreaseIndentation ();
this->decreaseIndentation ();
}
void StringPrinter::printImageEffectPass (const ImageEffectPass& imageEffectPass) {
this->m_out << "Pass " << imageEffectPass.id << ":";
void StringPrinter::printImageEffectPassOverride (const ImageEffectPassOverride& imageEffectPass) {
this->lineEnd ();
this->m_out << "Pass override " << imageEffectPass.id << ":";
this->increaseIndentation ();
this->lineEnd ();
this->m_out << "Textures count: " << imageEffectPass.textures.size ();
if (!imageEffectPass.textures.empty ()) {
this->m_out << "Textures count: " << imageEffectPass.textures.size ();
this->increaseIndentation ();
for (const auto& texture : imageEffectPass.textures) {
this->m_out << "Texture " << texture.first << ": " << texture.second;
this->lineEnd ();
this->m_out << "Texture " << texture.first << ": " << texture.second;
}
this->decreaseIndentation ();
}
this->lineEnd ();
this->m_out << "Combos count: " << imageEffectPass.combos.size ();
if (!imageEffectPass.combos.empty ()) {
this->increaseIndentation ();
for (const auto& combo : imageEffectPass.combos) {
this->lineEnd ();
this->m_out << "Combo " << combo.first << "=" << combo.second;
}
this->decreaseIndentation ();
}
this->lineEnd ();
this->m_out << "Constants count: " << imageEffectPass.constants.size ();
if (!imageEffectPass.constants.empty ()) {
this->increaseIndentation ();
for (const auto& constant : imageEffectPass.constants) {
this->lineEnd ();
this->m_out << "Constant " << constant.first << "=" << constant.second->toString();
}
this->decreaseIndentation ();
}
this->decreaseIndentation ();
}
void StringPrinter::printEffect (const Effect& effect) {
this->lineEnd ();
this->m_out << "Effect " << effect.name << ":";
this->increaseIndentation ();
if (!effect.description.empty ()) {
this->m_out << "Description: " << effect.description;
this->lineEnd ();
this->m_out << "Description: " << effect.description;
}
if (!effect.dependencies.empty ()) {
this->lineEnd ();
this->m_out << "Dependencies count: " << effect.dependencies.size ();
this->increaseIndentation ();
for (const auto& dependency : effect.dependencies) {
this->m_out << "Dependency: " << dependency;
this->lineEnd ();
this->m_out << "Dependency: " << dependency;
}
this->decreaseIndentation ();
}
if (!effect.group.empty ()) {
this->m_out << "Group: " << effect.group;
this->lineEnd ();
this->m_out << "Group: " << effect.group;
}
if (!effect.preview.empty ()) {
this->m_out << "Preview: " << effect.preview;
this->lineEnd ();
this->m_out << "Preview: " << effect.preview;
}
this->lineEnd ();
this->m_out << "Passes count: " << effect.passes.size ();
this->increaseIndentation ();
int passId = 0;
for (const auto& pass : effect.passes) {
this->m_out << "Pass " << passId << ":";
this->lineEnd ();
this->m_out << "Pass " << ++passId << ":";
this->increaseIndentation ();
this->lineEnd ();
this->printEffectPass (*pass);
this->decreaseIndentation ();
passId ++;
}
this->decreaseIndentation ();
this->lineEnd ();
this->m_out << "FBOs count: " << effect.fbos.size ();
this->increaseIndentation ();
for (const auto& fbo : effect.fbos) {
this->lineEnd ();
this->printFBO (*fbo);
}
@ -182,25 +272,31 @@ void StringPrinter::printEffectPass (const EffectPass& effectPass) {
this->m_out << "Source: " << command.source;
this->lineEnd ();
this->m_out << "Target: " << command.target;
this->lineEnd ();
} else {
if (effectPass.target.has_value ()) {
this->m_out << "Target: " << effectPass.target.value ();
this->lineEnd ();
}
if (!effectPass.binds.empty ()) {
if (effectPass.target.has_value ()) {
this->lineEnd ();
}
this->m_out << "Binds count: " << effectPass.binds.size ();
this->increaseIndentation ();
for (const auto& bind : effectPass.binds) {
this->m_out << "Bind " << bind.first << ": " << bind.second;
this->lineEnd ();
this->m_out << "Bind " << bind.first << ": " << bind.second;
}
this->decreaseIndentation ();
}
if (effectPass.target.has_value () || !effectPass.binds.empty ()) {
this->lineEnd ();
}
this->printMaterial (*effectPass.material);
}
}
@ -209,9 +305,10 @@ void StringPrinter::printFBO (const FBO& fbo) {
this->m_out << "FBO " << fbo.name << ":";
this->increaseIndentation ();
this->m_out << "Format: " << fbo.format;
this->lineEnd ();
this->m_out << "Format: " << fbo.format;
this->lineEnd ();
this->m_out << "Scale: " << fbo.scale;
this->decreaseIndentation ();
}
@ -219,10 +316,12 @@ void StringPrinter::printFBO (const FBO& fbo) {
void StringPrinter::printMaterial (const Material& material) {
this->m_out << "Material " << material.filename << ":";
this->increaseIndentation ();
this->lineEnd ();
this->m_out << "Passes count: " << material.passes.size ();
this->increaseIndentation ();
for (const auto& pass : material.passes) {
this->lineEnd ();
this->printMaterialPass (*pass);
}
@ -234,6 +333,7 @@ void StringPrinter::printMaterialPass (const MaterialPass& materialPass) {
this->m_out << "Pass " << materialPass.shader << ":";
this->increaseIndentation ();
this->lineEnd ();
this->m_out << "Depth test: " << materialPass.depthtest;
this->lineEnd ();
this->m_out << "Depth write: " << materialPass.depthwrite;
@ -241,27 +341,28 @@ void StringPrinter::printMaterialPass (const MaterialPass& materialPass) {
this->m_out << "Blend mode: " << materialPass.blending;
this->lineEnd ();
this->m_out << "Culling mode: " << materialPass.cullmode;
this->lineEnd ();
if (!materialPass.textures.empty ()) {
this->lineEnd ();
this->m_out << "Textures count: " << materialPass.textures.size ();
this->increaseIndentation ();
for (const auto& texture : materialPass.textures) {
this->m_out << "Texture " << texture.first << ": " << texture.second;
this->lineEnd ();
this->m_out << "Texture " << texture.first << ": " << texture.second;
}
this->decreaseIndentation ();
}
if (!materialPass.combos.empty ()) {
this->lineEnd ();
this->m_out << "Combos count: " << materialPass.combos.size ();
this->increaseIndentation ();
for (const auto& combo : materialPass.combos) {
this->m_out << "Combo " << combo.first << ": " << combo.second;
this->lineEnd ();
this->m_out << "Combo " << combo.first << ": " << combo.second;
}
this->decreaseIndentation ();
@ -282,12 +383,10 @@ void StringPrinter::lineEnd () {
void StringPrinter::increaseIndentation () {
this->m_level ++;
this->lineEnd ();
}
void StringPrinter::decreaseIndentation () {
this->m_level --;
this->lineEnd ();
}
std::string StringPrinter::str () {

View File

@ -25,6 +25,13 @@ class StringPrinter {
*/
void printWallpaper (const Wallpaper& wallpaper);
/**
* Prints the information of the given object
*
* @param object
*/
void printObject (const Object& object);
/**
* Prints the information of the given image
*
@ -32,6 +39,13 @@ class StringPrinter {
*/
void printImage (const Image& image);
/**
* Prints the information of the given sound
*
* @param sound
*/
void printSound (const Sound& sound);
/**
* Prints the information of the given model
*
@ -51,7 +65,7 @@ class StringPrinter {
*
* @param imageEffectPass
*/
void printImageEffectPass (const ImageEffectPass& imageEffectPass);
void printImageEffectPassOverride (const ImageEffectPassOverride& imageEffectPass);
/**
* Prints the information of the given FBO

View File

@ -1,5 +1,6 @@
#pragma once
#include <utility>
#include <vector>
#include <string>
@ -43,9 +44,9 @@ class Object : public TypeCaster, public ObjectData {
* @see ImageEffect
* @see EffectPass
*/
struct ImageEffectPass {
struct ImageEffectPassOverride {
int id;
std::map <std::string, int> combos;
ComboMap combos;
ShaderConstantMap constants;
std::map <int, std::string> textures;
};
@ -66,7 +67,7 @@ struct ImageEffect {
/** If this effect is visible or not */
UserSettingSharedPtr visible;
/** Pass overrides to apply to the effect's passes */
std::vector <ImageEffectPassUniquePtr> passes;
std::vector <ImageEffectPassOverrideUniquePtr> passOverrides;
/** The effect definition */
EffectUniquePtr effect;
};
@ -103,7 +104,7 @@ struct ImageData {
class Image : public Object, public ImageData {
public:
explicit Image (ObjectData data, ImageData imageData) noexcept : Object (data), ImageData (std::move (imageData)) {};
explicit Image (ObjectData data, ImageData imageData) noexcept : Object (std::move(data)), ImageData (std::move (imageData)) {};
~Image () override = default;
};
@ -115,7 +116,7 @@ struct SoundData {
class Sound : public Object, public SoundData {
public:
explicit Sound (ObjectData data, SoundData soundData) noexcept : Object (data), SoundData (std::move (soundData)) {};
explicit Sound (ObjectData data, SoundData soundData) noexcept : Object (std::move(data)), SoundData (std::move (soundData)) {};
~Sound () override = default;
};
} // namespace WallpaperEngine::Data::Model

View File

@ -24,7 +24,7 @@ class Object;
class Sound;
class Image;
struct ImageEffect;
struct ImageEffectPass;
struct ImageEffectPassOverride;
class Particle;
struct Material;
struct MaterialPass;
@ -75,10 +75,12 @@ using MaterialUniquePtr = std::unique_ptr <Material>;
using MaterialPassUniquePtr = std::unique_ptr <MaterialPass>;
using EffectUniquePtr = std::unique_ptr <Effect>;
using ImageEffectUniquePtr = std::unique_ptr <ImageEffect>;
using ImageEffectPassUniquePtr = std::unique_ptr <ImageEffectPass>;
using ImageEffectPassOverrideUniquePtr = std::unique_ptr <ImageEffectPassOverride>;
using EffectPassUniquePtr = std::unique_ptr <EffectPass>;
using FBOUniquePtr = std::unique_ptr <FBO>;
using ModelUniquePtr = std::unique_ptr <ModelStruct>;
using ObjectMap = std::map<int, ObjectUniquePtr>;
using ComboMap = std::map<std::string, int>;
using TextureMap = std::map<int, std::string>;
}

View File

@ -2,9 +2,10 @@
#include "ModelParser.h"
#include "EffectParser.h"
#include "WallpaperEngine/Logging/CLog.h"
#include "WallpaperEngine/Data/Model/Project.h"
#include "ShaderConstantParser.h"
#include "WallpaperEngine/Data/Model/Object.h"
#include "WallpaperEngine/Data/Model/Project.h"
#include "WallpaperEngine/Logging/CLog.h"
using namespace WallpaperEngine::Data::Parsers;
using namespace WallpaperEngine::Data::Model;
@ -15,23 +16,22 @@ ObjectUniquePtr ObjectParser::parse (const JSON& it, const ProjectWeakPtr& proje
const auto particleIt = it.find ("particle");
const auto textIt = it.find ("text");
const auto lightIt = it.find ("light");
const auto dependenciesIt = it.find ("dependencies");
const auto basedata = ObjectData {
.id = it.require <int> ("id", "Object must have an id"),
.name = it.require <std::string> ("name", "Object must have a name"),
.dependencies = parseDependencies (it),
};
if (imageIt != it.end ()) {
if (imageIt != it.end () && imageIt->is_string ()) {
return parseImage (it, project, basedata, *imageIt);
} else if (soundIt != it.end ()) {
} else if (soundIt != it.end () && soundIt->is_array ()) {
return parseSound (it, project, basedata);
} else if (particleIt != it.end ()) {
sLog.error ("Particle objects are not supported yet");
} else if (textIt != it.end ()) {
sLog.error ("Text objects are not supported yet");
} else if (lightIt != it.end ()) {
sLog.error ("Light objects are not supported yet");
} else {
// dump the object for now, might want to change later
sLog.exception ("Unknown object type found: ", it.dump ());
@ -113,23 +113,22 @@ std::vector <ImageEffectUniquePtr> ObjectParser::parseEffects (const JSON& it, c
}
ImageEffectUniquePtr ObjectParser::parseEffect (const JSON& it, const ProjectWeakPtr& project) {
const auto& passes = it.optional ("passes");
const auto& passsOverrides = it.optional ("passes");
return std::make_unique <ImageEffect> (ImageEffect {
.id = it.require <int> ("id", "Image effect must have an id"),
.name = it.require <std::string> ("name", "Image effect must have a name"),
.visible = it.user ("visible", project.lock ()->properties, true),
//TODO: ADD EFFECTS HERE
.passes = passes.has_value () ? parseEffectPasses (passes.value (), project) : std::vector <ImageEffectPassUniquePtr> {},
.passOverrides = passsOverrides.has_value () ? parseEffectPassOverrides (passsOverrides.value (), project) : std::vector <ImageEffectPassOverrideUniquePtr> {},
.effect = EffectParser::load (project, it.require ("file", "Image effect must have an effect"))
});
}
std::vector <ImageEffectPassUniquePtr> ObjectParser::parseEffectPasses (const JSON& it, const ProjectWeakPtr& project) {
std::vector <ImageEffectPassOverrideUniquePtr> ObjectParser::parseEffectPassOverrides (const JSON& it, const ProjectWeakPtr& project) {
if (!it.is_array ()) {
return {};
}
std::vector <ImageEffectPassUniquePtr> result = {};
std::vector <ImageEffectPassOverrideUniquePtr> result = {};
for (const auto& cur : it) {
result.push_back (parseEffectPass (cur, project));
@ -138,8 +137,51 @@ std::vector <ImageEffectPassUniquePtr> ObjectParser::parseEffectPasses (const JS
return result;
}
ImageEffectPassUniquePtr ObjectParser::parseEffectPass (const JSON& it, const ProjectWeakPtr& project) {
return std::make_unique <ImageEffectPass> (ImageEffectPass {
ImageEffectPassOverrideUniquePtr ObjectParser::parseEffectPass (const JSON& it, const ProjectWeakPtr& project) {
const auto& combos = it.optional ("combos");
const auto& textures = it.optional ("textures");
const auto& constants = it.optional ("constantshadervalues");
// TODO: PARSE CONSTANT SHADER VALUES AND FIND REFS?
return std::make_unique <ImageEffectPassOverride> (ImageEffectPassOverride {
.id = it.require <int> ("id", "Image effect pass must have an id"),
.combos = combos.has_value () ? parseComboMap (combos.value ()) : ComboMap {},
.constants = constants.has_value () ? ShaderConstantParser::parse (constants.value (), project) : ShaderConstantMap {},
.textures = textures.has_value () ? parseTextureMap (textures.value ()) : TextureMap {},
});
}
TextureMap ObjectParser::parseTextureMap (const JSON& it) {
if (!it.is_array ()) {
return {};
}
TextureMap result = {};
int textureIndex = -1;
for (const auto& cur : it) {
textureIndex ++;
if (cur.is_null ()) {
continue;
}
result.emplace (textureIndex, cur);
}
return result;
}
ComboMap ObjectParser::parseComboMap (const JSON& it) {
if (!it.is_object ()) {
return {};
}
ComboMap result = {};
for (const auto& cur : it.items ()) {
result.emplace (cur.key (), cur.value ());
}
return result;
}

View File

@ -24,7 +24,9 @@ class ObjectParser {
const JSON& it, const ProjectWeakPtr& project, ObjectData base, const std::string& image);
static std::vector <ImageEffectUniquePtr> parseEffects (const JSON& it, const ProjectWeakPtr& project);
static ImageEffectUniquePtr parseEffect (const JSON& it, const ProjectWeakPtr& project);
static std::vector <ImageEffectPassUniquePtr> parseEffectPasses (const JSON& it, const ProjectWeakPtr& project);
static ImageEffectPassUniquePtr parseEffectPass (const JSON& it, const ProjectWeakPtr& project);
static std::vector <ImageEffectPassOverrideUniquePtr> parseEffectPassOverrides (const JSON& it, const ProjectWeakPtr& project);
static ImageEffectPassOverrideUniquePtr parseEffectPass (const JSON& it, const ProjectWeakPtr& project);
static TextureMap parseTextureMap (const JSON& it);
static ComboMap parseComboMap (const JSON& it);
};
} // namespace WallpaperEngine::Data::Parsers

View File

@ -1,3 +1,5 @@
#include <algorithm>
#include "ProjectParser.h"
#include "WallpaperEngine/Logging/CLog.h"
@ -9,10 +11,14 @@ static int backgroundId = 0;
ProjectSharedPtr ProjectParser::parse (const JSON& data, const ContainerWeakPtr& container) {
const auto general = data.optional ("general");
auto type = data.require <std::string> ("type", "Project type missing");
// lowercase for consistency
std::transform (type.begin (), type.end (), type.begin (), tolower);
auto result = std::make_shared <Project> (Project {
.title = data.require <std::string> ("title", "Project title missing"),
.type = parseType (data.require <std::string> ("type", "Project type missing")),
.type = parseType (type),
.workshopId = data.optional ("workshopid", std::to_string (--backgroundId)),
.supportsAudioProcessing = general.has_value () && general.value ().optional ("supportsAudioProcessing", false),
.properties = parseProperties (general),

View File

@ -20,47 +20,52 @@ void initLogging () {
}
int main (int argc, char* argv[]) {
// if type parameter is specified, this is a subprocess, so no logging should be enabled from our side
bool enableLogging = true;
std::string typeZygote = "--type=zygote";
std::string typeUtility = "--type=utility";
try {
// if type parameter is specified, this is a subprocess, so no logging should be enabled from our side
bool enableLogging = true;
std::string typeZygote = "--type=zygote";
std::string typeUtility = "--type=utility";
for (int i = 1; i < argc; i ++) {
if (strncmp (typeZygote.c_str(), argv[i], typeZygote.size()) == 0) {
enableLogging = false;
break;
} else if (strncmp (typeUtility.c_str(), argv[i], typeUtility.size()) == 0) {
enableLogging = false;
break;
for (int i = 1; i < argc; i ++) {
if (strncmp (typeZygote.c_str(), argv[i], typeZygote.size()) == 0) {
enableLogging = false;
break;
} else if (strncmp (typeUtility.c_str(), argv[i], typeUtility.size()) == 0) {
enableLogging = false;
break;
}
}
}
if (enableLogging) {
initLogging ();
}
if (enableLogging) {
initLogging ();
}
WallpaperEngine::Application::CApplicationContext appContext (argc, argv);
WallpaperEngine::Application::CApplicationContext appContext (argc, argv);
// halt if the list-properties option was specified
if (appContext.settings.general.onlyListProperties)
return 0;
app = new WallpaperEngine::Application::CWallpaperApplication (appContext);
// attach signals to gracefully stop
std::signal (SIGINT, signalhandler);
std::signal (SIGTERM, signalhandler);
std::signal (SIGKILL, signalhandler);
// show the wallpaper application
app->show ();
// remove signal handlers before destroying app
std::signal (SIGINT, SIG_DFL);
std::signal (SIGTERM, SIG_DFL);
std::signal (SIGKILL, SIG_DFL);
delete app;
// halt if the list-properties option was specified
if (appContext.settings.general.onlyListProperties)
return 0;
app = new WallpaperEngine::Application::CWallpaperApplication (appContext);
// attach signals to gracefully stop
std::signal (SIGINT, signalhandler);
std::signal (SIGTERM, signalhandler);
std::signal (SIGKILL, signalhandler);
// show the wallpaper application
app->show ();
// remove signal handlers before destroying app
std::signal (SIGINT, SIG_DFL);
std::signal (SIGTERM, SIG_DFL);
std::signal (SIGKILL, SIG_DFL);
delete app;
return 0;
} catch (const std::exception& e) {
std::cerr << e.what () << std::endl;
return 1;
}
}