zv0n
f92a94ef01
Since textures should only be manipulated in the main thread (as well as rendering), let programmers deal with ensuring the texture is available during rendercopy
235 lines
7.8 KiB
C++
235 lines
7.8 KiB
C++
#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
|