~ cleaned up main function and moved initialization functions to a more proper place

~ check for SDL initialization before playing audio to prevent error messages when there is not really any error
~ changed a missed iterator to auto on CSound

Signed-off-by: Alexis Maiquez <almamu@almamu.com>
This commit is contained in:
Alexis Maiquez 2019-09-10 12:55:45 +02:00
parent ce67c0bf64
commit d03edb7c1e
8 changed files with 275 additions and 229 deletions

293
main.cpp
View File

@ -1,158 +1,27 @@
#include <iostream>
#include <irrlicht/irrlicht.h>
#include <sstream>
#include <WallpaperEngine/Irrlicht/CPkgReader.h>
#include <getopt.h>
#include <SDL_mixer.h>
#include <SDL.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
#include "WallpaperEngine/Render/Shaders/Compiler.h"
#include "WallpaperEngine/Irrlicht/CImageLoaderTEX.h"
#include "WallpaperEngine/Core/CProject.h"
#include "WallpaperEngine/Irrlicht/CContext.h"
#include "WallpaperEngine/Render/CScene.h"
bool IsRootWindow = false;
std::vector<std::string> Screens;
std::vector<irr::core::rect<irr::s32>> Viewports;
enum BACKGROUND_RUN_MODE
{
RUN_MODE_UNKNOWN = 0,
RUN_MODE_HELP = 1,
RUN_MODE_DIRECTORY = 2,
RUN_MODE_PACKAGE = 3
};
// TODO: MOVE GLOBAL SHADER VARIABLES TO THEIR OWN CLASS
irr::f32 g_Time = 0;
WallpaperEngine::Irrlicht::CContext* IrrlichtContext;
void initialize_viewports (irr::SIrrlichtCreationParameters& irrlichtCreationParameters)
{
if (IsRootWindow == false || Screens.empty () == true)
return;
Display* display = XOpenDisplay (NULL);
int xrandr_result, xrandr_error;
if (!XRRQueryExtension (display, &xrandr_result, &xrandr_error))
{
std::cerr << "XRandr is not present, cannot detect specified screens, running in window mode" << std::endl;
return;
}
XRRScreenResources* screenResources = XRRGetScreenResources (display, DefaultRootWindow (display));
// there are some situations where xrandr returns null (like screen not using the extension)
if (screenResources == nullptr)
return;
for (int i = 0; i < screenResources->noutput; i ++)
{
XRROutputInfo* info = XRRGetOutputInfo (display, screenResources, screenResources->outputs [i]);
// there are some situations where xrandr returns null (like screen not using the extension)
if (info == nullptr)
continue;
auto cur = Screens.begin ();
auto end = Screens.end ();
for (; cur != end; cur ++)
{
if (info->connection == RR_Connected && strcmp (info->name, (*cur).c_str ()) == 0)
{
XRRCrtcInfo* crtc = XRRGetCrtcInfo (display, screenResources, info->crtc);
std::cout << "Found requested screen: " << info->name << " -> " << crtc->x << "x" << crtc->y << ":" << crtc->width << "x" << crtc->height << std::endl;
irr::core::rect<irr::s32> viewport;
viewport.UpperLeftCorner.X = crtc->x;
viewport.UpperLeftCorner.Y = crtc->y;
viewport.LowerRightCorner.X = crtc->x + crtc->width;
viewport.LowerRightCorner.Y = crtc->y + crtc->height;
Viewports.push_back (viewport);
XRRFreeCrtcInfo (crtc);
}
}
XRRFreeOutputInfo (info);
}
XRRFreeScreenResources (screenResources);
irrlichtCreationParameters.WindowId = reinterpret_cast<void*> (DefaultRootWindow (display));
}
int init_irrlicht()
{
IrrlichtContext = new WallpaperEngine::Irrlicht::CContext ();
irr::SIrrlichtCreationParameters irrlichtCreationParameters;
// prepare basic configuration for irrlicht
irrlichtCreationParameters.AntiAlias = 8;
irrlichtCreationParameters.Bits = 16;
// _irr_params.DeviceType = Irrlicht::EIDT_X11;
irrlichtCreationParameters.DriverType = irr::video::EDT_OPENGL;
irrlichtCreationParameters.Doublebuffer = false;
irrlichtCreationParameters.EventReceiver = nullptr;
irrlichtCreationParameters.Fullscreen = false;
irrlichtCreationParameters.HandleSRGB = false;
irrlichtCreationParameters.IgnoreInput = true;
irrlichtCreationParameters.Stencilbuffer = true;
irrlichtCreationParameters.UsePerformanceTimer = false;
irrlichtCreationParameters.Vsync = false;
irrlichtCreationParameters.WithAlphaChannel = false;
irrlichtCreationParameters.ZBufferBits = 24;
irrlichtCreationParameters.LoggingLevel = irr::ELL_DEBUG;
initialize_viewports (irrlichtCreationParameters);
IrrlichtContext->setDevice (irr::createDeviceEx (irrlichtCreationParameters));
if (IrrlichtContext->getDevice () == nullptr)
{
return 1;
}
IrrlichtContext->getDevice ()->setWindowCaption (L"Test game");
// check for ps and vs support
if (
IrrlichtContext->getDevice ()->getVideoDriver()->queryFeature (irr::video::EVDF_PIXEL_SHADER_1_1) == false &&
IrrlichtContext->getDevice ()->getVideoDriver()->queryFeature (irr::video::EVDF_ARB_FRAGMENT_PROGRAM_1) == false)
{
IrrlichtContext->getDevice ()->getLogger ()->log ("WARNING: Pixel shaders disabled because of missing driver/hardware support");
}
if (
IrrlichtContext->getDevice ()->getVideoDriver()->queryFeature (irr::video::EVDF_VERTEX_SHADER_1_1) == false &&
IrrlichtContext->getDevice ()->getVideoDriver()->queryFeature (irr::video::EVDF_ARB_VERTEX_PROGRAM_1) == false)
{
IrrlichtContext->getDevice ()->getLogger ()->log ("WARNING: Vertex shaders disabled because of missing driver/hardware support");
}
if (IrrlichtContext->getDevice ()->getVideoDriver ()->queryFeature (irr::video::EVDF_RENDER_TO_TARGET) == false)
{
IrrlichtContext->getDevice ()->getLogger ()->log ("ERROR: Your hardware or this renderer do not support rendering to texture");
return 1;
}
return 0;
}
void preconfigure_wallpaper_engine ()
{
// load the assets from wallpaper engine
IrrlichtContext->getDevice ()->getFileSystem ()->addFileArchive ("assets.zip", true, false);
// register custom loaders
IrrlichtContext->getDevice ()->getVideoDriver()->addExternalImageLoader (
new WallpaperEngine::Irrlicht::CImageLoaderTex (IrrlichtContext)
);
IrrlichtContext->getDevice ()->getFileSystem ()->addArchiveLoader (
new WallpaperEngine::Irrlicht::CArchiveLoaderPkg (IrrlichtContext)
);
}
WallpaperEngine::Irrlicht::CContext* IrrlichtContext = nullptr;
void print_help (const char* route)
{
@ -181,21 +50,24 @@ std::string stringPathFixes(const std::string& s){
int main (int argc, char* argv[])
{
int mode = 0;
int max_fps = 30;
bool audio_support = true;
std::vector <std::string> screens;
bool isRootWindow = false;
int mode = RUN_MODE_UNKNOWN;
int maximumFPS = 30;
bool shouldEnableAudio = true;
std::string path;
int option_index = 0;
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'},
{"help", no_argument, 0, 'h'},
{"fps", required_argument, 0, 'f'},
{nullptr, 0, 0, 0}
{"screen-root", required_argument, 0, 'r'},
{"pkg", required_argument, 0, 'p'},
{"dir", required_argument, 0, 'd'},
{"silent", no_argument, 0, 's'},
{"help", no_argument, 0, 'h'},
{"fps", required_argument, 0, 'f'},
{nullptr, 0, 0, 0}
};
while (true)
@ -208,30 +80,32 @@ int main (int argc, char* argv[])
switch (c)
{
case 'r':
IsRootWindow = true;
Screens.emplace_back (optarg);
isRootWindow = true;
screens.emplace_back (optarg);
break;
case 'p':
mode = 1;
if (mode == RUN_MODE_UNKNOWN)
mode = RUN_MODE_PACKAGE;
path = optarg;
break;
case 'd':
mode = 2;
if (mode == RUN_MODE_UNKNOWN)
mode = RUN_MODE_DIRECTORY;
path = optarg;
break;
case 's':
audio_support = false;
shouldEnableAudio = false;
break;
case 'h':
print_help (argv [0]);
return 0;
mode = RUN_MODE_HELP;
break;
case 'f':
max_fps = atoi (optarg);
maximumFPS = atoi (optarg);
break;
default:
@ -239,55 +113,51 @@ int main (int argc, char* argv[])
}
}
if (init_irrlicht ())
if (mode == RUN_MODE_UNKNOWN || mode == RUN_MODE_HELP)
{
print_help (argv [0]);
return 0;
}
try
{
IrrlichtContext = new WallpaperEngine::Irrlicht::CContext (screens, isRootWindow);
IrrlichtContext->initializeContext ();
}
catch (std::runtime_error& ex)
{
std::cerr << ex.what () << std::endl;
return 1;
}
preconfigure_wallpaper_engine ();
path = stringPathFixes (path);
irr::io::path wallpaper_path;
irr::io::path project_path;
irr::io::path wallpaper_path = IrrlichtContext->getDevice ()->getFileSystem ()->getAbsolutePath (path.c_str ());
irr::io::path project_path = wallpaper_path + "project.json";
irr::io::path scene_path;
switch (mode)
if (mode == RUN_MODE_PACKAGE)
{
case 0:
print_help (argv [0]);
return 0;
// pkg mode
case 1:
path = stringPathFixes(path);
wallpaper_path = IrrlichtContext->getDevice ()->getFileSystem ()->getAbsolutePath (path.c_str ());
project_path = wallpaper_path + "project.json";
scene_path = wallpaper_path + "scene.pkg";
IrrlichtContext->getDevice ()->getFileSystem ()->addFileArchive (scene_path, true, false); // add the pkg file to the lookup list
break;
// folder mode
case 2:
path = stringPathFixes(path);
wallpaper_path = IrrlichtContext->getDevice ()->getFileSystem ()->getAbsolutePath (path.c_str ());
project_path = wallpaper_path + "project.json";
// set our working directory
IrrlichtContext->getDevice ()->getFileSystem ()->changeWorkingDirectoryTo (wallpaper_path);
break;
default:
break;
irr::io::path scene_path = wallpaper_path + "scene.pkg";
// add the package file to the lookup list
IrrlichtContext->getDevice ()->getFileSystem ()->addFileArchive (scene_path, true, false);
}
else if (mode == RUN_MODE_DIRECTORY)
{
project_path = wallpaper_path + "project.json";
// set the working directory to the project folder
IrrlichtContext->getDevice ()->getFileSystem ()->changeWorkingDirectoryTo (wallpaper_path);
}
if (audio_support == true)
if (shouldEnableAudio == true)
{
int mixer_flags = MIX_INIT_MP3 | MIX_INIT_FLAC | MIX_INIT_OGG;
if (SDL_Init (SDL_INIT_AUDIO) < 0 || mixer_flags != Mix_Init (mixer_flags))
{
IrrlichtContext->getDevice ()->getLogger ()->log ("Cannot initialize SDL audio system", irr::ELL_ERROR);
return -1;
return 2;
}
// initialize audio engine
@ -295,52 +165,29 @@ int main (int argc, char* argv[])
}
WallpaperEngine::Core::CProject* project = WallpaperEngine::Core::CProject::fromFile (project_path);
WallpaperEngine::Render::CScene* sceneRender = new WallpaperEngine::Render::CScene (project, IrrlichtContext);
WallpaperEngine::Render::CScene* scene = new WallpaperEngine::Render::CScene (project, IrrlichtContext);
irr::u32 lastTime = 0;
irr::u32 minimumTime = 1000 / max_fps;
irr::u32 minimumTime = 1000 / maximumFPS;
irr::u32 currentTime = 0;
irr::u32 startTime = 0;
irr::u32 endTime = 0;
IrrlichtContext->getDevice ()->getSceneManager ()->setAmbientLight (sceneRender->getScene ()->getAmbientColor ().toSColor ());
IrrlichtContext->getDevice ()->getSceneManager ()->setAmbientLight (scene->getScene ()->getAmbientColor ().toSColor ());
while (IrrlichtContext && IrrlichtContext->getDevice () && IrrlichtContext->getDevice ()->run ())
{
if (IrrlichtContext->getDevice ()->getVideoDriver () == nullptr)
continue;
// if (device->isWindowActive ())
{
currentTime = startTime = IrrlichtContext->getDevice ()->getTimer ()->getTime ();
g_Time = currentTime / 1000.0f;
currentTime = startTime = IrrlichtContext->getDevice ()->getTimer ()->getTime ();
g_Time = currentTime / 1000.0f;
if (Viewports.size () > 0)
{
auto cur = Viewports.begin ();
auto end = Viewports.end ();
IrrlichtContext->renderFrame (scene);
for (; cur != end; cur ++)
{
// change viewport to render to the correct portion of the display
IrrlichtContext->getDevice ()->getVideoDriver ()->setViewPort (*cur);
endTime = IrrlichtContext->getDevice ()->getTimer ()->getTime ();
IrrlichtContext->getDevice ()->getVideoDriver ()->beginScene (false, true, sceneRender->getScene ()->getClearColor ().toSColor());
IrrlichtContext->getDevice ()->getSceneManager ()->drawAll ();
IrrlichtContext->getDevice ()->getVideoDriver ()->endScene ();
}
}
else
{
IrrlichtContext->getDevice ()->getVideoDriver ()->beginScene (true, true, sceneRender->getScene ()->getClearColor ().toSColor());
IrrlichtContext->getDevice ()->getSceneManager ()->drawAll ();
IrrlichtContext->getDevice ()->getVideoDriver ()->endScene ();
}
endTime = IrrlichtContext->getDevice ()->getTimer ()->getTime ();
IrrlichtContext->getDevice ()->sleep (minimumTime - (endTime - startTime), false);
}
IrrlichtContext->getDevice ()->sleep (minimumTime - (endTime - startTime), false);
}
SDL_Quit ();

View File

@ -1,13 +1,177 @@
#include <iostream>
#include <stdexcept>
#include <utility>
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
#include "WallpaperEngine/Irrlicht/CImageLoaderTEX.h"
#include "WallpaperEngine/Irrlicht/CPkgReader.h"
#include "CContext.h"
using namespace WallpaperEngine::Irrlicht;
CContext::CContext (std::vector<std::string> screens, bool isRootWindow) :
m_screens (std::move(screens)),
m_isRootWindow (isRootWindow)
{
}
void CContext::setDevice (irr::IrrlichtDevice* device)
{
this->m_device = device;
}
void CContext::initializeContext ()
{
irr::SIrrlichtCreationParameters irrlichtCreationParameters;
// prepare basic configuration for irrlicht
irrlichtCreationParameters.AntiAlias = 8;
irrlichtCreationParameters.Bits = 16;
// _irr_params.DeviceType = Irrlicht::EIDT_X11;
irrlichtCreationParameters.DriverType = irr::video::EDT_OPENGL;
irrlichtCreationParameters.Doublebuffer = false;
irrlichtCreationParameters.EventReceiver = nullptr;
irrlichtCreationParameters.Fullscreen = false;
irrlichtCreationParameters.HandleSRGB = false;
irrlichtCreationParameters.IgnoreInput = true;
irrlichtCreationParameters.Stencilbuffer = true;
irrlichtCreationParameters.UsePerformanceTimer = false;
irrlichtCreationParameters.Vsync = false;
irrlichtCreationParameters.WithAlphaChannel = false;
irrlichtCreationParameters.ZBufferBits = 24;
irrlichtCreationParameters.LoggingLevel = irr::ELL_DEBUG;
this->initializeViewports (irrlichtCreationParameters);
this->setDevice (irr::createDeviceEx (irrlichtCreationParameters));
if (this->getDevice () == nullptr)
{
throw std::runtime_error ("Cannot create irrlicht device");
}
this->getDevice ()->setWindowCaption (L"Test game");
// check for ps and vs support
if (
this->getDevice ()->getVideoDriver()->queryFeature (irr::video::EVDF_PIXEL_SHADER_2_0) == false &&
this->getDevice ()->getVideoDriver()->queryFeature (irr::video::EVDF_ARB_FRAGMENT_PROGRAM_1) == false)
{
throw std::runtime_error ("Pixel Shader 2.0 not supported by your video driver/hardware");
}
if (
this->getDevice ()->getVideoDriver()->queryFeature (irr::video::EVDF_VERTEX_SHADER_2_0) == false &&
this->getDevice ()->getVideoDriver()->queryFeature (irr::video::EVDF_ARB_VERTEX_PROGRAM_1) == false)
{
throw std::runtime_error ("Vertex Shader 2.0 not supported by your video driver/hardware");
}
if (this->getDevice ()->getVideoDriver ()->queryFeature (irr::video::EVDF_RENDER_TO_TARGET) == false)
{
throw std::runtime_error ("Render to texture not supported by your video driver/hardware");
}
// load the assets from wallpaper engine
this->getDevice ()->getFileSystem ()->addFileArchive ("assets.zip", true, false);
// register custom loaders
this->getDevice ()->getVideoDriver()->addExternalImageLoader (
new WallpaperEngine::Irrlicht::CImageLoaderTex (this)
);
this->getDevice ()->getFileSystem ()->addArchiveLoader (
new WallpaperEngine::Irrlicht::CArchiveLoaderPkg (this)
);
}
void CContext::initializeViewports (irr::SIrrlichtCreationParameters &irrlichtCreationParameters)
{
if (this->m_isRootWindow == false || this->m_screens.empty () == true)
return;
Display* display = XOpenDisplay (nullptr);
int xrandr_result, xrandr_error;
if (!XRRQueryExtension (display, &xrandr_result, &xrandr_error))
{
std::cerr << "XRandr is not present, cannot detect specified screens, running in window mode" << std::endl;
return;
}
XRRScreenResources* screenResources = XRRGetScreenResources (display, DefaultRootWindow (display));
// there are some situations where xrandr returns null (like screen not using the extension)
if (screenResources == nullptr)
return;
for (int i = 0; i < screenResources->noutput; i ++)
{
XRROutputInfo* info = XRRGetOutputInfo (display, screenResources, screenResources->outputs [i]);
// there are some situations where xrandr returns null (like screen not using the extension)
if (info == nullptr)
continue;
auto cur = this->m_screens.begin ();
auto end = this->m_screens.end ();
for (; cur != end; cur ++)
{
if (info->connection == RR_Connected && strcmp (info->name, (*cur).c_str ()) == 0)
{
XRRCrtcInfo* crtc = XRRGetCrtcInfo (display, screenResources, info->crtc);
std::cout << "Found requested screen: " << info->name << " -> " << crtc->x << "x" << crtc->y << ":" << crtc->width << "x" << crtc->height << std::endl;
irr::core::rect<irr::s32> viewport;
viewport.UpperLeftCorner.X = crtc->x;
viewport.UpperLeftCorner.Y = crtc->y;
viewport.LowerRightCorner.X = crtc->x + crtc->width;
viewport.LowerRightCorner.Y = crtc->y + crtc->height;
this->m_viewports.push_back (viewport);
XRRFreeCrtcInfo (crtc);
}
}
XRRFreeOutputInfo (info);
}
XRRFreeScreenResources (screenResources);
irrlichtCreationParameters.WindowId = reinterpret_cast<void*> (DefaultRootWindow (display));
}
void CContext::renderFrame (Render::CScene* scene)
{
if (this->m_viewports.empty () == true)
{
this->getDevice ()->getVideoDriver ()->beginScene (true, true, scene->getScene ()->getClearColor ().toSColor());
this->getDevice ()->getSceneManager ()->drawAll ();
this->getDevice ()->getVideoDriver ()->endScene ();
}
else
{
auto cur = this->m_viewports.begin ();
auto end = this->m_viewports.end ();
for (; cur != end; cur ++)
{
// change viewport to render to the correct portion of the display
this->getDevice ()->getVideoDriver ()->setViewPort (*cur);
this->getDevice ()->getVideoDriver ()->beginScene (false, true, scene->getScene ()->getClearColor ().toSColor());
this->getDevice ()->getSceneManager ()->drawAll ();
this->getDevice ()->getVideoDriver ()->endScene ();
}
}
}
irr::IrrlichtDevice* CContext::getDevice ()
{
return this->m_device;

View File

@ -1,15 +1,28 @@
#pragma once
#include <vector>
#include <string>
#include <irrlicht/irrlicht.h>
#include "WallpaperEngine/Render/CScene.h"
namespace WallpaperEngine::Render
{
class CScene;
};
namespace WallpaperEngine::Irrlicht
{
class CContext
{
public:
CContext (std::vector<std::string> screens, bool isRootWindow = false);
void setDevice (irr::IrrlichtDevice* device);
void initializeContext ();
void renderFrame (Render::CScene* scene);
irr::IrrlichtDevice* getDevice ();
irr::io::path resolveMaterials (const std::string& materialName);
@ -17,8 +30,14 @@ namespace WallpaperEngine::Irrlicht
irr::io::path resolveFragmentShader (const std::string& fragmentShader);
irr::io::path resolveIncludeShader (const std::string& includeShader);
private:
void initializeViewports (irr::SIrrlichtCreationParameters& irrlichtCreationParameters);
irr::io::path resolveFile (const irr::io::path& file);
irr::IrrlichtDevice* m_device;
std::vector<std::string> m_screens;
std::vector<irr::core::recti> m_viewports;
bool m_isRootWindow;
};
};

View File

@ -1,3 +1,5 @@
#include "WallpaperEngine/Irrlicht/CContext.h"
#include "WallpaperEngine/Core/Objects/CImage.h"
#include "WallpaperEngine/Core/Objects/CSound.h"

View File

@ -7,6 +7,11 @@
#include "WallpaperEngine/Irrlicht/CContext.h"
namespace WallpaperEngine::Irrlicht
{
class CContext;
};
namespace WallpaperEngine::Render
{
class CCamera;

View File

@ -126,7 +126,6 @@ void CImage::generatePass (Core::Objects::Images::Materials::CPassess* pass)
for (int textureNumber = 0; texturesCur != texturesEnd; texturesCur ++, textureNumber ++)
{
// TODO: LOOK THIS UP PROPERLY
irr::io::path texturepath = this->getScene ()->getContext ()->resolveMaterials (*texturesCur);
irr::video::ITexture* texture = nullptr;

View File

@ -11,7 +11,6 @@ using namespace WallpaperEngine;
namespace WallpaperEngine::Render::Objects
{
// TODO: MOVE IShaderConstantSetCallBack TO IT'S OWN CLASS OR ORGANIZE THIS BETTER
class CImage : public CObject, public irr::video::IShaderConstantSetCallBack
{
public:

View File

@ -1,3 +1,4 @@
#include <SDL.h>
#include <SDL_rwops.h>
#include <SDL_mixer.h>
@ -18,8 +19,13 @@ CSound::CSound (CScene* scene, Core::Objects::CSound* sound) :
void CSound::load ()
{
std::vector<std::string>::const_iterator cur = this->m_sound->getSounds ().begin ();
std::vector<std::string>::const_iterator end = this->m_sound->getSounds ().end ();
if (SDL_WasInit (SDL_INIT_AUDIO) != SDL_INIT_AUDIO)
{
return;
}
auto cur = this->m_sound->getSounds ().begin ();
auto end = this->m_sound->getSounds ().end ();
for (; cur != end; cur ++)
{
@ -51,8 +57,13 @@ void CSound::load ()
}
void CSound::play ()
{
std::vector<Mix_Music*>::const_iterator mixcur = this->m_sdl.begin ();
std::vector<Mix_Music*>::const_iterator mixend = this->m_sdl.end ();
if (SDL_WasInit (SDL_INIT_AUDIO) != SDL_INIT_AUDIO)
{
return;
}
auto mixcur = this->m_sdl.begin ();
auto mixend = this->m_sdl.end ();
for (; mixcur != mixend; mixcur ++)
{