#include "sdlpp_scene.hpp" namespace SDLPP { Scene::Scene( std::shared_ptr< Renderer > &r ) : renderer( r ) { SDL_SetRenderDrawColor( renderer->getRendererPtr(), 0xFF, 0xFF, 0xFF, 0xFF ); prev_ticks = SDL_GetTicks(); } void Scene::addObject( const std::shared_ptr< RenderObject > &obj ) { std::lock_guard< std::mutex > lock( render_mutex ); render_objects.push_back( obj ); obj->setSceneID( ++max_object_id ); if ( obj->hasCollisions() ) { collision_objects.push_back( obj ); } if ( render_objects.size() == 1 ) { leftmost_obj = obj; rightmost_obj = obj; } else { auto rect = obj->getDoubleRect(); auto leftmost_rect = leftmost_obj->getDoubleRect(); if ( rect.first.first < leftmost_rect.first.first ) leftmost_obj = obj; auto rightmost_rect = rightmost_obj->getDoubleRect(); if ( rect.first.first + rect.second.first > rightmost_rect.first.first + rightmost_rect.second.first ) rightmost_obj = obj; } } void Scene::setZIndex( const std::shared_ptr< RenderObject > &obj, int index ) { std::lock_guard< std::mutex > guard( render_mutex ); int original_index = 0; for ( long unsigned int i = 0; i < render_objects.size(); i++ ) { if ( render_objects[i] == obj ) { original_index = i; } } if ( original_index == index ) return; if ( original_index > index ) original_index++; render_objects.insert( render_objects.begin() + index, obj ); render_objects.erase( render_objects.begin() + original_index ); } void Scene::moveDownZ( const std::shared_ptr< RenderObject > &obj ) { moveZ( obj, -1 ); } void Scene::moveUpZ( const std::shared_ptr< RenderObject > &obj ) { moveZ( obj, 1 ); } void Scene::moveZ( const std::shared_ptr< RenderObject > &obj, int addition ) { int original_index = 0; for ( long unsigned int i = 0; i < render_objects.size(); i++ ) { if ( render_objects[i] == obj ) { original_index = i; } } std::iter_swap( render_objects.begin() + original_index, render_objects.begin() + original_index + addition ); } // TODO addCollision std::shared_ptr< RenderObject > Scene::getObject( int index ) { return render_objects[index]; } std::vector< std::shared_ptr< RenderObject > > Scene::getObjects() { return render_objects; } std::vector< std::shared_ptr< RenderObject > > Scene::getObjects( const std::unordered_set< int > &objectIDs ) { std::vector< std::shared_ptr< RenderObject > > ret{}; for ( const auto &x : render_objects ) { // check if object exists because of possible race condition if ( x && objectIDs.find( x->getId() ) != objectIDs.end() ) { ret.push_back( x ); } } return ret; } void Scene::movement() { checkKilled(); std::lock_guard< std::mutex > lock( render_mutex ); int now_ticks = SDL_GetTicks(); for ( const auto &x : render_objects ) { x->move( now_ticks - prev_ticks ); } prev_ticks = now_ticks; } std::vector< std::shared_ptr< RenderObject > > Scene::getCollisions( RenderObject &r ) { if ( r.getHidden() ) return {}; std::vector< std::shared_ptr< RenderObject > > ret{}; for ( const auto &x : collision_objects ) { if ( x->colidesWith( r ) ) { ret.push_back( x ); } } return ret; } std::vector< std::shared_ptr< RenderObject > > Scene::getCollisions( RenderObject &r, const std::unordered_set< int > &objectIDs ) { if ( r.getHidden() ) return {}; std::vector< std::shared_ptr< RenderObject > > ret{}; for ( const auto &x : collision_objects ) { if ( objectIDs.find( x->getId() ) != objectIDs.end() && x->colidesWith( r ) ) { ret.push_back( x ); } } return ret; } void Scene::renderScene( bool clear_renderer ) { checkKilled(); std::lock_guard< std::mutex > lock( render_mutex ); if ( clear_renderer ) SDL_RenderClear( renderer->getRendererPtr() ); if ( background && background->getTexturePtr() ) SDL_RenderCopy( renderer->getRendererPtr(), background->getTexturePtr(), NULL, NULL ); for ( const auto &x : render_objects ) { x->render(); } } void Scene::presentScene() { SDL_RenderPresent( renderer->getRendererPtr() ); } void Scene::setBackground( std::shared_ptr< Texture > bg ) { background = bg; } void Scene::setBackground( const std::string &img_path ) { background = std::make_shared< Texture >( renderer, img_path ); } void Scene::updateSizeAndPosition() { checkKilled(); std::lock_guard< std::mutex > lock( render_mutex ); for ( auto &x : render_objects ) { x->updateSizeAndPosition(); for ( auto &col : x->getCollisions() ) { col->updateCollision( x->collisionPushX(), x->collisionPushY(), x->collisionWidth(), x->collisionHeight() ); } } } void Scene::moveEverything( double x, double y ) { checkKilled(); std::lock_guard< std::mutex > lock( render_mutex ); for ( auto &obj : render_objects ) { if ( obj->getPermanent() ) continue; auto curPos = obj->getDoubleRect(); obj->setPos( curPos.first.first + x, curPos.first.second + y ); } } const std::shared_ptr< RenderObject > &Scene::leftmost() { return leftmost_obj; } const std::shared_ptr< RenderObject > &Scene::rightmost() { return rightmost_obj; } std::pair< int, int > Scene::getDimensions() const { return renderer->getDimensions(); } int Scene::getWidth() const { return renderer->getWidth(); } int Scene::getHeight() const { return renderer->getHeight(); } Renderer &Scene::getRenderer() { return *renderer; } std::shared_ptr< Renderer > Scene::getRendererShared() { return renderer; } void Scene::setPrevTicks( int ticks ) { prev_ticks = ticks; } void Scene::saveScene() { saved_render_objects.clear(); saved_collision_objects.clear(); for ( auto &obj : render_objects ) { if ( !obj->isStatic() ) saved_render_objects.push_back( obj->copySelf() ); else saved_render_objects.push_back( obj ); } for ( auto &obj : collision_objects ) { if ( !obj->isStatic() ) saved_collision_objects.push_back( obj->copySelf() ); else saved_collision_objects.push_back( obj ); } } void Scene::resetScene() { render_objects.clear(); collision_objects.clear(); for ( auto &obj : saved_render_objects ) { if ( !obj->isStatic() ) render_objects.push_back( obj->copySelf() ); else render_objects.push_back( obj ); } for ( auto &obj : saved_collision_objects ) { if ( !obj->isStatic() ) collision_objects.push_back( obj->copySelf() ); else collision_objects.push_back( obj ); } } void Scene::checkKilled() { std::lock_guard< std::mutex > lock( render_mutex ); std::vector< int > killed; std::vector< int > killed_collisions; for ( long unsigned int i = 0; i < render_objects.size(); i++ ) { if ( render_objects[i]->getKilled() ) killed.push_back( i ); if ( i < collision_objects.size() && collision_objects[i]->getKilled() ) killed_collisions.push_back( i ); } // reverse so we don't screw up indexing while going thorugh the kill // indices std::reverse( killed.begin(), killed.end() ); std::reverse( killed_collisions.begin(), killed_collisions.end() ); for ( auto &index : killed ) { render_objects.erase( render_objects.begin() + index ); } for ( auto &index : killed_collisions ) { collision_objects.erase( collision_objects.begin() + index ); } } } // namespace SDLPP