<commit_before>/*
 *  PlayState.cpp
 *  Normal "play" state
 *
 *  Created by Marcelo Cohen on 08/13.
 *  Copyright 2013 PUCRS. All rights reserved.
 *
 */

#include <iostream>
#include <cmath>
#include "Game.h"
#include "PlayState.h"
#include "MenuState.h"
#include "InputManager.h"

#include "ItemShells.h"
#include "ItemShotgun.h"
#include "ItemRocketLauncher.h"
#include "ItemRocket.h"

#include "Player.h"
#include "PlayerDriver.h"

#include "Imp.h"
#include "CyberDemon.h"
#include "PinkDemon.h"
#include "BaronOfHell.h"

PlayState PlayState::m_PlayState;

using namespace std;

void PlayState::init()
{

    im = cgf::InputManager::instance();

    im->addKeyInput("left", sf::Keyboard::Left);
    im->addKeyInput("right", sf::Keyboard::Right);
    im->addKeyInput("up", sf::Keyboard::Up);
    im->addKeyInput("down", sf::Keyboard::Down);
    im->addKeyInput("one", sf::Keyboard::Num1);
    im->addKeyInput("two", sf::Keyboard::Num2);
    im->addKeyInput("three", sf::Keyboard::Num3);
    im->addKeyInput("quit", sf::Keyboard::Escape);
    im->addKeyInput("zoomin", sf::Keyboard::Z);
    im->addKeyInput("zoomout", sf::Keyboard::X);
    im->addMouseInput("rightclick", sf::Mouse::Right);

    map = new tmx::MapLoader("data/maps");
    //map->Load("dungeon-tilesets2.tmx");
    map->Load("level1.tmx");

    projectiles = new Projectiles();
    player = new Player(projectiles);
    playerdriver = new PlayerDriver(*player, im);
    monsters = new Monsters(player);
    items = new Items(player->getInventory());

    firstTime = true;

    // BEGIN MANUALLY SET MAP ENTITIES
    monsters->spawnNew(new Imp(150, 90, 3));
    monsters->spawnNew(new PinkDemon(500, 360, 3));
    monsters->spawnNew(new PinkDemon(300, 310, 3));
    monsters->spawnNew(new PinkDemon(360, 240, 3));
    monsters->spawnNew(new PinkDemon(950, 650, 3));
    monsters->spawnNew(new BaronOfHell(1000, 270, 3));
    monsters->spawnNew(new BaronOfHell(1200, 380, 3));

    monsters->spawnNew(new Imp(500, 630, 3));
    monsters->spawnNew(new Imp(340, 630, 3));
    monsters->spawnNew(new Imp(480, 760, 3));
    monsters->spawnNew(new Imp(300, 775, 3));

    monsters->spawnNew(new CyberDemon(1250, 900, 3));

    items->spawnNew(new ItemShotgun(700, 420));
    items->spawnNew(new ItemShells(740, 440));
    items->spawnNew(new ItemShells(770, 480));
    items->spawnNew(new ItemShells(670, 430));

    items->spawnNew(new ItemRocketLauncher(700, 750));
    items->spawnNew(new ItemRocket(90, 850));
    items->spawnNew(new ItemRocket(120, 900));
    items->spawnNew(new ItemRocket(170, 850));
    // END MANUALLY SET MAP ENTITIES

	cout << "PlayState Init Successful" << endl;
}

void PlayState::cleanup()
{
	cout << "PlayState Clean Successful" << endl;
	delete map;
	delete playerdriver;
	delete projectiles;
	delete monsters;
	delete items;
}

void PlayState::pause()
{
	cout << "PlayState Paused" << endl;
}

void PlayState::resume()
{
	cout << "PlayState Resumed" << endl;
}

void PlayState::handleEvents(cgf::Game* game)
{
    sf::Event event;
    sf::View view = screen->getView();

    while (screen->pollEvent(event)){

        if(event.type == sf::Event::Closed){
            game->quit();
        }

        if(event.key.code == sf::Keyboard::S){
            game->toggleStats();
        }
        playerdriver->receiveInput(event);
    }

    if(im->testEvent("quit") || im->testEvent("rightclick"))
        game->quit();

    if(im->testEvent("zoomin"))
    {
        view.zoom(1.01);
        screen->setView(view);
    }
    else if(im->testEvent("zoomout"))
    {
        view.zoom(0.99);
        screen->setView(view);
    }

}

void PlayState::update(cgf::Game* game)
{
    if(firstTime) {
        // Background audio from http://www.looperman.com/loops/detail/77776
        music.openFromFile("data/audio/background-loop.wav");
        music.setVolume(30);
        music.setLoop(true);
        music.play();
        firstTime = false;
    }

    screen = game->getScreen();
    checkCollision(2, game, player->getSprite());
    centerMapOnPlayer();

    // check projectile collisions.
    bool repeat_dreaded_bubble_sort = true;
    while (repeat_dreaded_bubble_sort){
        repeat_dreaded_bubble_sort = false;

        for (int i=0; i<projectiles->projectiles.size(); ++i){

            cgf::Sprite *prjspr = projectiles->projectiles[i]->sprite;

            // check against the map
            if (checkCollision(2, game, prjspr)){
                projectiles->kill(i);
                repeat_dreaded_bubble_sort = true;
                break;
            }

            // check against monsters
            bool i_wanna_cry = false;
            for (int j=0; j<monsters->monsters.size(); ++j){

                if (!(monsters->monsters[j]->isAlive())){
                    continue;
                }

                cgf::Sprite *monspr = monsters->monsters[j]->sprite;

                if (prjspr->circleCollision(*monspr)){
                    projectiles->kill(i);
                    monsters->kill(j);
                    i_wanna_cry = true;
                    break;
                }
            }
            if (i_wanna_cry){
                repeat_dreaded_bubble_sort = true;
                break;
            }
        }
    }

    // check collisions between player and any items
    items->checkCollisionsWithPlayer(player);
}

bool PlayState::checkCollision(u_int8_t layer, cgf::Game* game, cgf::Sprite* obj)
{
    int i, x1, x2, y1, y2;
    bool bump = false;

    // Get the limits of the map
    sf::Vector2u mapsize = map->GetMapSize();
    // Get the width and height of a single tile
    sf::Vector2u tilesize = map->GetMapTileSize();

    mapsize.x /= tilesize.x;
    mapsize.y /= tilesize.y;
    mapsize.x--;
    mapsize.y--;

    // Get the height and width of the object (in this case, 100% of a tile)
    sf::Vector2u objsize = obj->getSize();
    objsize.x *= obj->getScale().x;
    objsize.y *= obj->getScale().y;

    float px = obj->getPosition().x;
    float py = obj->getPosition().y;

    double deltaTime = game->getUpdateInterval();

    sf::Vector2f offset(obj->getXspeed()/1000 * deltaTime, obj->getYspeed()/1000 * deltaTime);

    float vx = offset.x;
    float vy = offset.y;

    // Test the horizontal movement first
    i = objsize.y > tilesize.y ? tilesize.y : objsize.y;

    for (;;)
    {
        x1 = (px + vx) / tilesize.x;
        x2 = (px + vx + objsize.x - 1) / tilesize.x;

        y1 = (py) / tilesize.y;
        y2 = (py + i - 1) / tilesize.y;

        if (x1 >= 0 && x2 <= mapsize.x && y1 >= 0 && y2 < mapsize.y)
        {
            if (vx > 0)
            {
                // Trying to move right

                int upRight   = getCellFromMap(layer, x2*tilesize.x, y1*tilesize.y);
                int downRight = getCellFromMap(layer, x2*tilesize.x, y2*tilesize.y);
                if (upRight || downRight)
                {
                    // Place the player as close to the solid tile as possible
                    px = x2 * tilesize.x;
                    px -= objsize.x;// + 1;
                    vx = 0;
                    bump = true;
                }
            }

            else if (vx < 0)
            {
                // Trying to move left

                int upLeft   = getCellFromMap(layer, x1*tilesize.x, y1*tilesize.y);
                int downLeft = getCellFromMap(layer, x1*tilesize.x, y2*tilesize.y);
                if (upLeft || downLeft)
                {
                    // Place the player as close to the solid tile as possible
                    px = (x1+1) * tilesize.x;
                    vx = 0;
                    bump = true;
                }
            }
        }

        if (i == objsize.y) // Checked player height with all tiles ?
        {
            break;
        }

        i += tilesize.y; // done, check next tile upwards

        if (i > objsize.y)
        {
            i = objsize.y;
        }
    }

    // Now test the vertical movement

    i = objsize.x > tilesize.x ? tilesize.x : objsize.x;

    for (;;)
    {
        x1 = (px / tilesize.x);
        x2 = ((px + i-1) / tilesize.x);

        y1 = ((py + vy) / tilesize.y);
        y2 = ((py + vy + objsize.y-1) / tilesize.y);

        if (x1 >= 0 && x2 < mapsize.x && y1 >= 0 && y2 <= mapsize.y)
        {
            if (vy > 0)
            {
                // Trying to move down
                int downLeft  = getCellFromMap(layer, x1*tilesize.x, y2*tilesize.y);
                int downRight = getCellFromMap(layer, x2*tilesize.x, y2*tilesize.y);
                if (downLeft || downRight)
                {
                    // Place the player as close to the solid tile as possible
                    py = y2 * tilesize.y;
                    py -= objsize.y;
                    vy = 0;
                    bump = true;
                }
            }

            else if (vy < 0)
            {
                // Trying to move up

                int upLeft  = getCellFromMap(layer, x1*tilesize.x, y1*tilesize.y);
                int upRight = getCellFromMap(layer, x2*tilesize.x, y1*tilesize.y);
                if (upLeft || upRight)
                {
                    // Place the player as close to the solid tile as possible
                    py = (y1 + 1) * tilesize.y;
                    vy = 0;
                    bump = true;
                }
            }
        }

        if (i == objsize.x)
        {
            break;
        }

        i += tilesize.x; // done, check next tile to the right

        if (i > objsize.x)
        {
            i = objsize.x;
        }
    }

    // Now apply the movement and animation

    obj->setPosition(px+vx,py+vy);
    px = obj->getPosition().x;
    py = obj->getPosition().y;

    obj->update(deltaTime, false); // only update animation

    // Check collision with edges of map
    if (px < 0)
        obj->setPosition(px,py);
    else if (px + objsize.x >= mapsize.x * tilesize.x)
        obj->setPosition(mapsize.x*tilesize.x - objsize.x - 1,py);

    if(py < 0)
        obj->setPosition(px,0);
    else if(py + objsize.y >= mapsize.y * tilesize.y)
        obj->setPosition(px, mapsize.y*tilesize.y - objsize.y - 1);

    return bump;
}

sf::Uint16 PlayState::getCellFromMap(uint8_t layernum, float x, float y)
{
    auto layers = map->GetLayers();
    tmx::MapLayer& layer = layers[layernum];
    sf::Vector2u mapsize = map->GetMapSize();
    sf::Vector2u tilesize = map->GetMapTileSize();
    mapsize.x /= tilesize.x;
    mapsize.y /= tilesize.y;
    int col = floor(x / tilesize.x);
    int row = floor(y / tilesize.y);
    return layer.tiles[row*mapsize.x + col].gid;
}

void PlayState::centerMapOnPlayer()
{
    sf::View view = screen->getView();
    sf::Vector2u mapsize = map->GetMapSize();
    sf::Vector2f viewsize = view.getSize();
    viewsize.x /= 2;
    viewsize.y /= 2;
    sf::Vector2f pos = player->getPosition();

    float panX = viewsize.x; // minimum pan
    if(pos.x >= viewsize.x)
        panX = pos.x;

    if(panX >= mapsize.x - viewsize.x)
        panX = mapsize.x - viewsize.x;

    float panY = viewsize.y; // minimum pan
    if(pos.y >= viewsize.y)
        panY = pos.y;

    if(panY >= mapsize.y - viewsize.y)
        panY = mapsize.y - viewsize.y;

    view.setCenter(sf::Vector2f(panX,panY));
    screen->setView(view);
}

void PlayState::draw(cgf::Game* game)
{
    //sf::View view = screen->getView();

    screen->clear(sf::Color(0,0,0));

    map->Draw(*screen, 0);
    player->draw(game);
    projectiles->draw(game);
    map->Draw(*screen, 1);
    monsters->draw(game);
    items->draw(game);

    //screen->draw(text);
}
<commit_msg>Draw player in front of monsters<commit_after>/*
 *  PlayState.cpp
 *  Normal "play" state
 *
 *  Created by Marcelo Cohen on 08/13.
 *  Copyright 2013 PUCRS. All rights reserved.
 *
 */

#include <iostream>
#include <cmath>
#include "Game.h"
#include "PlayState.h"
#include "MenuState.h"
#include "InputManager.h"

#include "ItemShells.h"
#include "ItemShotgun.h"
#include "ItemRocketLauncher.h"
#include "ItemRocket.h"

#include "Player.h"
#include "PlayerDriver.h"

#include "Imp.h"
#include "CyberDemon.h"
#include "PinkDemon.h"
#include "BaronOfHell.h"

PlayState PlayState::m_PlayState;

using namespace std;

void PlayState::init()
{

    im = cgf::InputManager::instance();

    im->addKeyInput("left", sf::Keyboard::Left);
    im->addKeyInput("right", sf::Keyboard::Right);
    im->addKeyInput("up", sf::Keyboard::Up);
    im->addKeyInput("down", sf::Keyboard::Down);
    im->addKeyInput("one", sf::Keyboard::Num1);
    im->addKeyInput("two", sf::Keyboard::Num2);
    im->addKeyInput("three", sf::Keyboard::Num3);
    im->addKeyInput("quit", sf::Keyboard::Escape);
    im->addKeyInput("zoomin", sf::Keyboard::Z);
    im->addKeyInput("zoomout", sf::Keyboard::X);
    im->addMouseInput("rightclick", sf::Mouse::Right);

    map = new tmx::MapLoader("data/maps");
    //map->Load("dungeon-tilesets2.tmx");
    map->Load("level1.tmx");

    projectiles = new Projectiles();
    player = new Player(projectiles);
    playerdriver = new PlayerDriver(*player, im);
    monsters = new Monsters(player);
    items = new Items(player->getInventory());

    firstTime = true;

    // BEGIN MANUALLY SET MAP ENTITIES
    monsters->spawnNew(new Imp(150, 90, 3));
    monsters->spawnNew(new PinkDemon(500, 360, 3));
    monsters->spawnNew(new PinkDemon(300, 310, 3));
    monsters->spawnNew(new PinkDemon(360, 240, 3));
    monsters->spawnNew(new PinkDemon(950, 650, 3));
    monsters->spawnNew(new BaronOfHell(1000, 270, 3));
    monsters->spawnNew(new BaronOfHell(1200, 380, 3));

    monsters->spawnNew(new Imp(500, 630, 3));
    monsters->spawnNew(new Imp(340, 630, 3));
    monsters->spawnNew(new Imp(480, 760, 3));
    monsters->spawnNew(new Imp(300, 775, 3));

    monsters->spawnNew(new CyberDemon(1250, 900, 3));

    items->spawnNew(new ItemShotgun(700, 420));
    items->spawnNew(new ItemShells(740, 440));
    items->spawnNew(new ItemShells(770, 480));
    items->spawnNew(new ItemShells(670, 430));

    items->spawnNew(new ItemRocketLauncher(700, 750));
    items->spawnNew(new ItemRocket(90, 850));
    items->spawnNew(new ItemRocket(120, 900));
    items->spawnNew(new ItemRocket(170, 850));
    // END MANUALLY SET MAP ENTITIES

	cout << "PlayState Init Successful" << endl;
}

void PlayState::cleanup()
{
	cout << "PlayState Clean Successful" << endl;
	delete map;
	delete playerdriver;
	delete projectiles;
	delete monsters;
	delete items;
}

void PlayState::pause()
{
	cout << "PlayState Paused" << endl;
}

void PlayState::resume()
{
	cout << "PlayState Resumed" << endl;
}

void PlayState::handleEvents(cgf::Game* game)
{
    sf::Event event;
    sf::View view = screen->getView();

    while (screen->pollEvent(event)){

        if(event.type == sf::Event::Closed){
            game->quit();
        }

        if(event.key.code == sf::Keyboard::S){
            game->toggleStats();
        }
        playerdriver->receiveInput(event);
    }

    if(im->testEvent("quit") || im->testEvent("rightclick"))
        game->quit();

    if(im->testEvent("zoomin"))
    {
        view.zoom(1.01);
        screen->setView(view);
    }
    else if(im->testEvent("zoomout"))
    {
        view.zoom(0.99);
        screen->setView(view);
    }

}

void PlayState::update(cgf::Game* game)
{
    if(firstTime) {
        // Background audio from http://www.looperman.com/loops/detail/77776
        music.openFromFile("data/audio/background-loop.wav");
        music.setVolume(30);
        music.setLoop(true);
        music.play();
        firstTime = false;
    }

    screen = game->getScreen();
    checkCollision(2, game, player->getSprite());
    centerMapOnPlayer();

    // check projectile collisions.
    bool repeat_dreaded_bubble_sort = true;
    while (repeat_dreaded_bubble_sort){
        repeat_dreaded_bubble_sort = false;

        for (int i=0; i<projectiles->projectiles.size(); ++i){

            cgf::Sprite *prjspr = projectiles->projectiles[i]->sprite;

            // check against the map
            if (checkCollision(2, game, prjspr)){
                projectiles->kill(i);
                repeat_dreaded_bubble_sort = true;
                break;
            }

            // check against monsters
            bool i_wanna_cry = false;
            for (int j=0; j<monsters->monsters.size(); ++j){

                if (!(monsters->monsters[j]->isAlive())){
                    continue;
                }

                cgf::Sprite *monspr = monsters->monsters[j]->sprite;

                if (prjspr->circleCollision(*monspr)){
                    projectiles->kill(i);
                    monsters->kill(j);
                    i_wanna_cry = true;
                    break;
                }
            }
            if (i_wanna_cry){
                repeat_dreaded_bubble_sort = true;
                break;
            }
        }
    }

    // check collisions between player and any items
    items->checkCollisionsWithPlayer(player);
}

bool PlayState::checkCollision(u_int8_t layer, cgf::Game* game, cgf::Sprite* obj)
{
    int i, x1, x2, y1, y2;
    bool bump = false;

    // Get the limits of the map
    sf::Vector2u mapsize = map->GetMapSize();
    // Get the width and height of a single tile
    sf::Vector2u tilesize = map->GetMapTileSize();

    mapsize.x /= tilesize.x;
    mapsize.y /= tilesize.y;
    mapsize.x--;
    mapsize.y--;

    // Get the height and width of the object (in this case, 100% of a tile)
    sf::Vector2u objsize = obj->getSize();
    objsize.x *= obj->getScale().x;
    objsize.y *= obj->getScale().y;

    float px = obj->getPosition().x;
    float py = obj->getPosition().y;

    double deltaTime = game->getUpdateInterval();

    sf::Vector2f offset(obj->getXspeed()/1000 * deltaTime, obj->getYspeed()/1000 * deltaTime);

    float vx = offset.x;
    float vy = offset.y;

    // Test the horizontal movement first
    i = objsize.y > tilesize.y ? tilesize.y : objsize.y;

    for (;;)
    {
        x1 = (px + vx) / tilesize.x;
        x2 = (px + vx + objsize.x - 1) / tilesize.x;

        y1 = (py) / tilesize.y;
        y2 = (py + i - 1) / tilesize.y;

        if (x1 >= 0 && x2 <= mapsize.x && y1 >= 0 && y2 < mapsize.y)
        {
            if (vx > 0)
            {
                // Trying to move right

                int upRight   = getCellFromMap(layer, x2*tilesize.x, y1*tilesize.y);
                int downRight = getCellFromMap(layer, x2*tilesize.x, y2*tilesize.y);
                if (upRight || downRight)
                {
                    // Place the player as close to the solid tile as possible
                    px = x2 * tilesize.x;
                    px -= objsize.x;// + 1;
                    vx = 0;
                    bump = true;
                }
            }

            else if (vx < 0)
            {
                // Trying to move left

                int upLeft   = getCellFromMap(layer, x1*tilesize.x, y1*tilesize.y);
                int downLeft = getCellFromMap(layer, x1*tilesize.x, y2*tilesize.y);
                if (upLeft || downLeft)
                {
                    // Place the player as close to the solid tile as possible
                    px = (x1+1) * tilesize.x;
                    vx = 0;
                    bump = true;
                }
            }
        }

        if (i == objsize.y) // Checked player height with all tiles ?
        {
            break;
        }

        i += tilesize.y; // done, check next tile upwards

        if (i > objsize.y)
        {
            i = objsize.y;
        }
    }

    // Now test the vertical movement

    i = objsize.x > tilesize.x ? tilesize.x : objsize.x;

    for (;;)
    {
        x1 = (px / tilesize.x);
        x2 = ((px + i-1) / tilesize.x);

        y1 = ((py + vy) / tilesize.y);
        y2 = ((py + vy + objsize.y-1) / tilesize.y);

        if (x1 >= 0 && x2 < mapsize.x && y1 >= 0 && y2 <= mapsize.y)
        {
            if (vy > 0)
            {
                // Trying to move down
                int downLeft  = getCellFromMap(layer, x1*tilesize.x, y2*tilesize.y);
                int downRight = getCellFromMap(layer, x2*tilesize.x, y2*tilesize.y);
                if (downLeft || downRight)
                {
                    // Place the player as close to the solid tile as possible
                    py = y2 * tilesize.y;
                    py -= objsize.y;
                    vy = 0;
                    bump = true;
                }
            }

            else if (vy < 0)
            {
                // Trying to move up

                int upLeft  = getCellFromMap(layer, x1*tilesize.x, y1*tilesize.y);
                int upRight = getCellFromMap(layer, x2*tilesize.x, y1*tilesize.y);
                if (upLeft || upRight)
                {
                    // Place the player as close to the solid tile as possible
                    py = (y1 + 1) * tilesize.y;
                    vy = 0;
                    bump = true;
                }
            }
        }

        if (i == objsize.x)
        {
            break;
        }

        i += tilesize.x; // done, check next tile to the right

        if (i > objsize.x)
        {
            i = objsize.x;
        }
    }

    // Now apply the movement and animation

    obj->setPosition(px+vx,py+vy);
    px = obj->getPosition().x;
    py = obj->getPosition().y;

    obj->update(deltaTime, false); // only update animation

    // Check collision with edges of map
    if (px < 0)
        obj->setPosition(px,py);
    else if (px + objsize.x >= mapsize.x * tilesize.x)
        obj->setPosition(mapsize.x*tilesize.x - objsize.x - 1,py);

    if(py < 0)
        obj->setPosition(px,0);
    else if(py + objsize.y >= mapsize.y * tilesize.y)
        obj->setPosition(px, mapsize.y*tilesize.y - objsize.y - 1);

    return bump;
}

sf::Uint16 PlayState::getCellFromMap(uint8_t layernum, float x, float y)
{
    auto layers = map->GetLayers();
    tmx::MapLayer& layer = layers[layernum];
    sf::Vector2u mapsize = map->GetMapSize();
    sf::Vector2u tilesize = map->GetMapTileSize();
    mapsize.x /= tilesize.x;
    mapsize.y /= tilesize.y;
    int col = floor(x / tilesize.x);
    int row = floor(y / tilesize.y);
    return layer.tiles[row*mapsize.x + col].gid;
}

void PlayState::centerMapOnPlayer()
{
    sf::View view = screen->getView();
    sf::Vector2u mapsize = map->GetMapSize();
    sf::Vector2f viewsize = view.getSize();
    viewsize.x /= 2;
    viewsize.y /= 2;
    sf::Vector2f pos = player->getPosition();

    float panX = viewsize.x; // minimum pan
    if(pos.x >= viewsize.x)
        panX = pos.x;

    if(panX >= mapsize.x - viewsize.x)
        panX = mapsize.x - viewsize.x;

    float panY = viewsize.y; // minimum pan
    if(pos.y >= viewsize.y)
        panY = pos.y;

    if(panY >= mapsize.y - viewsize.y)
        panY = mapsize.y - viewsize.y;

    view.setCenter(sf::Vector2f(panX,panY));
    screen->setView(view);
}

void PlayState::draw(cgf::Game* game)
{
    //sf::View view = screen->getView();

    screen->clear(sf::Color(0,0,0));

    map->Draw(*screen, 0);
    projectiles->draw(game);
    map->Draw(*screen, 1);
    monsters->draw(game);
    items->draw(game);
    player->draw(game);

    //screen->draw(text);
}
<|endoftext|>


<commit_before>//
// MIT License
// Copyright (c) 2018 Jonathan R. Madsen
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// ---------------------------------------------------------------
//  Tasking class implementation
//
// Class Description:
//
// This file creates an abstract base class for the grouping the thread-pool
// tasking system into independently joinable units
//
// ---------------------------------------------------------------
// Author: Jonathan Madsen (Feb 13th 2018)
// ---------------------------------------------------------------

#include "PTL/VTaskGroup.hh"
#include "PTL/VTask.hh"
#include "PTL/ThreadData.hh"
#include "PTL/ThreadPool.hh"
#include "PTL/Task.hh"
#include "PTL/TaskRunManager.hh"

//============================================================================//

std::atomic_uintmax_t& vtask_group_counter()
{
    static std::atomic_uintmax_t _instance(0);
    return _instance;
}

//============================================================================//

VTaskGroup::VTaskGroup(ThreadPool* tp)
: m_clear_count(0),
  m_clear_freq(1),
  m_tot_task_count(0),
  m_id(vtask_group_counter()++),
  m_pool(tp),
  m_task_lock(),
  m_main_tid(std::this_thread::get_id())
{
    if(!m_pool && TaskRunManager::GetMasterRunManager())
        m_pool = TaskRunManager::GetMasterRunManager()->GetThreadPool();

#ifdef DEBUG
    if(!m_pool && GetEnv<int>("PTL_VERBOSE", 0) > 0)
    {
        std::cerr << __FUNCTION__ << "@" << __LINE__ << " :: Warning! "
                  << "nullptr to thread pool!" << std::endl;
    }
#endif
}

//============================================================================//

VTaskGroup::~VTaskGroup()
{ }

//============================================================================//

void VTaskGroup::execute_this_threads_tasks()
{
    // for internal threads
    ThreadData* data = ThreadData::GetInstance();

    ThreadPool* _tpool = (m_pool) ? m_pool
                                  : ((data) ? data->thread_pool : nullptr);

    VUserTaskQueue* _taskq = (m_pool) ? m_pool->get_queue()
                                      : ((data) ? data->current_queue : nullptr);

    // for external threads
    bool within_task = (data) ? data->within_task : true;

    // for external threads
    if(!data)
    {
        _tpool = TaskRunManager::GetMasterRunManager()->GetThreadPool();
        _taskq = _tpool->get_queue();
    }

    // something is wrong, didn't create thread-pool?
    if(!_tpool || !_taskq)
    {
#ifdef DEBUG
        if(GetEnv<int>("PTL_VERBOSE", 0) > 0)
            std::cerr << __FUNCTION__ << "@" << __LINE__ << " :: Warning! "
                      << "nullptr to thread data!" << std::endl;
#endif
        return;
    }

    // only want to process if within a task
    if((!is_master || _tpool->size() < 2) && within_task)
    {
#if defined(DEBUG)
        std::cout << "VTaskGroup::" << __FUNCTION__ << "()..." << std::endl;
#endif
        if(!_taskq)
            return;
        int bin = static_cast<int>(_taskq->GetThreadBin());
        const auto nitr = (_tpool)
                           ? _tpool->size()
                           : Thread::hardware_concurrency();
        while(this->pending() > 0)
        {
#if defined(DEBUG)
            std::cout << "[" << _taskq->GetThreadBin() << "] pending = "
                   << this->pending() << "..." << std::endl;
#endif
            task_pointer _task = _taskq->GetTask(bin, static_cast<int>(nitr));
            if(_task.get())
                (*_task)();
        }
    }
}

//============================================================================//

void VTaskGroup::wait()
{
    // if no pool was initially present at creation
    if(!m_pool)
    {
        // check for master MT run-manager
        if(TaskRunManager::GetMasterRunManager())
            m_pool = TaskRunManager::GetMasterRunManager()->GetThreadPool();

        // if MTRunManager does not exist or no thread pool created
        if(!m_pool)
        {
#ifdef DEBUG
            if(GetEnv<int>("PTL_VERBOSE", 0) > 0)
            {
                std::cerr << __FUNCTION__ << "@" << __LINE__ << " :: Warning! "
                          << "nullptr to thread pool!" << std::endl;
            }
#endif
            return;
        }
    }

    // return if thread pool isn't built
    if(!m_pool->is_alive() || !is_native_task_group())
        return;

    //execute_this_threads_tasks();
    //return;

    auto is_active_state = [&] ()
    {
        return static_cast<int>(m_pool->state()) != static_cast<int>(state::STOPPED);
    };

    intmax_t _pool_size = m_pool->size();
    intmax_t _pending = 0;
    AutoLock _lock(m_task_lock, std::defer_lock);

    while(is_active_state())
    {
        execute_this_threads_tasks();

        // while loop protects against spurious wake-ups
        while((_pending = pending()) > 0 && is_active_state())
        {
            // lock before sleeping on condition
            if(!_lock.owns_lock())
                _lock.lock();
            // Wait until signaled that a task has been competed
            // Unlock mutex while wait, then lock it back when signaled
            if((_pending = pending()) > _pool_size) // for safety
                m_task_cond.wait(_lock);
            else
                m_task_cond.wait_for(_lock, std::chrono::milliseconds(10));
            if(_lock.owns_lock())
                _lock.unlock();
        }

        // if pending is not greater than zero, we are joined
        if((_pending = pending()) <= 0)
            break;
    }

    if(_lock.owns_lock())
        _lock.unlock();

    intmax_t ntask = this->task_count().load();
    if(ntask > 0)
    {
        std::stringstream ss;
        ss << "\nWarning! Join operation issue! " << ntask << " tasks still "
           << "are running!" << std::endl;
        std::cout << ss.str();
        this->wait();
        //throw std::runtime_error(ss.str().c_str());
    }

}

//============================================================================//
<commit_msg>Update VTaskGroup.cc<commit_after>//
// MIT License
// Copyright (c) 2018 Jonathan R. Madsen
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// ---------------------------------------------------------------
//  Tasking class implementation
//
// Class Description:
//
// This file creates an abstract base class for the grouping the thread-pool
// tasking system into independently joinable units
//
// ---------------------------------------------------------------
// Author: Jonathan Madsen (Feb 13th 2018)
// ---------------------------------------------------------------

#include "PTL/VTaskGroup.hh"
#include "PTL/VTask.hh"
#include "PTL/ThreadData.hh"
#include "PTL/ThreadPool.hh"
#include "PTL/Task.hh"
#include "PTL/TaskRunManager.hh"

//============================================================================//

std::atomic_uintmax_t& vtask_group_counter()
{
    static std::atomic_uintmax_t _instance(0);
    return _instance;
}

//============================================================================//

VTaskGroup::VTaskGroup(ThreadPool* tp)
: m_clear_count(0),
  m_clear_freq(1),
  m_tot_task_count(0),
  m_id(vtask_group_counter()++),
  m_pool(tp),
  m_task_lock(),
  m_main_tid(std::this_thread::get_id())
{
    if(!m_pool && TaskRunManager::GetMasterRunManager())
        m_pool = TaskRunManager::GetMasterRunManager()->GetThreadPool();

#ifdef DEBUG
    if(!m_pool && GetEnv<int>("PTL_VERBOSE", 0) > 0)
    {
        std::cerr << __FUNCTION__ << "@" << __LINE__ << " :: Warning! "
                  << "nullptr to thread pool!" << std::endl;
    }
#endif
}

//============================================================================//

VTaskGroup::~VTaskGroup()
{ }

//============================================================================//

void VTaskGroup::execute_this_threads_tasks()
{
    // for internal threads
    ThreadData* data = ThreadData::GetInstance();

    ThreadPool* _tpool = (m_pool) ? m_pool
                                  : ((data) ? data->thread_pool : nullptr);

    VUserTaskQueue* _taskq = (m_pool) ? m_pool->get_queue()
                                      : ((data) ? data->current_queue : nullptr);

    // for external threads
    bool within_task = (data) ? data->within_task : true;

    // for external threads
    if(!data)
    {
        _tpool = TaskRunManager::GetMasterRunManager()->GetThreadPool();
        _taskq = _tpool->get_queue();
    }

    // something is wrong, didn't create thread-pool?
    if(!_tpool || !_taskq)
    {
#ifdef DEBUG
        if(GetEnv<int>("PTL_VERBOSE", 0) > 0)
            std::cerr << __FUNCTION__ << "@" << __LINE__ << " :: Warning! "
                      << "nullptr to thread data!" << std::endl;
#endif
        return;
    }

    // only want to process if within a task
    if((!is_master() || _tpool->size() < 2) && within_task)
    {
#if defined(DEBUG)
        std::cout << "VTaskGroup::" << __FUNCTION__ << "()..." << std::endl;
#endif
        if(!_taskq)
            return;
        int bin = static_cast<int>(_taskq->GetThreadBin());
        const auto nitr = (_tpool)
                           ? _tpool->size()
                           : Thread::hardware_concurrency();
        while(this->pending() > 0)
        {
#if defined(DEBUG)
            std::cout << "[" << _taskq->GetThreadBin() << "] pending = "
                   << this->pending() << "..." << std::endl;
#endif
            task_pointer _task = _taskq->GetTask(bin, static_cast<int>(nitr));
            if(_task.get())
                (*_task)();
        }
    }
}

//============================================================================//

void VTaskGroup::wait()
{
    // if no pool was initially present at creation
    if(!m_pool)
    {
        // check for master MT run-manager
        if(TaskRunManager::GetMasterRunManager())
            m_pool = TaskRunManager::GetMasterRunManager()->GetThreadPool();

        // if MTRunManager does not exist or no thread pool created
        if(!m_pool)
        {
#ifdef DEBUG
            if(GetEnv<int>("PTL_VERBOSE", 0) > 0)
            {
                std::cerr << __FUNCTION__ << "@" << __LINE__ << " :: Warning! "
                          << "nullptr to thread pool!" << std::endl;
            }
#endif
            return;
        }
    }

    // return if thread pool isn't built
    if(!m_pool->is_alive() || !is_native_task_group())
        return;

    //execute_this_threads_tasks();
    //return;

    auto is_active_state = [&] ()
    {
        return static_cast<int>(m_pool->state()) != static_cast<int>(state::STOPPED);
    };

    intmax_t _pool_size = m_pool->size();
    intmax_t _pending = 0;
    AutoLock _lock(m_task_lock, std::defer_lock);

    while(is_active_state())
    {
        execute_this_threads_tasks();

        // while loop protects against spurious wake-ups
        while((_pending = pending()) > 0 && is_active_state())
        {
            // lock before sleeping on condition
            if(!_lock.owns_lock())
                _lock.lock();
            // Wait until signaled that a task has been competed
            // Unlock mutex while wait, then lock it back when signaled
            if((_pending = pending()) > _pool_size) // for safety
                m_task_cond.wait(_lock);
            else
                m_task_cond.wait_for(_lock, std::chrono::milliseconds(10));
            if(_lock.owns_lock())
                _lock.unlock();
        }

        // if pending is not greater than zero, we are joined
        if((_pending = pending()) <= 0)
            break;
    }

    if(_lock.owns_lock())
        _lock.unlock();

    intmax_t ntask = this->task_count().load();
    if(ntask > 0)
    {
        std::stringstream ss;
        ss << "\nWarning! Join operation issue! " << ntask << " tasks still "
           << "are running!" << std::endl;
        std::cout << ss.str();
        this->wait();
        //throw std::runtime_error(ss.str().c_str());
    }

}

//============================================================================//
<|endoftext|>


<commit_before>#include "common.h"
#include "parser.h"
#include<algorithm>

#define d
#ifdef d
extern Lex lex;
#else
extern Lex lex("test.ws");
#endif

extern shared_ptr<Node> root;
extern bool parseStmt();
extern void initSysFunc();

bool FileInput() {
	initSysFunc();
	if (parseStmt()) {
		//root->visit(0);
		root->eval();
		return 1;
	}
	// std::out_of_range;
	// return 0;
	// for (int i = 1; i <= 30; i++)
	// out(lex.readNextToken());
	return 0;
}

extern ostream & operator<< (ostream &, const Value &);

shared_ptr<Node> saved_root;

string info = "WeakScript 0.2.11 alpha on win32\nCopyright 2015-2016 zcy. All Rights Reserved\nThis project is under the MIT license: http://www.opensource.org/licenses/mit-license.php\n";
bool InterInput() {
	string code;
	initSysFunc();
	//lex = Lex();
	cout << info;
	while (1) {
		cout << ">>>";
		if (parseStmt()) {
			root->visit(0);
			try {
				auto x = root->eval();if (dynamic_pointer_cast<SimpleNode>(root) != nullptr)
					cout << x << endl;
				//else cout << endl;
			}
			catch (MyExpection &e ) {
				cout << e.getErrorMessage()<<endl;
			}		//if (x.type == Value::Type::Null)
			//return 1;
		}
		else {
			cout << "SyntaxError" << endl;
			lex.reset();
			//return 0;
		}
		//saved_root = root;
	}
}

int main() {
#ifndef d
	FileInput();
#else
	InterInput();
#endif
	return 0;
}
<commit_msg>hello<commit_after>#include "common.h"
#include "parser.h"
#include<algorithm>

#define d
#ifdef d
extern Lex lex;
#else
extern Lex lex("test.ws");
#endif

extern shared_ptr<Node> root;
extern bool parseStmt();
extern void initSysFunc();

bool FileInput() {
	initSysFunc();
	if (parseStmt()) {
		//root->visit(0);
		root->eval();
		return 1;
	}
	// std::out_of_range;
	// return 0;
	// for (int i = 1; i <= 30; i++)
	// out(lex.readNextToken());
	return 0;
}

extern ostream & operator<< (ostream &, const Value &);

string info = "WeakScript 0.2.11 alpha on win32\nCopyright 2015-2016 zcy. All Rights Reserved\nThis project is under the MIT license: http://www.opensource.org/licenses/mit-license.php\n";
bool InterInput() {
	string code;
	initSysFunc();
	//lex = Lex();
	cout << info;
	while (1) {
		cout << ">>>";
		if (parseStmt()) {
			//root->visit(0);
			try {
				auto x = root->eval();if (dynamic_pointer_cast<SimpleNode>(root) != nullptr)
					cout << x << endl;
				//else cout << endl;
			}
			catch (MyExpection &e ) {
				cout << e.getErrorMessage()<<endl;
			}		//if (x.type == Value::Type::Null)
			//return 1;
		}
		else {
			cout << "SyntaxError" << endl;
			lex.reset();
			//return 0;
		}
		//saved_root = root;
	}
}

int main() {
#ifndef d
	FileInput();
#else
	InterInput();
#endif
	return 0;
}
<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include <QmitkSliderLevelWindowWidget.h>

#include <QCursor>
#include <QPainter>
#include <QToolTip>
#include <QMouseEvent>

#include <itkCommand.h>
#include <QmitkLevelWindowWidgetContextMenu.h>
#include <mitkRenderingManager.h>

#include <math.h>

/**
* Constructor
*/
QmitkSliderLevelWindowWidget::QmitkSliderLevelWindowWidget( QWidget * parent, Qt::WindowFlags f )
: QWidget( parent, f )
{
  m_Manager = mitk::LevelWindowManager::New();

  itk::ReceptorMemberCommand<QmitkSliderLevelWindowWidget>::Pointer command = itk::ReceptorMemberCommand<QmitkSliderLevelWindowWidget>::New();
  command->SetCallbackFunction(this, &QmitkSliderLevelWindowWidget::OnPropertyModified);
  m_ObserverTag = m_Manager->AddObserver(itk::ModifiedEvent(), command);
  m_IsObserverTagSet = true;

  setMouseTracking(true);
  m_Resize = false;
  m_Bottom = false;
  m_CtrlPressed = false;
  m_MouseDown = false;

  m_Font.setPointSize( 6 );

  m_MoveHeight = height() - 25;
  m_ScaleVisible = true;
  m_Contextmenu = new QmitkLevelWindowWidgetContextMenu(this); //, true);

  //setBackgroundMode( Qt::NoBackground );

  this->hide();
  update();

}

QmitkSliderLevelWindowWidget::~QmitkSliderLevelWindowWidget()
{
  if ( m_IsObserverTagSet)
  {
    m_Manager->RemoveObserver(m_ObserverTag);
    m_IsObserverTagSet = false;
  }
}

void QmitkSliderLevelWindowWidget::setLevelWindowManager(mitk::LevelWindowManager* levelWindowManager)
{
  if ( m_IsObserverTagSet)
  {
    m_Manager->RemoveObserver(m_ObserverTag);
   m_IsObserverTagSet = false;
  }
  m_Manager = levelWindowManager;
  if ( m_Manager.IsNotNull() )
  {
    itk::ReceptorMemberCommand<QmitkSliderLevelWindowWidget>::Pointer command = itk::ReceptorMemberCommand<QmitkSliderLevelWindowWidget>::New();
    command->SetCallbackFunction(this, &QmitkSliderLevelWindowWidget::OnPropertyModified);
    m_ObserverTag = m_Manager->AddObserver(itk::ModifiedEvent(), command);
    m_IsObserverTagSet = true;
  }
}

void QmitkSliderLevelWindowWidget::OnPropertyModified(const itk::EventObject& )
{
  try
  {
    m_LevelWindow = m_Manager->GetLevelWindow();
    this->show();
    update();
  }
  catch(...)
  {
    try
    {
      this->hide();
    }
    catch(...)
    {
    }
  }
}

void QmitkSliderLevelWindowWidget::paintEvent( QPaintEvent* itkNotUsed(e) )
{
  QPixmap pm(width(), height());
  //pm.fill( static_cast<QWidget*>(parent())->paletteBackgroundColor() );
  pm.fill(this, 0, 0);
  QPainter painter(&pm);

  painter.setFont( m_Font );
  //painter.setPen(static_cast<QWidget*>(parent())->paletteForegroundColor());
  painter.setPen(this->palette().color(this->foregroundRole()));

  QColor c(93,144,169);
  QColor cl = c.light();
  QColor cd = c.dark();

  painter.setBrush(c);
  painter.drawRect(m_Rect);

  float mr = m_LevelWindow.GetRange();

  if ( mr < 1 )
    mr = 1;

  float fact = (float) m_MoveHeight / mr;

  //begin draw scale
  if (m_ScaleVisible)
  {
    int minRange = (int)m_LevelWindow.GetRangeMin();
    int maxRange = (int)m_LevelWindow.GetRangeMax();
    int yValue = m_MoveHeight + (int)(minRange*fact);
    QString s = " 0";
    if (minRange <= 0 && maxRange >= 0)
    {
      painter.drawLine( 5, yValue , 15, yValue);
      painter.drawText( 21, yValue + 3, s );
    }

    int count = 1;
    int k = 5;
    bool enoughSpace = false;
    bool enoughSpace2 = false;

    double dStepSize = pow(10,floor(log10(mr/100))+1);

    for(int i = m_MoveHeight + (int)(minRange*fact); i < m_MoveHeight;)//negative
    {
      if (-count*dStepSize < minRange)
        break;
      yValue = m_MoveHeight + (int)((minRange + count*dStepSize)*fact);

      s = QString::number(-count*dStepSize);
      if (count % k && ((dStepSize*fact) > 2.5))
      {
        painter.drawLine( 8, yValue, 12, yValue);
        enoughSpace = true;
      }
      else if (!(count % k))
      {
        if ((k*dStepSize*fact) > 7)
        {
          painter.drawLine( 5, yValue, 15, yValue);
          painter.drawText( 21, yValue + 3, s );
          enoughSpace2 = true;
        }
        else
        {
          k += 5;
        }
      }
      if (enoughSpace)
      {
        i=yValue;
        count++;
      }
      else if (enoughSpace2)
      {
        i=yValue;
        count += k;
      }
      else
      {
        i=yValue;
        count = k;
      }
    }
    count = 1;
    k = 5;
    enoughSpace = false;
    enoughSpace2 = false;

    for(int i = m_MoveHeight + (int)(minRange*fact); i >= 0;)
    {
      if (count*dStepSize > maxRange)
        break;
      yValue = m_MoveHeight + (int)((minRange - count*dStepSize)*fact);

      s = QString::number(count*dStepSize);
      if(count % k && ((dStepSize*fact) > 2.5))
      {
        if (!(minRange > 0 && (count*dStepSize) < minRange))
          painter.drawLine( 8, yValue, 12, yValue);
        enoughSpace = true;
      }
      else if (!(count % k))
      {
        if ((k*dStepSize*fact) > 7)
        {
          if (!(minRange > 0 && (count*dStepSize) < minRange))
          {
            painter.drawLine( 5, yValue, 15, yValue);
            painter.drawText( 21, yValue + 3, s );
          }
          enoughSpace2 = true;
        }
        else
        {
          k += 5;
        }
      }
      if (enoughSpace)
      {
        i=yValue;
        count++;
      }
      else if (enoughSpace2)
      {
        i=yValue;
        count += k;
      }
      else
      {
        i=yValue;
        count = k;
      }
    }
  }
  //end draw scale
  painter.setPen (cl);
  painter.drawLine(m_Rect.topLeft(),m_Rect.topRight());
  painter.drawLine(m_Rect.topLeft(),m_Rect.bottomLeft());

  painter.setPen (cd);
  painter.drawLine(m_Rect.topRight(),m_Rect.bottomRight());
  painter.drawLine(m_Rect.bottomRight(),m_Rect.bottomLeft());
  painter.end();

  QPainter p (this);
  p.drawPixmap(0, 0, pm);
}

/**
*
*/
void QmitkSliderLevelWindowWidget::mouseMoveEvent( QMouseEvent* mouseEvent )
{
  if(!mouseEvent)
    return;
  if ( m_LevelWindow.IsFixed() )
    return;
  if (!m_MouseDown)
  {
    if ( mouseEvent->pos().y() >= 0
      && mouseEvent->pos().y() <= (m_Rect.topLeft().y() + 3) )
    {
      setCursor(Qt::SizeVerCursor);
      m_UpperBound.setRect(m_Rect.topLeft().x(), m_Rect.topLeft().y() - 3, 17, 7);
      QToolTip::showText(mouseEvent->globalPos(), "Ctrl + left click to change only upper bound", this, m_UpperBound);
      m_Resize = true;
    }
    else if ( mouseEvent->pos().y() >= (m_Rect.bottomLeft().y() - 3) )
    {
      setCursor(Qt::SizeVerCursor);
      m_LowerBound.setRect(m_Rect.bottomLeft().x(), m_Rect.bottomLeft().y() - 3, 17, 7);
      QToolTip::showText(mouseEvent->globalPos(), "Ctrl + left click to change only lower bound", this, m_LowerBound);
      m_Resize = true;
      m_Bottom = true;
    }
    else
    {
      setCursor(Qt::ArrowCursor);
      m_Resize = false;
      m_Bottom = false;
    }
  }

  else {

    float fact = (float) m_MoveHeight / m_LevelWindow.GetRange();

    if ( m_Leftbutton )
    {
      if (m_Resize && !m_CtrlPressed)
      {
        double diff = (mouseEvent->pos().y()) / fact;
        diff -= (m_StartPos.y()) / fact;
        m_StartPos = mouseEvent->pos();

        if (diff == 0) return;
        float value;
        if (m_Bottom)
          value = m_LevelWindow.GetWindow() + ( ( 2 * diff ) );
        else
          value = m_LevelWindow.GetWindow() - ( ( 2 * diff ) );

        if ( value < 0 )
          value = 0;

        m_LevelWindow.SetLevelWindow( m_LevelWindow.GetLevel(), value );
      }
      else if(m_Resize && m_CtrlPressed)
      {
        if (!m_Bottom)
        {
          double diff = (mouseEvent->pos().y()) / fact;
          diff -= (m_StartPos.y()) / fact;
          m_StartPos = mouseEvent->pos();

          if (diff == 0) return;
          float value;

          value = m_LevelWindow.GetWindow() - ( ( diff ) );

          if ( value < 0 )
            value = 0;
          float oldWindow;
          float oldLevel;
          float newLevel;
          oldWindow = m_LevelWindow.GetWindow();
          oldLevel = m_LevelWindow.GetLevel();
          newLevel = oldLevel + (value - oldWindow)/2;
          if (!((newLevel + value/2) > m_LevelWindow.GetRangeMax()))
            m_LevelWindow.SetLevelWindow( newLevel, value );
        }
        else
        {
          double diff = (mouseEvent->pos().y()) / fact;
          diff -= (m_StartPos.y()) / fact;
          m_StartPos = mouseEvent->pos();

          if (diff == 0) return;
          float value;

          value = m_LevelWindow.GetWindow() + ( ( diff ) );

          if ( value < 0 )
            value = 0;
          float oldWindow;
          float oldLevel;
          float newLevel;
          oldWindow = m_LevelWindow.GetWindow();
          oldLevel = m_LevelWindow.GetLevel();
          newLevel = oldLevel - (value - oldWindow)/2;
          if (!((newLevel - value/2) < m_LevelWindow.GetRangeMin()))
            m_LevelWindow.SetLevelWindow( newLevel, value );
        }
      }
      else
      {
        const float minv = m_LevelWindow.GetRangeMin();

        const float level = (m_MoveHeight - mouseEvent->pos().y()) / fact + minv;

        double diff = (mouseEvent->pos().x()) / fact;
        diff -= (m_StartPos.x()) / fact;
        m_StartPos = mouseEvent->pos();

        float window;
        if (m_Bottom)
          window = m_LevelWindow.GetWindow() + ( ( 2 * diff ) );
        else
          window = m_LevelWindow.GetWindow() - ( ( 2 * diff ) );

        if ( window < 0 )
          window = 0;

        m_LevelWindow.SetLevelWindow( level, window );
      }
      m_Manager->SetLevelWindow(m_LevelWindow);
      mitk::RenderingManager::GetInstance()->RequestUpdateAll();
    }
  }
}
void QmitkSliderLevelWindowWidget::enterEvent ( QEvent * /*event*/  )
{
  /*
  if(event->type() != QEvent::MouseMove)
    return;*/

  //mouseMoveEvent( static_cast< QMouseEvent* > ( event ) );
  QPoint p = QCursor::pos();
  p = this->mapFromGlobal(p);
  QMouseEvent ev(QEvent::MouseMove, p, Qt::NoButton, Qt::NoButton , Qt::NoModifier );
  this->mouseMoveEvent( &ev );
}

/**
*
*/
void QmitkSliderLevelWindowWidget::mousePressEvent( QMouseEvent* mouseEvent ) {
  if ( m_LevelWindow.IsFixed() )
    return;
  m_MouseDown = true;
  m_StartPos = mouseEvent->pos();

  if ( mouseEvent->button() == Qt::LeftButton )
  {
    if (mouseEvent->modifiers() == Qt::ControlModifier || mouseEvent->modifiers() == Qt::ShiftModifier)
    {
      m_CtrlPressed = true;
    }
    else
    {
      m_CtrlPressed = false;
    }
    m_Leftbutton = true;
  }
  else
    m_Leftbutton = false;

  mouseMoveEvent( mouseEvent );
}

/**
*
*/
void QmitkSliderLevelWindowWidget::resizeEvent ( QResizeEvent * event ) {
  m_MoveHeight = event->size().height() - 25;
  update();
}

/**
*
*/
void QmitkSliderLevelWindowWidget::mouseReleaseEvent( QMouseEvent* )
{
  if ( m_LevelWindow.IsFixed() )
    return;
  m_MouseDown = false;
}

/**
*
*/
void QmitkSliderLevelWindowWidget::update() {
  int rectWidth;
  if(m_ScaleVisible)
  {
    rectWidth = 17;
    setMinimumSize ( QSize( 50, 50 ) );
    setMaximumSize ( QSize( 50, 2000 ) );
    setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ) );
  }
  else
  {
    rectWidth = 26;
    setMinimumSize ( QSize( 40, 50 ) );
    setMaximumSize ( QSize( 50, 2000 ) );
    setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ) );
  }
  float mr = m_LevelWindow.GetRange();

  if ( mr < 1 )
    mr = 1;

  float fact = (float) m_MoveHeight / mr;

  float rectHeight = m_LevelWindow.GetWindow() * fact;

  if ( rectHeight < 15 )
    rectHeight = 15;

  if ( m_LevelWindow.GetLowerWindowBound() < 0 )
    m_Rect.setRect( 2, (int) (m_MoveHeight - (m_LevelWindow.GetUpperWindowBound() - m_LevelWindow.GetRangeMin()) * fact) , rectWidth, (int) rectHeight );
  else
    m_Rect.setRect( 2, (int) (m_MoveHeight - (m_LevelWindow.GetUpperWindowBound() - m_LevelWindow.GetRangeMin()) * fact), rectWidth, (int) rectHeight );

  QWidget::repaint();
}

void QmitkSliderLevelWindowWidget::contextMenuEvent( QContextMenuEvent * )
{
  m_Contextmenu->setLevelWindowManager(m_Manager.GetPointer());
  QMenu *contextMenu = new QMenu( this );
  Q_CHECK_PTR( contextMenu );
  if (m_ScaleVisible)
    contextMenu->addAction(tr("Hide Scale"), this, SLOT(hideScale()));
  else
    contextMenu->addAction(tr("Show Scale"), this, SLOT(showScale()));
  contextMenu->addSeparator();
  m_Contextmenu->getContextMenu(contextMenu);

  // Fix: Bug #13327 we need to reset the m_MouseDown value
  // otherwise the cursor is not correctly restored afterwards
  m_MouseDown = false;
}

void QmitkSliderLevelWindowWidget::hideScale()
{
  m_ScaleVisible = false;
  update();
}

void QmitkSliderLevelWindowWidget::showScale()
{
  m_ScaleVisible = true;
  update();
}

void QmitkSliderLevelWindowWidget::setDataStorage(mitk::DataStorage* ds)
{
  m_Manager->SetDataStorage(ds);
}

mitk::LevelWindowManager* QmitkSliderLevelWindowWidget::GetManager()
{
  return m_Manager.GetPointer();
}
<commit_msg>Fixed crash<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include <QmitkSliderLevelWindowWidget.h>

#include <QCursor>
#include <QPainter>
#include <QToolTip>
#include <QMouseEvent>

#include <itkCommand.h>
#include <QmitkLevelWindowWidgetContextMenu.h>
#include <mitkRenderingManager.h>

#include <math.h>

/**
* Constructor
*/
QmitkSliderLevelWindowWidget::QmitkSliderLevelWindowWidget( QWidget * parent, Qt::WindowFlags f )
: QWidget( parent, f )
{
  m_Manager = mitk::LevelWindowManager::New();

  itk::ReceptorMemberCommand<QmitkSliderLevelWindowWidget>::Pointer command = itk::ReceptorMemberCommand<QmitkSliderLevelWindowWidget>::New();
  command->SetCallbackFunction(this, &QmitkSliderLevelWindowWidget::OnPropertyModified);
  m_ObserverTag = m_Manager->AddObserver(itk::ModifiedEvent(), command);
  m_IsObserverTagSet = true;

  setMouseTracking(true);
  m_Resize = false;
  m_Bottom = false;
  m_CtrlPressed = false;
  m_MouseDown = false;

  m_Font.setPointSize( 6 );

  m_MoveHeight = height() - 25;
  m_ScaleVisible = true;
  m_Contextmenu = new QmitkLevelWindowWidgetContextMenu(this); //, true);

  //setBackgroundMode( Qt::NoBackground );

  this->hide();
  update();

}

QmitkSliderLevelWindowWidget::~QmitkSliderLevelWindowWidget()
{
  if ( m_IsObserverTagSet)
  {
    m_Manager->RemoveObserver(m_ObserverTag);
    m_IsObserverTagSet = false;
  }
}

void QmitkSliderLevelWindowWidget::setLevelWindowManager(mitk::LevelWindowManager* levelWindowManager)
{
  if ( m_IsObserverTagSet)
  {
    m_Manager->RemoveObserver(m_ObserverTag);
   m_IsObserverTagSet = false;
  }
  m_Manager = levelWindowManager;
  if ( m_Manager.IsNotNull() )
  {
    itk::ReceptorMemberCommand<QmitkSliderLevelWindowWidget>::Pointer command = itk::ReceptorMemberCommand<QmitkSliderLevelWindowWidget>::New();
    command->SetCallbackFunction(this, &QmitkSliderLevelWindowWidget::OnPropertyModified);
    m_ObserverTag = m_Manager->AddObserver(itk::ModifiedEvent(), command);
    m_IsObserverTagSet = true;
  }
}

void QmitkSliderLevelWindowWidget::OnPropertyModified(const itk::EventObject& )
{
  try
  {
    m_LevelWindow = m_Manager->GetLevelWindow();
    this->show();
    update();
  }
  catch(...)
  {
    try
    {
      this->hide();
    }
    catch(...)
    {
    }
  }
}

void QmitkSliderLevelWindowWidget::paintEvent( QPaintEvent* itkNotUsed(e) )
{
  QPixmap pm(width(), height());
  //pm.fill( static_cast<QWidget*>(parent())->paletteBackgroundColor() );
  pm.fill(this, 0, 0);
  QPainter painter(&pm);

  painter.setFont( m_Font );
  //painter.setPen(static_cast<QWidget*>(parent())->paletteForegroundColor());
  painter.setPen(this->palette().color(this->foregroundRole()));

  QColor c(93,144,169);
  QColor cl = c.light();
  QColor cd = c.dark();

  painter.setBrush(c);
  painter.drawRect(m_Rect);

  float mr = m_LevelWindow.GetRange();

  if ( mr < 1 )
    mr = 1;

  float fact = (float) m_MoveHeight / mr;

  //begin draw scale
  if (m_ScaleVisible)
  {
    int minRange = (int)m_LevelWindow.GetRangeMin();
    int maxRange = (int)m_LevelWindow.GetRangeMax();
    int yValue = m_MoveHeight + (int)(minRange*fact);
    QString s = " 0";
    if (minRange <= 0 && maxRange >= 0)
    {
      painter.drawLine( 5, yValue , 15, yValue);
      painter.drawText( 21, yValue + 3, s );
    }

    int count = 1;
    int k = 5;
    bool enoughSpace = false;
    bool enoughSpace2 = false;

    double dStepSize = pow(10,floor(log10(mr/100))+1);

    for(int i = m_MoveHeight + (int)(minRange*fact); i < m_MoveHeight;)//negative
    {
      if (-count*dStepSize < minRange)
        break;
      yValue = m_MoveHeight + (int)((minRange + count*dStepSize)*fact);

      s = QString::number(-count*dStepSize);
      if (count % k && ((dStepSize*fact) > 2.5))
      {
        painter.drawLine( 8, yValue, 12, yValue);
        enoughSpace = true;
      }
      else if (!(count % k))
      {
        if ((k*dStepSize*fact) > 7)
        {
          painter.drawLine( 5, yValue, 15, yValue);
          painter.drawText( 21, yValue + 3, s );
          enoughSpace2 = true;
        }
        else
        {
          k += 5;
        }
      }
      if (enoughSpace)
      {
        i=yValue;
        count++;
      }
      else if (enoughSpace2)
      {
        i=yValue;
        count += k;
      }
      else
      {
        i=yValue;
        count = k;
      }
    }
    count = 1;
    k = 5;
    enoughSpace = false;
    enoughSpace2 = false;

    for(int i = m_MoveHeight + (int)(minRange*fact); i >= 0;)
    {
      if (count*dStepSize > maxRange)
        break;
      yValue = m_MoveHeight + (int)((minRange - count*dStepSize)*fact);

      s = QString::number(count*dStepSize);
      if(count % k && ((dStepSize*fact) > 2.5))
      {
        if (!(minRange > 0 && (count*dStepSize) < minRange))
          painter.drawLine( 8, yValue, 12, yValue);
        enoughSpace = true;
      }
      else if (!(count % k))
      {
        if ((k*dStepSize*fact) > 7)
        {
          if (!(minRange > 0 && (count*dStepSize) < minRange))
          {
            painter.drawLine( 5, yValue, 15, yValue);
            painter.drawText( 21, yValue + 3, s );
          }
          enoughSpace2 = true;
        }
        else
        {
          k += 5;
        }
      }
      if (enoughSpace)
      {
        i=yValue;
        count++;
      }
      else if (enoughSpace2)
      {
        i=yValue;
        count += k;
      }
      else
      {
        i=yValue;
        count = k;
      }
    }
  }
  //end draw scale
  painter.setPen (cl);
  painter.drawLine(m_Rect.topLeft(),m_Rect.topRight());
  painter.drawLine(m_Rect.topLeft(),m_Rect.bottomLeft());

  painter.setPen (cd);
  painter.drawLine(m_Rect.topRight(),m_Rect.bottomRight());
  painter.drawLine(m_Rect.bottomRight(),m_Rect.bottomLeft());
  painter.end();

  QPainter p (this);
  p.drawPixmap(0, 0, pm);
}

/**
*
*/
void QmitkSliderLevelWindowWidget::mouseMoveEvent( QMouseEvent* mouseEvent )
{
  if(!mouseEvent)
    return;
  if ( m_LevelWindow.IsFixed() )
    return;
  if (!m_MouseDown)
  {
    if ( mouseEvent->pos().y() >= 0
      && mouseEvent->pos().y() <= (m_Rect.topLeft().y() + 3) )
    {
      setCursor(Qt::SizeVerCursor);
      m_UpperBound.setRect(m_Rect.topLeft().x(), m_Rect.topLeft().y() - 3, 17, 7);
      this->setToolTip("Ctrl + left click to change only upper bound");
      m_Resize = true;
    }
    else if ( mouseEvent->pos().y() >= (m_Rect.bottomLeft().y() - 3) )
    {
      setCursor(Qt::SizeVerCursor);
      m_LowerBound.setRect(m_Rect.bottomLeft().x(), m_Rect.bottomLeft().y() - 3, 17, 7);
      this->setToolTip("Ctrl + left click to change only lower bound");
      m_Resize = true;
      m_Bottom = true;
    }
    else
    {
      setCursor(Qt::ArrowCursor);
      m_Resize = false;
      m_Bottom = false;
    }
  }

  else {

    float fact = (float) m_MoveHeight / m_LevelWindow.GetRange();

    if ( m_Leftbutton )
    {
      if (m_Resize && !m_CtrlPressed)
      {
        double diff = (mouseEvent->pos().y()) / fact;
        diff -= (m_StartPos.y()) / fact;
        m_StartPos = mouseEvent->pos();

        if (diff == 0) return;
        float value;
        if (m_Bottom)
          value = m_LevelWindow.GetWindow() + ( ( 2 * diff ) );
        else
          value = m_LevelWindow.GetWindow() - ( ( 2 * diff ) );

        if ( value < 0 )
          value = 0;

        m_LevelWindow.SetLevelWindow( m_LevelWindow.GetLevel(), value );
      }
      else if(m_Resize && m_CtrlPressed)
      {
        if (!m_Bottom)
        {
          double diff = (mouseEvent->pos().y()) / fact;
          diff -= (m_StartPos.y()) / fact;
          m_StartPos = mouseEvent->pos();

          if (diff == 0) return;
          float value;

          value = m_LevelWindow.GetWindow() - ( ( diff ) );

          if ( value < 0 )
            value = 0;
          float oldWindow;
          float oldLevel;
          float newLevel;
          oldWindow = m_LevelWindow.GetWindow();
          oldLevel = m_LevelWindow.GetLevel();
          newLevel = oldLevel + (value - oldWindow)/2;
          if (!((newLevel + value/2) > m_LevelWindow.GetRangeMax()))
            m_LevelWindow.SetLevelWindow( newLevel, value );
        }
        else
        {
          double diff = (mouseEvent->pos().y()) / fact;
          diff -= (m_StartPos.y()) / fact;
          m_StartPos = mouseEvent->pos();

          if (diff == 0) return;
          float value;

          value = m_LevelWindow.GetWindow() + ( ( diff ) );

          if ( value < 0 )
            value = 0;
          float oldWindow;
          float oldLevel;
          float newLevel;
          oldWindow = m_LevelWindow.GetWindow();
          oldLevel = m_LevelWindow.GetLevel();
          newLevel = oldLevel - (value - oldWindow)/2;
          if (!((newLevel - value/2) < m_LevelWindow.GetRangeMin()))
            m_LevelWindow.SetLevelWindow( newLevel, value );
        }
      }
      else
      {
        const float minv = m_LevelWindow.GetRangeMin();

        const float level = (m_MoveHeight - mouseEvent->pos().y()) / fact + minv;

        double diff = (mouseEvent->pos().x()) / fact;
        diff -= (m_StartPos.x()) / fact;
        m_StartPos = mouseEvent->pos();

        float window;
        if (m_Bottom)
          window = m_LevelWindow.GetWindow() + ( ( 2 * diff ) );
        else
          window = m_LevelWindow.GetWindow() - ( ( 2 * diff ) );

        if ( window < 0 )
          window = 0;

        m_LevelWindow.SetLevelWindow( level, window );
      }
      m_Manager->SetLevelWindow(m_LevelWindow);
      mitk::RenderingManager::GetInstance()->RequestUpdateAll();
    }
  }
}
void QmitkSliderLevelWindowWidget::enterEvent ( QEvent * /*event*/  )
{
  /*
  if(event->type() != QEvent::MouseMove)
    return;*/

  //mouseMoveEvent( static_cast< QMouseEvent* > ( event ) );
  QPoint p = QCursor::pos();
  p = this->mapFromGlobal(p);
  QMouseEvent ev(QEvent::MouseMove, p, Qt::NoButton, Qt::NoButton , Qt::NoModifier );
  this->mouseMoveEvent( &ev );
}

/**
*
*/
void QmitkSliderLevelWindowWidget::mousePressEvent( QMouseEvent* mouseEvent ) {
  if ( m_LevelWindow.IsFixed() )
    return;
  m_MouseDown = true;
  m_StartPos = mouseEvent->pos();

  if ( mouseEvent->button() == Qt::LeftButton )
  {
    if (mouseEvent->modifiers() == Qt::ControlModifier || mouseEvent->modifiers() == Qt::ShiftModifier)
    {
      m_CtrlPressed = true;
    }
    else
    {
      m_CtrlPressed = false;
    }
    m_Leftbutton = true;
  }
  else
    m_Leftbutton = false;

  mouseMoveEvent( mouseEvent );
}

/**
*
*/
void QmitkSliderLevelWindowWidget::resizeEvent ( QResizeEvent * event ) {
  m_MoveHeight = event->size().height() - 25;
  update();
}

/**
*
*/
void QmitkSliderLevelWindowWidget::mouseReleaseEvent( QMouseEvent* )
{
  if ( m_LevelWindow.IsFixed() )
    return;
  m_MouseDown = false;
}

/**
*
*/
void QmitkSliderLevelWindowWidget::update() {
  int rectWidth;
  if(m_ScaleVisible)
  {
    rectWidth = 17;
    setMinimumSize ( QSize( 50, 50 ) );
    setMaximumSize ( QSize( 50, 2000 ) );
    setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ) );
  }
  else
  {
    rectWidth = 26;
    setMinimumSize ( QSize( 40, 50 ) );
    setMaximumSize ( QSize( 50, 2000 ) );
    setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ) );
  }
  float mr = m_LevelWindow.GetRange();

  if ( mr < 1 )
    mr = 1;

  float fact = (float) m_MoveHeight / mr;

  float rectHeight = m_LevelWindow.GetWindow() * fact;

  if ( rectHeight < 15 )
    rectHeight = 15;

  if ( m_LevelWindow.GetLowerWindowBound() < 0 )
    m_Rect.setRect( 2, (int) (m_MoveHeight - (m_LevelWindow.GetUpperWindowBound() - m_LevelWindow.GetRangeMin()) * fact) , rectWidth, (int) rectHeight );
  else
    m_Rect.setRect( 2, (int) (m_MoveHeight - (m_LevelWindow.GetUpperWindowBound() - m_LevelWindow.GetRangeMin()) * fact), rectWidth, (int) rectHeight );

  QWidget::repaint();
}

void QmitkSliderLevelWindowWidget::contextMenuEvent( QContextMenuEvent * )
{
  m_Contextmenu->setLevelWindowManager(m_Manager.GetPointer());
  QMenu *contextMenu = new QMenu( this );
  Q_CHECK_PTR( contextMenu );
  if (m_ScaleVisible)
    contextMenu->addAction(tr("Hide Scale"), this, SLOT(hideScale()));
  else
    contextMenu->addAction(tr("Show Scale"), this, SLOT(showScale()));
  contextMenu->addSeparator();
  m_Contextmenu->getContextMenu(contextMenu);

  // Fix: Bug #13327 we need to reset the m_MouseDown value
  // otherwise the cursor is not correctly restored afterwards
  m_MouseDown = false;
}

void QmitkSliderLevelWindowWidget::hideScale()
{
  m_ScaleVisible = false;
  update();
}

void QmitkSliderLevelWindowWidget::showScale()
{
  m_ScaleVisible = true;
  update();
}

void QmitkSliderLevelWindowWidget::setDataStorage(mitk::DataStorage* ds)
{
  m_Manager->SetDataStorage(ds);
}

mitk::LevelWindowManager* QmitkSliderLevelWindowWidget::GetManager()
{
  return m_Manager.GetPointer();
}
<|endoftext|>


<commit_before>#include <SFML\Graphics.hpp>
#include <Box2D\Box2D.h>
#include <array>
#include <memory>
#include <iostream>
#include <boost/math/special_functions/round.hpp>
#include "Marvin.h"
#include "SceneNode.h"
#include "SpriteNode.h"
#include "TextNode.h"
#include "TilemapNode.h"
#include "SoundNode.h"
#include "ResourceManager.h"
#include "TiledJSONLoader.h"
#include "Box2DTiledLoader.h"
#include "MapData.h"
#include "GameObjectFactory.h"
#include "EntityFactory.h"
#include "CollisionHandler.h"
#include "World.h"
#include "SaveManager.h"

World::World(sf::RenderWindow &window, SoundPlayer &soundPlayer, const std::string &map) :
        mWindow(window),
        mWorldView(mWindow.getDefaultView()),
        mTextureManager(TextureManager()),
        mFontManager(FontManager()),
        mSoundPlayer(soundPlayer),
        mMapLoader(TiledJSONLoader("Resources/Maps/", "Resources/Textures/Tileset/")),
        mWorldLoader(Box2DTiledLoader()),
        mCollisionHandler(CollisionHandler(*this)),
        mSceneGraph(SceneNode()),
        mPlayerCharacter(nullptr),
        numDeaths(0),
        mGemCollected(false),
        mResetRequested(false),
        mCompletionRequested(false),
        mCompleted(false),
        mMapLoaded(false),
        mObjectsLoaded(false),
        mTexturesLoaded(false),
        mMap(map){}

void World::initialize(){
    mMapLoader.load(mMap);
    mMapLoaded = mMapLoader.isMapLoaded();
    assert(mMapLoader.isMapLoaded());
    mMapData.tileWidth = mMapLoader.getTileSize().x;
    mMapData.tileHeight = mMapLoader.getTileSize().y;
    mMapData.mapWidth = mMapLoader.getMapSize().x;
    mMapData.mapHeight = mMapLoader.getMapSize().y;
    mMapData.tileLayers = mMapLoader.getTileLayers();
    mMapData.objectGroups = mMapLoader.getObjectGroups();

    mWorldLoader.load(mMapLoader.getTileLayers().back().tiles);
    mObjectsLoaded = mWorldLoader.isWorldLoaded();
    assert(mWorldLoader.isWorldLoaded());
    mBox2DWorld = std::unique_ptr<b2World>(mWorldLoader.getWorld());
    mBox2DWorld->SetContactListener(&mCollisionHandler);
    mGameObjectFactory = GameObjectFactory(mMapData, mBox2DWorld.get());
    loadResources();
    buildScene();
    mTexturesLoaded = true;

    centerPlayerView();
    mWindow.setView(mWorldView);
}

void World::reset(){
    mBox2DWorld.release();
    mLevelTimeElapsed = sf::Time::Zero;
    mCompletionTime = 0.0f;
    mPlayerCharacter = nullptr;
    mPlayerBody = nullptr;
    mWorldLoader.load(mMapData.tileLayers.back().tiles);
    assert(mWorldLoader.isWorldLoaded());
    mBox2DWorld = std::unique_ptr<b2World>(mWorldLoader.getWorld());
    mBox2DWorld->SetContactListener(&mCollisionHandler);
    mGameObjectFactory = GameObjectFactory(mMapData, mBox2DWorld.get());
    for (std::size_t i = 0; i < LayerCount; ++i){
        mSceneGraph.detachChild(*mSceneLayers[i]);
    }
    mSceneLayers.empty();
    buildScene();
    centerPlayerView();
    mResetRequested = false;
    ++numDeaths;
}

void World::requestReset(){
    mResetRequested = true;
    Command resetSoundCommand;
    resetSoundCommand.category = Category::SoundEffect;
    resetSoundCommand.action = [](SceneNode &node, sf::Time deltaTime){
        SoundNode &sound = static_cast<SoundNode&>(node);
        sound.play(SoundEffectID::PlayerDie);
    };
    mCommandQueue.push(resetSoundCommand);
}

CommandQueue& World::getCommandQueue(){
    return mCommandQueue;
}

void World::update(sf::Time deltaTime){

    if (!mCompletionRequested){
        mLevelTimeElapsed += deltaTime;

        //It's important we advance our physics engine before updating
        mBox2DWorld->Step(deltaTime.asSeconds(), 6, 2);

        while (!mCommandQueue.empty()){
            mSceneGraph.onCommand(mCommandQueue.front(), deltaTime);
            mCommandQueue.pop();
        }

        mSceneGraph.removeChildren();
        mSceneGraph.update(deltaTime);
        centerPlayerView();

        //Reposition and update our time
        std::ostringstream timeStream;
        timeStream << boost::math::round(
            mLevelTimeElapsed.asSeconds() * 100.f) / 100.f;
        mTimeText->setText(timeStream.str());
        mTimeText->setPosition(
            mWorldView.getCenter().x + mWorldView.getSize().x / 2.f - 125.f,
            mWorldView.getCenter().y - mWorldView.getSize().y / 2.f + 25.f);

        if (mResetRequested)
            reset();
    }

    else if (!mPlayerCharacter->isFaded()){
        mPlayerCharacter->update(deltaTime);
    }

    else{
        mCompleted = true;
    }

    mSoundPlayer.removeStoppedSounds();
}

void World::requestCompletion(){
    mCompletionRequested = true;
    std::ostringstream timeStream;
    mCompletionTime = boost::math::round(mLevelTimeElapsed.asSeconds() * 100.f) / 100.f;
    mPlayerCharacter->fade();
    Command fadeSoundCommand;
    fadeSoundCommand.category = Category::SoundEffect;
    fadeSoundCommand.action = [](SceneNode &node, sf::Time deltaTime){
        SoundNode &sound = static_cast<SoundNode&>(node);
        sound.play(SoundEffectID::PlayerFade);
    };
    mCommandQueue.push(fadeSoundCommand);
}

bool World::isComplete(){
    return mCompleted;
}

float World::getAttemptTime(){
    return mCompletionTime;
}

int World::getNumDeaths(){
    return numDeaths;
}

bool World::isGemCollected(){
    return mGemCollected;
}

void World::collectGem(){
    mGemCollected = true;
}

void World::centerPlayerView(){

    //Make sure our view is inside map bounds
    float viewWidth =  mWorldView.getSize().x;
    float viewHeight = mWorldView.getSize().y;
    sf::Vector2f viewCenter = mWorldView.getCenter();
    sf::Vector2f playerPos = mPlayerCharacter->getRenderPosition();
    float mMapWidthPixels = mMapData.mapWidth * 70.f;
    float mMapHeightPixels = mMapData.mapHeight * 70.f;

    float xOffset = 0;
    float yOffset = 0;

    if (playerPos.y - viewHeight/2 < 0)
        yOffset = fabs(playerPos.y - viewHeight/2);
    else if (playerPos.y + viewHeight/2 > mMapHeightPixels)
        yOffset = -1 * (viewHeight/2 - (mMapHeightPixels - playerPos.y));
    if (playerPos.x - viewWidth/2 < 0)
        xOffset = fabs(playerPos.x - viewWidth/2);
    else if (playerPos.x + viewWidth/2 > mMapWidthPixels)
        xOffset = -1 * (viewWidth/2 - (mMapWidthPixels - playerPos.x));

    sf::Vector2f newCenter(playerPos.x + xOffset, playerPos.y + yOffset);
    mWorldView.setCenter(newCenter);
}

void World::draw(){
    mWindow.setView(mWorldView);
    mWindow.draw(mSceneGraph);
    renderStaticBodyFixtures();
}

void World::loadResources(){

    //Load our backgrounds
    mTextureManager.load(TextureID::GrasslandsBackground, "Resources/Textures/Background/bg.png");

    //Load our player
    mTextureManager.load(TextureID::PlayerSpriteSheet, "Resources/Textures/Player/player_spritesheet.png");
    mTextureManager.load(TextureID::PlayerStanding, "Resources/Textures/Player/alienGreen_stand.png");

    //Load entities
    mTextureManager.load(TextureID::EnemiesSpriteSheet, "Resources/Textures/Enemy/enemies_spritesheet.png");

    //Load fonts
    mFontManager.load(FontID::Thin, "Resources/Fonts/kenvector_future_thin.ttf");
}

void World::buildScene(){

    //Setup our layers
    for (std::size_t i = 0; i < LayerCount; ++i){
        SceneNode::Ptr layer(new SceneNode());
        mSceneLayers[i] = layer.get();
        mSceneGraph.attachChild(std::move(layer));
    }

    //Background layer
    sf::Texture &texture = mTextureManager.get(TextureID::GrasslandsBackground);
    texture.setRepeated(true);
    std::unique_ptr<SpriteNode> backgroundSprite(new SpriteNode(texture, sf::IntRect(0, 0, mMapData.mapWidth * 70, mMapData.mapHeight * 70)));
    mSceneLayers[Background]->attachChild(std::move(backgroundSprite));

    //Tilemap layer
    std::unique_ptr<TilemapNode> tileMap(
        new TilemapNode(mMapData, mWorldLoader.getContours()));
    mSceneLayers[Tilemap]->attachChild(std::move(tileMap));

    //Object layer (players, enemies, etc)
    EntityFactory entityFactory = EntityFactory(mTextureManager, mMapData, mBox2DWorld.get());
    for(auto &objectGroup : mMapData.objectGroups){
        if (objectGroup.name == "Objects"){
            for (auto &object : objectGroup.objects){
              if (object.type == "Gem" && SaveManager::getInstance().getLevelData(mMap).collectedGem)
                  continue;
                mSceneLayers[Object]->attachChild(
                    GameObject::Ptr(mGameObjectFactory.createGameObject(object)));
            }
        }
        else if (objectGroup.name == "Spawns"){
            for (auto &object : objectGroup.objects){
                if (object.type == "Player")
                    spawnPlayer(object.position);
                else{
                    mSceneLayers[Object]->attachChild(
                        Entity::Ptr(entityFactory.createEntity(object)));
                }
            }
        }
    }
    mSceneLayers[Object]->attachChild(std::move(std::unique_ptr<Marvin>(mPlayerCharacter)));

    //HUD Layer
    sf::Font &timeFont = mFontManager.get(FontID::Thin);
    std::unique_ptr<TextNode> timeText(new TextNode(timeFont));
    mTimeText = timeText.get();
    mTimeText->setColor(sf::Color::Black);
    mSceneLayers[HUD]->attachChild(std::move(timeText));

    //Sound Effects
    std::unique_ptr<SoundNode> soundEffects(new SoundNode(mSoundPlayer));
    mSceneLayers[Sounds]->attachChild(std::move(soundEffects));
}

void World::spawnPlayer(sf::Vector2f position){

    sf::Sprite playerSprite(mTextureManager.get(TextureID::PlayerStanding));
    sf::FloatRect bounds = playerSprite.getGlobalBounds();
    sf::Vector2f renderPos = position + sf::Vector2f(0.f, bounds.height/2);
    sf::Vector2f centerPlayerPos = sf::Vector2f(
        renderPos.x,
        mMapData.mapHeight*70.f - renderPos.y);

    //Create our box2D body
    b2BodyDef playerDef;
    playerDef.fixedRotation = true;
    playerDef.type = b2_dynamicBody;
    playerDef.position.Set(centerPlayerPos.x / 70.f, centerPlayerPos.y / 70.f);
    mPlayerBody = mBox2DWorld->CreateBody(&playerDef);

    //Bounding box with no friction to prevent sticking to static body walls
    b2PolygonShape boundingBox;
    boundingBox.SetAsBox(bounds.width / 70.f / 2 - 0.1f, bounds.height / 70.f / 2);
    b2FixtureDef playerFixture;
    playerFixture.friction = 0.f;
    playerFixture.shape = &boundingBox;
    mPlayerBody->CreateFixture(&playerFixture);

    //Special foot sensor to manage jumping/movement
    b2PolygonShape footShape;
    b2Vec2 footVertices[4];
    footVertices[0] = b2Vec2(-bounds.width / 70.f / 2 + 0.2f, -bounds.height / 70.f / 2 - 0.04f);
    footVertices[1] = b2Vec2(-bounds.width / 70.f / 2 + 0.2f, -bounds.height / 70.f / 2 + 0.05f);
    footVertices[2] = b2Vec2(bounds.width / 70.f / 2 - 0.2f, -bounds.height / 70.f / 2 + 0.05f);
    footVertices[3] = b2Vec2(bounds.width / 70.f / 2 - 0.2f, -bounds.height / 70.f / 2 - 0.04f);
    footShape.Set(footVertices,4);
    b2FixtureDef footFixture;
    footFixture.isSensor = true;
    footFixture.friction = 0.25f;
    footFixture.shape = &footShape;
    mPlayerBody->CreateFixture(&footFixture);

    mPlayerCharacter = new Marvin(mTextureManager, mPlayerBody);
    mPlayerCharacter->setRenderPosition(renderPos);
    mPlayerBody->SetUserData(mPlayerCharacter);
}

void World::renderStaticBodyFixtures(){

    for (b2Body *b = mBox2DWorld->GetBodyList(); b; b = b->GetNext()){

        if (static_cast<SceneNode*>(b->GetUserData())->getCategory() & Category::Type::Walkable){
            for (b2Fixture *fixture = b->GetFixtureList(); fixture; fixture = fixture->GetNext()){

                //We know it's a chain shape
                b2ChainShape *chain = static_cast<b2ChainShape*>(fixture->GetShape());
                sf::VertexArray lines(sf::PrimitiveType::Lines);

                for (int i = 0; i < chain->GetChildCount(); ++i){

                    b2EdgeShape edge;
                    chain->GetChildEdge(&edge, i);
                    b2Vec2 v1 = edge.m_vertex1;
                    b2Vec2 v2 = edge.m_vertex2;
                    lines.append(sf::Vertex(sf::Vector2f(v1.x * 70.f, (mMapData.mapHeight * 70) - v1.y * 70.f), sf::Color::Blue));
                    lines.append(sf::Vertex(sf::Vector2f(v2.x * 70.f, (mMapData.mapHeight * 70) - v2.y * 70.f), sf::Color::Blue));
                }
                mWindow.draw(lines);
            }
        }
    }
}

void World::onResolutionChange(){

    mWorldView.setSize(sf::Vector2f(
        mWindow.getSize().x,
        mWindow.getSize().y));
    centerPlayerView();
    mTimeText->setPosition(
        mWorldView.getCenter().x + mWorldView.getSize().x / 2.f - 125.f,
        mWorldView.getCenter().y - mWorldView.getSize().y / 2.f + 25.f);
}

bool World::mapLoaded(){ return mMapLoaded; }

bool World::objectsLoaded(){ return mObjectsLoaded; }

bool World::texturesLoaded(){ return mTexturesLoaded; }<commit_msg>Removed static body rendering, woops<commit_after>#include <SFML\Graphics.hpp>
#include <Box2D\Box2D.h>
#include <array>
#include <memory>
#include <iostream>
#include <boost/math/special_functions/round.hpp>
#include "Marvin.h"
#include "SceneNode.h"
#include "SpriteNode.h"
#include "TextNode.h"
#include "TilemapNode.h"
#include "SoundNode.h"
#include "ResourceManager.h"
#include "TiledJSONLoader.h"
#include "Box2DTiledLoader.h"
#include "MapData.h"
#include "GameObjectFactory.h"
#include "EntityFactory.h"
#include "CollisionHandler.h"
#include "World.h"
#include "SaveManager.h"

World::World(sf::RenderWindow &window, SoundPlayer &soundPlayer, const std::string &map) :
        mWindow(window),
        mWorldView(mWindow.getDefaultView()),
        mTextureManager(TextureManager()),
        mFontManager(FontManager()),
        mSoundPlayer(soundPlayer),
        mMapLoader(TiledJSONLoader("Resources/Maps/", "Resources/Textures/Tileset/")),
        mWorldLoader(Box2DTiledLoader()),
        mCollisionHandler(CollisionHandler(*this)),
        mSceneGraph(SceneNode()),
        mPlayerCharacter(nullptr),
        numDeaths(0),
        mGemCollected(false),
        mResetRequested(false),
        mCompletionRequested(false),
        mCompleted(false),
        mMapLoaded(false),
        mObjectsLoaded(false),
        mTexturesLoaded(false),
        mMap(map){}

void World::initialize(){
    mMapLoader.load(mMap);
    mMapLoaded = mMapLoader.isMapLoaded();
    assert(mMapLoader.isMapLoaded());
    mMapData.tileWidth = mMapLoader.getTileSize().x;
    mMapData.tileHeight = mMapLoader.getTileSize().y;
    mMapData.mapWidth = mMapLoader.getMapSize().x;
    mMapData.mapHeight = mMapLoader.getMapSize().y;
    mMapData.tileLayers = mMapLoader.getTileLayers();
    mMapData.objectGroups = mMapLoader.getObjectGroups();

    mWorldLoader.load(mMapLoader.getTileLayers().back().tiles);
    mObjectsLoaded = mWorldLoader.isWorldLoaded();
    assert(mWorldLoader.isWorldLoaded());
    mBox2DWorld = std::unique_ptr<b2World>(mWorldLoader.getWorld());
    mBox2DWorld->SetContactListener(&mCollisionHandler);
    mGameObjectFactory = GameObjectFactory(mMapData, mBox2DWorld.get());
    loadResources();
    buildScene();
    mTexturesLoaded = true;

    centerPlayerView();
    mWindow.setView(mWorldView);
}

void World::reset(){
    mBox2DWorld.release();
    mLevelTimeElapsed = sf::Time::Zero;
    mCompletionTime = 0.0f;
    mPlayerCharacter = nullptr;
    mPlayerBody = nullptr;
    mWorldLoader.load(mMapData.tileLayers.back().tiles);
    assert(mWorldLoader.isWorldLoaded());
    mBox2DWorld = std::unique_ptr<b2World>(mWorldLoader.getWorld());
    mBox2DWorld->SetContactListener(&mCollisionHandler);
    mGameObjectFactory = GameObjectFactory(mMapData, mBox2DWorld.get());
    for (std::size_t i = 0; i < LayerCount; ++i){
        mSceneGraph.detachChild(*mSceneLayers[i]);
    }
    mSceneLayers.empty();
    buildScene();
    centerPlayerView();
    mResetRequested = false;
    ++numDeaths;
}

void World::requestReset(){
    mResetRequested = true;
    Command resetSoundCommand;
    resetSoundCommand.category = Category::SoundEffect;
    resetSoundCommand.action = [](SceneNode &node, sf::Time deltaTime){
        SoundNode &sound = static_cast<SoundNode&>(node);
        sound.play(SoundEffectID::PlayerDie);
    };
    mCommandQueue.push(resetSoundCommand);
}

CommandQueue& World::getCommandQueue(){
    return mCommandQueue;
}

void World::update(sf::Time deltaTime){

    if (!mCompletionRequested){
        mLevelTimeElapsed += deltaTime;

        //It's important we advance our physics engine before updating
        mBox2DWorld->Step(deltaTime.asSeconds(), 6, 2);

        while (!mCommandQueue.empty()){
            mSceneGraph.onCommand(mCommandQueue.front(), deltaTime);
            mCommandQueue.pop();
        }

        mSceneGraph.removeChildren();
        mSceneGraph.update(deltaTime);
        centerPlayerView();

        //Reposition and update our time
        std::ostringstream timeStream;
        timeStream << boost::math::round(
            mLevelTimeElapsed.asSeconds() * 100.f) / 100.f;
        mTimeText->setText(timeStream.str());
        mTimeText->setPosition(
            mWorldView.getCenter().x + mWorldView.getSize().x / 2.f - 125.f,
            mWorldView.getCenter().y - mWorldView.getSize().y / 2.f + 25.f);

        if (mResetRequested)
            reset();
    }

    else if (!mPlayerCharacter->isFaded()){
        mPlayerCharacter->update(deltaTime);
    }

    else{
        mCompleted = true;
    }

    mSoundPlayer.removeStoppedSounds();
}

void World::requestCompletion(){
    mCompletionRequested = true;
    std::ostringstream timeStream;
    mCompletionTime = boost::math::round(mLevelTimeElapsed.asSeconds() * 100.f) / 100.f;
    mPlayerCharacter->fade();
    Command fadeSoundCommand;
    fadeSoundCommand.category = Category::SoundEffect;
    fadeSoundCommand.action = [](SceneNode &node, sf::Time deltaTime){
        SoundNode &sound = static_cast<SoundNode&>(node);
        sound.play(SoundEffectID::PlayerFade);
    };
    mCommandQueue.push(fadeSoundCommand);
}

bool World::isComplete(){
    return mCompleted;
}

float World::getAttemptTime(){
    return mCompletionTime;
}

int World::getNumDeaths(){
    return numDeaths;
}

bool World::isGemCollected(){
    return mGemCollected;
}

void World::collectGem(){
    mGemCollected = true;
}

void World::centerPlayerView(){

    //Make sure our view is inside map bounds
    float viewWidth =  mWorldView.getSize().x;
    float viewHeight = mWorldView.getSize().y;
    sf::Vector2f viewCenter = mWorldView.getCenter();
    sf::Vector2f playerPos = mPlayerCharacter->getRenderPosition();
    float mMapWidthPixels = mMapData.mapWidth * 70.f;
    float mMapHeightPixels = mMapData.mapHeight * 70.f;

    float xOffset = 0;
    float yOffset = 0;

    if (playerPos.y - viewHeight/2 < 0)
        yOffset = fabs(playerPos.y - viewHeight/2);
    else if (playerPos.y + viewHeight/2 > mMapHeightPixels)
        yOffset = -1 * (viewHeight/2 - (mMapHeightPixels - playerPos.y));
    if (playerPos.x - viewWidth/2 < 0)
        xOffset = fabs(playerPos.x - viewWidth/2);
    else if (playerPos.x + viewWidth/2 > mMapWidthPixels)
        xOffset = -1 * (viewWidth/2 - (mMapWidthPixels - playerPos.x));

    sf::Vector2f newCenter(playerPos.x + xOffset, playerPos.y + yOffset);
    mWorldView.setCenter(newCenter);
}

void World::draw(){
    mWindow.setView(mWorldView);
    mWindow.draw(mSceneGraph);
}

void World::loadResources(){

    //Load our backgrounds
    mTextureManager.load(TextureID::GrasslandsBackground, "Resources/Textures/Background/bg.png");

    //Load our player
    mTextureManager.load(TextureID::PlayerSpriteSheet, "Resources/Textures/Player/player_spritesheet.png");
    mTextureManager.load(TextureID::PlayerStanding, "Resources/Textures/Player/alienGreen_stand.png");

    //Load entities
    mTextureManager.load(TextureID::EnemiesSpriteSheet, "Resources/Textures/Enemy/enemies_spritesheet.png");

    //Load fonts
    mFontManager.load(FontID::Thin, "Resources/Fonts/kenvector_future_thin.ttf");
}

void World::buildScene(){

    //Setup our layers
    for (std::size_t i = 0; i < LayerCount; ++i){
        SceneNode::Ptr layer(new SceneNode());
        mSceneLayers[i] = layer.get();
        mSceneGraph.attachChild(std::move(layer));
    }

    //Background layer
    sf::Texture &texture = mTextureManager.get(TextureID::GrasslandsBackground);
    texture.setRepeated(true);
    std::unique_ptr<SpriteNode> backgroundSprite(new SpriteNode(texture, sf::IntRect(0, 0, mMapData.mapWidth * 70, mMapData.mapHeight * 70)));
    mSceneLayers[Background]->attachChild(std::move(backgroundSprite));

    //Tilemap layer
    std::unique_ptr<TilemapNode> tileMap(
        new TilemapNode(mMapData, mWorldLoader.getContours()));
    mSceneLayers[Tilemap]->attachChild(std::move(tileMap));

    //Object layer (players, enemies, etc)
    EntityFactory entityFactory = EntityFactory(mTextureManager, mMapData, mBox2DWorld.get());
    for(auto &objectGroup : mMapData.objectGroups){
        if (objectGroup.name == "Objects"){
            for (auto &object : objectGroup.objects){
              if (object.type == "Gem" && SaveManager::getInstance().getLevelData(mMap).collectedGem)
                  continue;
                mSceneLayers[Object]->attachChild(
                    GameObject::Ptr(mGameObjectFactory.createGameObject(object)));
            }
        }
        else if (objectGroup.name == "Spawns"){
            for (auto &object : objectGroup.objects){
                if (object.type == "Player")
                    spawnPlayer(object.position);
                else{
                    mSceneLayers[Object]->attachChild(
                        Entity::Ptr(entityFactory.createEntity(object)));
                }
            }
        }
    }
    mSceneLayers[Object]->attachChild(std::move(std::unique_ptr<Marvin>(mPlayerCharacter)));

    //HUD Layer
    sf::Font &timeFont = mFontManager.get(FontID::Thin);
    std::unique_ptr<TextNode> timeText(new TextNode(timeFont));
    mTimeText = timeText.get();
    mTimeText->setColor(sf::Color::Black);
    mSceneLayers[HUD]->attachChild(std::move(timeText));

    //Sound Effects
    std::unique_ptr<SoundNode> soundEffects(new SoundNode(mSoundPlayer));
    mSceneLayers[Sounds]->attachChild(std::move(soundEffects));
}

void World::spawnPlayer(sf::Vector2f position){

    sf::Sprite playerSprite(mTextureManager.get(TextureID::PlayerStanding));
    sf::FloatRect bounds = playerSprite.getGlobalBounds();
    sf::Vector2f renderPos = position + sf::Vector2f(0.f, bounds.height/2);
    sf::Vector2f centerPlayerPos = sf::Vector2f(
        renderPos.x,
        mMapData.mapHeight*70.f - renderPos.y);

    //Create our box2D body
    b2BodyDef playerDef;
    playerDef.fixedRotation = true;
    playerDef.type = b2_dynamicBody;
    playerDef.position.Set(centerPlayerPos.x / 70.f, centerPlayerPos.y / 70.f);
    mPlayerBody = mBox2DWorld->CreateBody(&playerDef);

    //Bounding box with no friction to prevent sticking to static body walls
    b2PolygonShape boundingBox;
    boundingBox.SetAsBox(bounds.width / 70.f / 2 - 0.1f, bounds.height / 70.f / 2);
    b2FixtureDef playerFixture;
    playerFixture.friction = 0.f;
    playerFixture.shape = &boundingBox;
    mPlayerBody->CreateFixture(&playerFixture);

    //Special foot sensor to manage jumping/movement
    b2PolygonShape footShape;
    b2Vec2 footVertices[4];
    footVertices[0] = b2Vec2(-bounds.width / 70.f / 2 + 0.2f, -bounds.height / 70.f / 2 - 0.04f);
    footVertices[1] = b2Vec2(-bounds.width / 70.f / 2 + 0.2f, -bounds.height / 70.f / 2 + 0.05f);
    footVertices[2] = b2Vec2(bounds.width / 70.f / 2 - 0.2f, -bounds.height / 70.f / 2 + 0.05f);
    footVertices[3] = b2Vec2(bounds.width / 70.f / 2 - 0.2f, -bounds.height / 70.f / 2 - 0.04f);
    footShape.Set(footVertices,4);
    b2FixtureDef footFixture;
    footFixture.isSensor = true;
    footFixture.friction = 0.25f;
    footFixture.shape = &footShape;
    mPlayerBody->CreateFixture(&footFixture);

    mPlayerCharacter = new Marvin(mTextureManager, mPlayerBody);
    mPlayerCharacter->setRenderPosition(renderPos);
    mPlayerBody->SetUserData(mPlayerCharacter);
}

void World::renderStaticBodyFixtures(){

    for (b2Body *b = mBox2DWorld->GetBodyList(); b; b = b->GetNext()){

        if (static_cast<SceneNode*>(b->GetUserData())->getCategory() & Category::Type::Walkable){
            for (b2Fixture *fixture = b->GetFixtureList(); fixture; fixture = fixture->GetNext()){

                //We know it's a chain shape
                b2ChainShape *chain = static_cast<b2ChainShape*>(fixture->GetShape());
                sf::VertexArray lines(sf::PrimitiveType::Lines);

                for (int i = 0; i < chain->GetChildCount(); ++i){

                    b2EdgeShape edge;
                    chain->GetChildEdge(&edge, i);
                    b2Vec2 v1 = edge.m_vertex1;
                    b2Vec2 v2 = edge.m_vertex2;
                    lines.append(sf::Vertex(sf::Vector2f(v1.x * 70.f, (mMapData.mapHeight * 70) - v1.y * 70.f), sf::Color::Blue));
                    lines.append(sf::Vertex(sf::Vector2f(v2.x * 70.f, (mMapData.mapHeight * 70) - v2.y * 70.f), sf::Color::Blue));
                }
                mWindow.draw(lines);
            }
        }
    }
}

void World::onResolutionChange(){

    mWorldView.setSize(sf::Vector2f(
        mWindow.getSize().x,
        mWindow.getSize().y));
    centerPlayerView();
    mTimeText->setPosition(
        mWorldView.getCenter().x + mWorldView.getSize().x / 2.f - 125.f,
        mWorldView.getCenter().y - mWorldView.getSize().y / 2.f + 25.f);
}

bool World::mapLoaded(){ return mMapLoaded; }

bool World::objectsLoaded(){ return mObjectsLoaded; }

bool World::texturesLoaded(){ return mTexturesLoaded; }<|endoftext|>


<commit_before>#ifndef ITER_COMPRESS_H_
#define ITER_COMPRESS_H_

#include "internal/iterator_wrapper.hpp"
#include "internal/iterbase.hpp"

#include <iterator>
#include <utility>

namespace iter {
  namespace impl {
    template <typename Container, typename Selector>
    class Compressed;
  }

  template <typename Container, typename Selector>
  impl::Compressed<Container, Selector> compress(Container&&, Selector&&);
}

template <typename Container, typename Selector>
class iter::impl::Compressed {
 private:
  Container container;
  Selector selectors;

  friend Compressed iter::compress<Container, Selector>(
      Container&&, Selector&&);

  // Selector::Iterator type
  using selector_iter_type = decltype(std::begin(selectors));

  Compressed(Container&& in_container, Selector&& in_selectors)
      : container(std::forward<Container>(in_container)),
        selectors(std::forward<Selector>(in_selectors)) {}

 public:
  Compressed(Compressed&&) = default;
  class Iterator : public std::iterator<std::input_iterator_tag,
                       iterator_traits_deref<Container>> {
   private:
    IteratorWrapper<Container> sub_iter;
    IteratorWrapper<Container> sub_end;

    selector_iter_type selector_iter;
    selector_iter_type selector_end;

    void increment_iterators() {
      ++this->sub_iter;
      ++this->selector_iter;
    }

    void skip_failures() {
      while (this->sub_iter != this->sub_end
             && this->selector_iter != this->selector_end
             && !*this->selector_iter) {
        this->increment_iterators();
      }
    }

   public:
    Iterator(IteratorWrapper<Container>&& cont_iter,
        IteratorWrapper<Container>&& cont_end, selector_iter_type&& sel_iter,
        selector_iter_type&& sel_end)
        : sub_iter{std::move(cont_iter)},
          sub_end{std::move(cont_end)},
          selector_iter{std::move(sel_iter)},
          selector_end{std::move(sel_end)} {
      this->skip_failures();
    }

    iterator_deref<Container> operator*() {
      return *this->sub_iter;
    }

    iterator_arrow<Container> operator->() {
      return apply_arrow(this->sub_iter);
    }

    Iterator& operator++() {
      this->increment_iterators();
      this->skip_failures();
      return *this;
    }

    Iterator operator++(int) {
      auto ret = *this;
      ++*this;
      return ret;
    }

    bool operator!=(const Iterator& other) const {
      return this->sub_iter != other.sub_iter
             && this->selector_iter != other.selector_iter;
    }

    bool operator==(const Iterator& other) const {
      return !(*this != other);
    }
  };

  Iterator begin() {
    return {std::begin(this->container), std::end(this->container),
        std::begin(this->selectors), std::end(this->selectors)};
  }

  Iterator end() {
    return {std::end(this->container), std::end(this->container),
        std::end(this->selectors), std::end(this->selectors)};
  }
};

template <typename Container, typename Selector>
iter::impl::Compressed<Container, Selector> iter::compress(
    Container&& container, Selector&& selectors) {
  return {
      std::forward<Container>(container), std::forward<Selector>(selectors)};
}

#endif
<commit_msg>trailing _ on data members<commit_after>#ifndef ITER_COMPRESS_H_
#define ITER_COMPRESS_H_

#include "internal/iterator_wrapper.hpp"
#include "internal/iterbase.hpp"

#include <iterator>
#include <utility>

namespace iter {
  namespace impl {
    template <typename Container, typename Selector>
    class Compressed;
  }

  template <typename Container, typename Selector>
  impl::Compressed<Container, Selector> compress(Container&&, Selector&&);
}

template <typename Container, typename Selector>
class iter::impl::Compressed {
 private:
  Container container_;
  Selector selectors_;

  friend Compressed iter::compress<Container, Selector>(
      Container&&, Selector&&);

  // Selector::Iterator type
  using selector_iter_type = decltype(std::begin(selectors_));

  Compressed(Container&& in_container, Selector&& in_selectors)
      : container_(std::forward<Container>(in_container)),
        selectors_(std::forward<Selector>(in_selectors)) {}

 public:
  Compressed(Compressed&&) = default;
  class Iterator : public std::iterator<std::input_iterator_tag,
                       iterator_traits_deref<Container>> {
   private:
    IteratorWrapper<Container> sub_iter_;
    IteratorWrapper<Container> sub_end_;

    selector_iter_type selector_iter_;
    selector_iter_type selector_end_;

    void increment_iterators() {
      ++sub_iter_;
      ++selector_iter_;
    }

    void skip_failures() {
      while (sub_iter_ != sub_end_ && selector_iter_ != selector_end_
             && !*selector_iter_) {
        increment_iterators();
      }
    }

   public:
    Iterator(IteratorWrapper<Container>&& cont_iter,
        IteratorWrapper<Container>&& cont_end, selector_iter_type&& sel_iter,
        selector_iter_type&& sel_end)
        : sub_iter_{std::move(cont_iter)},
          sub_end_{std::move(cont_end)},
          selector_iter_{std::move(sel_iter)},
          selector_end_{std::move(sel_end)} {
      skip_failures();
    }

    iterator_deref<Container> operator*() {
      return *sub_iter_;
    }

    iterator_arrow<Container> operator->() {
      return apply_arrow(sub_iter_);
    }

    Iterator& operator++() {
      increment_iterators();
      skip_failures();
      return *this;
    }

    Iterator operator++(int) {
      auto ret = *this;
      ++*this;
      return ret;
    }

    bool operator!=(const Iterator& other) const {
      return sub_iter_ != other.sub_iter_
             && selector_iter_ != other.selector_iter_;
    }

    bool operator==(const Iterator& other) const {
      return !(*this != other);
    }
  };

  Iterator begin() {
    return {std::begin(container_), std::end(container_),
        std::begin(selectors_), std::end(selectors_)};
  }

  Iterator end() {
    return {std::end(container_), std::end(container_), std::end(selectors_),
        std::end(selectors_)};
  }
};

template <typename Container, typename Selector>
iter::impl::Compressed<Container, Selector> iter::compress(
    Container&& container_, Selector&& selectors_) {
  return {
      std::forward<Container>(container_), std::forward<Selector>(selectors_)};
}

#endif
<|endoftext|>