diff --git a/dependencies/subprojects/animationwindow/include/AnimationWindow.h b/dependencies/subprojects/animationwindow/include/AnimationWindow.h index 680c98d566992783334b6d7be987f6e12487243a..8fa1c1b4470e0c160e0134a0040dc20c9183d681 100644 --- a/dependencies/subprojects/animationwindow/include/AnimationWindow.h +++ b/dependencies/subprojects/animationwindow/include/AnimationWindow.h @@ -51,7 +51,7 @@ class AnimationWindow { bool keepPreviousFrame = false; bool closeRequested = false; - bool render=false; + bool isSoftwareRenderer = false; std::vector<std::reference_wrapper<TDT4102::Widget>> widgets; @@ -60,7 +60,7 @@ class AnimationWindow { // SDL related context SDL_Window* windowHandle = nullptr; SDL_Renderer* rendererHandle = nullptr; - SDL_Surface* surf; + SDL_Surface* screenshotSurface = nullptr; // Nuklear related context nk_context* context = nullptr; @@ -75,7 +75,7 @@ class AnimationWindow { public: - explicit AnimationWindow(int x = 50, int y = 50, int width = 1024, int height = 768, const std::string& title = "Animation Window", bool softwareRender = false); + explicit AnimationWindow(int x = 50, int y = 50, int width = 1024, int height = 768, const std::string& title = "Animation Window", bool useSoftwareRenderer = false); ~AnimationWindow(); void screenshot(std::string name); void simulateClickAtPoint(TDT4102::Point p); diff --git a/dependencies/subprojects/animationwindow/src/AnimationWindow.cpp b/dependencies/subprojects/animationwindow/src/AnimationWindow.cpp index bdd30c230347fb493c1d41a3e84e4efc62a6b7d9..d9c7257d7a09e444d393d622e5ea67fbd22fa453 100644 --- a/dependencies/subprojects/animationwindow/src/AnimationWindow.cpp +++ b/dependencies/subprojects/animationwindow/src/AnimationWindow.cpp @@ -23,7 +23,7 @@ static bool sdlHasBeenInitialised = false; -TDT4102::AnimationWindow::AnimationWindow(int x, int y, int width, int height, const std::string& title, bool softwareRender) { +TDT4102::AnimationWindow::AnimationWindow(int x, int y, int width, int height, const std::string& title, bool useSoftwareRenderer) { // Initialise SDL if it has not already been if (!sdlHasBeenInitialised) { if (SDL_Init(SDL_INIT_VIDEO) < 0) { @@ -32,10 +32,14 @@ TDT4102::AnimationWindow::AnimationWindow(int x, int y, int width, int height, c sdlHasBeenInitialised = true; } // Open a new window - if (softwareRender){ - render=true; - surf = SDL_CreateRGBSurface(0, width, height, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000); - rendererHandle = SDL_CreateSoftwareRenderer(surf); + if (useSoftwareRenderer) { + isSoftwareRenderer = true; + screenshotSurface = SDL_CreateRGBSurface(0, width, height, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000); + if (screenshotSurface == nullptr) { + throw std::runtime_error("Failed to create an AnimationWindow: The SDL backend could not create a RGB Surface.\nError details: " + std::string(SDL_GetError())); + } + // Create a software renderer + rendererHandle = SDL_CreateSoftwareRenderer(screenshotSurface); } else{ windowHandle = SDL_CreateWindow( @@ -43,6 +47,7 @@ TDT4102::AnimationWindow::AnimationWindow(int x, int y, int width, int height, c if (windowHandle == nullptr) { throw std::runtime_error("Failed to create an AnimationWindow: The SDL backend could not open a new window.\nError details: " + std::string(SDL_GetError())); } + // Create a window renderer rendererHandle = SDL_CreateRenderer(windowHandle, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); } @@ -52,9 +57,6 @@ TDT4102::AnimationWindow::AnimationWindow(int x, int y, int width, int height, c - // Create a renderer - - // Default window background colour SDL_SetRenderDrawColor(rendererHandle, backgroundColour.redChannel, backgroundColour.greenChannel, backgroundColour.blueChannel, backgroundColour.alphaChannel); SDL_RenderClear(rendererHandle); @@ -64,7 +66,7 @@ TDT4102::AnimationWindow::AnimationWindow(int x, int y, int width, int height, c std::cout << "Created an SDL renderer with name: " << rendererInfo.name << std::endl; - context = nk_sdl_init(softwareRender ? nullptr:windowHandle, rendererHandle); + context = nk_sdl_init(isSoftwareRenderer ? nullptr : windowHandle, rendererHandle); fontCache.initialise(); fontCache.setFont(context, Font::defaultFont, 18); nk_clear(context); @@ -88,6 +90,10 @@ void TDT4102::AnimationWindow::destroy() { nk_free(context); context = nullptr; } + if (screenshotSurface != nullptr) { + SDL_FreeSurface(screenshotSurface); + screenshotSurface = nullptr; + } } void TDT4102::AnimationWindow::show_frame() { @@ -153,16 +159,16 @@ void TDT4102::AnimationWindow::next_frame() { void TDT4102::AnimationWindow::screenshot(std::string name){ - if (!render){ - std::cout << "screenshot only works in software render mode" << std::endl; - return; + if (!isSoftwareRenderer){ + throw std::runtime_error("Screenshot utility only works in software render mode"); } update_gui(); nk_sdl_render(NK_ANTI_ALIASING_ON); - std::cout<<"screenshot"<<std::endl; TDT4102::Point windowDimensions = getWindowDimensions(); - unsigned error = lodepng::encode("screenshot_"+name+".png", reinterpret_cast<const unsigned char*>(surf->pixels), static_cast<unsigned>(windowDimensions.x), static_cast<unsigned>(windowDimensions.y)); - if(error) std::cout << "encoder error " << error << ": "<< lodepng_error_text(error) << std::endl; + unsigned int error = lodepng::encode("screenshot_"+name+".png", reinterpret_cast<const unsigned char*>(screenshotSurface->pixels), static_cast<unsigned int>(windowDimensions.x), static_cast<unsigned int>(windowDimensions.y)); + if (error) { + throw std::runtime_error("Lodepng: Failed to encode, error code " + std::to_string(error) + ":\n" + std::string((lodepng_error_text(error)))); + } std::string content = ""; for (Widget& widget : widgets){ @@ -183,15 +189,15 @@ void TDT4102::AnimationWindow::screenshot(std::string name){ } void TDT4102::AnimationWindow::simulateClickAtPoint(TDT4102::Point p){ - std::cout<<"pressPoint"<<std::endl; - int posx=p.x; - int posy=p.y; + int xPos = p.x; + int yPos = p.y; + SDL_Event event; event.type = SDL_MOUSEBUTTONDOWN; event.button.button = SDL_BUTTON_LEFT; event.button.state = SDL_PRESSED; - event.button.x = posx; - event.button.y = posy; + event.button.x = xPos; + event.button.y = yPos; SDL_PushEvent(&event); next_frame(); event.type = SDL_MOUSEBUTTONUP; @@ -202,17 +208,15 @@ void TDT4102::AnimationWindow::simulateClickAtPoint(TDT4102::Point p){ } void TDT4102::AnimationWindow::simulateClickOnWidget(int n){ - std::cout<<"pressKey"<<std::endl; - - int posx=widgets.at(n).get().position.x+20; - int posy=widgets.at(n).get().position.y+5; + int xPos = widgets.at(n).get().position.x+20; + int yPos = widgets.at(n).get().position.y+5; SDL_Event event; event.type = SDL_MOUSEBUTTONDOWN; event.button.button = SDL_BUTTON_LEFT; event.button.state = SDL_PRESSED; - event.button.x = posx; - event.button.y = posy; + event.button.x = xPos; + event.button.y = yPos; SDL_PushEvent(&event); next_frame(); event.type = SDL_MOUSEBUTTONUP;