<commit_before>/***********************************************************************************************************************
**
** Copyright (c) 2011, 2015 ETH Zurich
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
** following conditions are met:
**
** * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
** disclaimer.
** * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
** following disclaimer in the documentation and/or other materials provided with the distribution.
** * Neither the name of the ETH Zurich nor the names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
***********************************************************************************************************************/

#include "Commit.h"

namespace FilePersistence {

Signature::Signature()
{
	dateTime_ = QDateTime::currentDateTimeUtc();
	timeZone_ = QTimeZone{QTimeZone::systemTimeZoneId()};
}

CommitFile::CommitFile(){}

CommitFile::CommitFile(QString relativePath, qint64 size, std::unique_ptr<char[]> content)
	: relativePath_{relativePath}, size_{size}, content_{std::move(content)}
{}

CommitFile::CommitFile(QString relativePath, qint64 size, std::unique_ptr<char[], CommitFileContentDeleter> content)
	: relativePath_{relativePath}, size_{size}, contentWithDeleter_{std::move(content)}
{}

const char* CommitFile::content() const
{
	Q_ASSERT((content_ && !contentWithDeleter_) || (!content_ && contentWithDeleter_));
	if (content_)
		return content_.get();
	else
		return contentWithDeleter_.get();
}

Commit::Commit() {}

Commit::~Commit()
{
	for (auto file : files_.values())
		SAFE_DELETE(file);
}

void Commit::addFile(QString relativePath, qint64 size, std::unique_ptr<char[]> content)
{
	files_.insert(relativePath, new CommitFile{relativePath, size, std::move(content)});
}

void Commit::addFile(QString relativePath, qint64 size, std::unique_ptr<char[], CommitFileContentDeleter> content)
{
	files_.insert(relativePath, new CommitFile{relativePath, size, std::move(content)});
}

bool Commit::getFileContent(QString fileName, const char*& content, int& contentSize, bool exactFileNameMatching) const
{
	QHash<QString, CommitFile*>::const_iterator iter;

	// name of file must match fileName exactly
	if (exactFileNameMatching)
		iter = files_.find(fileName);
	// name of file must contain fileName
	else
	{
		iter = files_.constBegin();
		while (iter != files_.constEnd())
		{
			QFileInfo fileInfo{iter.key()};
			if ((fileName.startsWith("{") && fileInfo.fileName().contains(fileName))|| fileInfo.fileName() == fileName)
				break;
			iter++;
		}
	}

	if (iter != files_.constEnd())
	{
		contentSize = iter.value()->size_;
		content = iter.value()->content();
		return true;
	}
	else
		return false;
}

}
<commit_msg>Add isDir check<commit_after>/***********************************************************************************************************************
**
** Copyright (c) 2011, 2015 ETH Zurich
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
** following conditions are met:
**
** * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
** disclaimer.
** * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
** following disclaimer in the documentation and/or other materials provided with the distribution.
** * Neither the name of the ETH Zurich nor the names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
***********************************************************************************************************************/

#include "Commit.h"

namespace FilePersistence {

Signature::Signature()
{
	dateTime_ = QDateTime::currentDateTimeUtc();
	timeZone_ = QTimeZone{QTimeZone::systemTimeZoneId()};
}

CommitFile::CommitFile(){}

CommitFile::CommitFile(QString relativePath, qint64 size, std::unique_ptr<char[]> content)
	: relativePath_{relativePath}, size_{size}, content_{std::move(content)}
{}

CommitFile::CommitFile(QString relativePath, qint64 size, std::unique_ptr<char[], CommitFileContentDeleter> content)
	: relativePath_{relativePath}, size_{size}, contentWithDeleter_{std::move(content)}
{}

const char* CommitFile::content() const
{
	Q_ASSERT((content_ && !contentWithDeleter_) || (!content_ && contentWithDeleter_));
	if (content_)
		return content_.get();
	else
		return contentWithDeleter_.get();
}

Commit::Commit() {}

Commit::~Commit()
{
	for (auto file : files_.values())
		SAFE_DELETE(file);
}

void Commit::addFile(QString relativePath, qint64 size, std::unique_ptr<char[]> content)
{
	files_.insert(relativePath, new CommitFile{relativePath, size, std::move(content)});
}

void Commit::addFile(QString relativePath, qint64 size, std::unique_ptr<char[], CommitFileContentDeleter> content)
{
	files_.insert(relativePath, new CommitFile{relativePath, size, std::move(content)});
}

bool Commit::getFileContent(QString fileName, const char*& content, int& contentSize, bool exactFileNameMatching) const
{
	QHash<QString, CommitFile*>::const_iterator iter;

	// name of file must match fileName exactly
	if (exactFileNameMatching)
		iter = files_.find(fileName);
	// name of file must contain fileName
	else
	{
		iter = files_.constBegin();
		while (iter != files_.constEnd())
		{
			QFileInfo fileInfo{iter.key()};
			if (!fileInfo.isDir() &&
				 ((fileName.startsWith("{") && fileInfo.fileName().contains(fileName))
				 || fileInfo.fileName() == fileName))
				break;
			iter++;
		}
	}

	if (iter != files_.constEnd())
	{
		contentSize = iter.value()->size_;
		content = iter.value()->content();
		return true;
	}
	else
		return false;
}

}
<|endoftext|>


<commit_before>#include "PortalGame.h"
#include "PhysicsController.h"
#include "Sphere.h"
#include "PhysicsCamera.h"
#include "Box.h"
#include "Cylinder.h"
#include "Steerable3DController.h"
#include "Ground.h"
#include "Content.h"
#include <btBulletDynamicsCommon.h>
#include <gtc/quaternion.hpp>
#include <gtx/quaternion.hpp>
#include <gtx/euler_angles.hpp>
#include <gtx/norm.hpp>
#include "VectorDrawer.h"

using namespace BGE;

PortalGame::PortalGame(void)
{
	physicsFactory = NULL;
	dynamicsWorld = NULL;
	broadphase = NULL;
	dispatcher = NULL;
	solver = NULL;
	fullscreen = false;
}

PortalGame::~PortalGame(void)
{
}

std::shared_ptr<GameComponent> station;
//float theta = 0.0f;

bool PortalGame::Initialise()
{
	riftEnabled = false;
	// Set up the collision configuration and dispatcher
    collisionConfiguration = new btDefaultCollisionConfiguration();
    dispatcher = new btCollisionDispatcher(collisionConfiguration);

    // The world.
	btVector3 worldMin(-1000,-1000,-1000);
	btVector3 worldMax(1000,1000,1000);
	broadphase = new btAxisSweep3(worldMin,worldMax);
	solver = new btSequentialImpulseConstraintSolver();
	dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);
    dynamicsWorld->setGravity(btVector3(0,-9,0));

	width = 800;
	height = 600;

	physicsFactory = make_shared<PhysicsFactory>(dynamicsWorld);

	physicsFactory->CreateGroundPhysics();
	physicsFactory->CreateCameraPhysics();

	//std::shared_ptr<GameComponent> box = make_shared<Box>(1, 1, 1);
	//box->position = glm::vec3(0, 5, -20);
	//Attach(box);

	//non kinematic cyl
	// Stands for Box Objects
	shared_ptr<PhysicsController> colCyl_01 = physicsFactory->CreateCylinder(0.5,5, glm::vec3(5, 0, 0), glm::quat());
	//colCyl_01->tag="colObject_01";
	shared_ptr<PhysicsController> colBox_01 = physicsFactory->CreateBox(1,1,1, glm::vec3(5, 7, 0), glm::quat());
	colBox_01->tag="colObject2";

	shared_ptr<PhysicsController> colCyl_02 = physicsFactory->CreateCylinder(0.5,8, glm::vec3(12, 0, 0), glm::quat());

	shared_ptr<PhysicsController> colBox_02 = physicsFactory->CreateBox(1,1,1, glm::vec3(12, 10, 0), glm::quat());
	colBox_02->tag="colObject2";

	shared_ptr<PhysicsController> colCyl_03 = physicsFactory->CreateCylinder(0.5,10, glm::vec3(18, 0, 0), glm::quat());
	shared_ptr<PhysicsController> colBox_03 = physicsFactory->CreateBox(1,1,1, glm::vec3(18, 12, 0), glm::quat());
	colBox_03->tag="colObject2";

 	//box for collision
	shared_ptr<PhysicsController> colBox = physicsFactory->CreateBox(1,1,1, glm::vec3(5, 0, 0), glm::quat());
	/*shared_ptr<PhysicsController> colBox = physicsFactory->CreateBox(1,1,1, glm::vec3(5, 10, 0), glm::quat());
 	colBox->tag="colObject2";
+	*/

	// Ball to throw at Boxes
	shared_ptr<PhysicsController> colBall_01 = physicsFactory->CreateSphere(0.5,glm::vec3(5, 0, 10),glm::quat());
	colBall_01->tag="colObject1";

	//physicsFactory->CreateWall(glm::vec3(-20,0,20), 50, 10);

	 //Now some constraints
	/*shared_ptr<PhysicsController> box1 = physicsFactory->CreateBox(1,1,4, glm::vec3(5, 5, 0), glm::quat());
	shared_ptr<PhysicsController> box2 = physicsFactory->CreateBox(1,1,4, glm::vec3(5, 5, 5), glm::quat()); */
	//shared_ptr<PhysicsController> cap1 = physicsFactory->CreateCapsule(1,1, glm::vec3(5, 50, 5), glm::quat());
	//cap1->scale = glm::vec3(0.001,0.001,0.001);

	 //A hinge
	//btHingeConstraint * hinge = new btHingeConstraint(*box1->rigidBody, *box2->rigidBody, btVector3(0,0,2.5f),btVector3(0,0,-2.5f), btVector3(0,1,0), btVector3(0,1,0), true);
	//dynamicsWorld->addConstraint(hinge);

	//box1 = physicsFactory->CreateBox(1,1,4, glm::vec3(10, 5, 0), glm::quat());
	//box2 = physicsFactory->CreateBox(1,1,4, glm::vec3(10, 5, 5), glm::quat());
	//cap1 = physicsFactory->CreateCapsule(5,5, glm::vec3(5, 5, 5), glm::quat());

	//physicsFactory->CreateCylinder(10, 3, glm::vec3(0, 20, 0), glm::quat());

	///*std::shared_ptr<GameComponent> ship = make_shared<GameComponent>();
	//ship->ambient = glm::vec3(0.2f, 0.2, 0.2f);
	//ship->specular = glm::vec3(1.2f, 1.2f, 1.2f);
	//std::shared_ptr<Model> model = Content::LoadModel("cobramk3", glm::rotate(glm::mat4(1), 180.0f, GameComponent::basisUp));
	//std::shared_ptr<GameComponent> steerable = make_shared<Steerable3DController>(model);
	//steerable->position = glm::vec3(20, 5, -20);
	//std::shared_ptr<VectorDrawer> vectorDrawer = make_shared<VectorDrawer>();
	//vectorDrawer->scale = glm::vec3(5,5,10);
	//ship->Attach(steerable);
	//ship->Attach(model);
	//ship->Attach(vectorDrawer);
	//Attach(ship);*/

	//// Create a hierarchy
	//station = make_shared<GameComponent>();
	//station->worldMode = world_modes::from_self;
	//station->ambient = glm::vec3(0.2f, 0.2, 0.2f);
	//station->specular = glm::vec3(0,0,0);
	//station->scale = glm::vec3(2,2,2);
	//std::shared_ptr<Model> cmodel = Content::LoadModel("coriolis", glm::rotate(glm::mat4(1), 90.0f, GameComponent::basisUp));
	//station->Attach(cmodel);
	//station->Attach(make_shared<VectorDrawer>(glm::vec3(7,7,7)));
	//station->position = glm::vec3(40, 5, -20);
	//Attach(station);

	//// Add a child to the station and update by including the parent's world transform
	//std::shared_ptr<GameComponent> ship1 = make_shared<GameComponent>();
	//ship1->worldMode = world_modes::from_self_with_parent;
	//ship1->ambient = glm::vec3(0.2f, 0.2, 0.2f);
	//ship1->specular = glm::vec3(1.2f, 1.2f, 1.2f);
	//std::shared_ptr<Model> ana = Content::LoadModel("anaconda", glm::rotate(glm::mat4(1), 180.0f, GameComponent::basisUp));
	//ship1->Attach(ana);
	//ship1->position = glm::vec3(0, 0, -10);
	//station->Attach(ship1);

	//physicsFactory->CreateVehicle(glm::vec3(0,10,-30));

	// Create Inca Pyramid
	//position(), baseWidth, blockHeight, blockWidth, blockDepth
    //physicsFactory->CreateIncaPyramid(glm::vec3(20,0,-20), 6, 1.5, 1.5, 1.5);

	//Create Rag Doll
	//physicsFactory->CreateRagDoll(glm::vec3(25,0,-50));

	if (!Game::Initialise()) {
		return false;
	}

	camera->GetController()->position = glm::vec3(0,10, 0);

	return true;
}

void BGE::PortalGame::Update(float timeDelta)
{
	dynamicsWorld->stepSimulation(timeDelta,100);
	//station->Yaw(timeDelta * 20.0f);

	//collision detection check
	 int numManifolds = dynamicsWorld->getDispatcher()->getNumManifolds();
        for (int i=0;i<numManifolds;i++)
        {
                btPersistentManifold* contactManifold =  dynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i);
                btCollisionObject* obA = (btCollisionObject*)(contactManifold->getBody0());
				btCollisionObject* obB = (btCollisionObject*)(contactManifold->getBody1());
				// btCollisionObject* obA = (btCollisionObject*)(contactManifold->colCyl = physicsFactory->CreateCylinder(2,1, glm::vec3(5, 0, -10), glm::quat()); );
				//btCollisionObject* obB = (btCollisionObject*)(contactManifold->colBox = physicsFactory->CreateBox(1,1,1, glm::vec3(5, 0, 0), glm::quat()); );
                PhysicsController * pcA = reinterpret_cast<PhysicsController*>(obA->getUserPointer());
                PhysicsController * pcB = reinterpret_cast<PhysicsController*>(obB->getUserPointer());

                int numContacts = contactManifold->getNumContacts();
                if (numContacts > 0)
                {
                        if ((pcA != nullptr) && (pcB != nullptr))
                        {
							//PrintText("Collision between " + pcA->tag + " and " + pcB->tag);
							if (pcA->tag == "colObject1" && pcB->tag == "colObject2")
                            {
								  PrintText("Collision between " + pcA->tag + " and " + pcB->tag);
							}
							/*if (pcB->tag == "colObject1" && pcA->tag == "colObject2")
                            {
								  PrintText("Collision between " + pcA->tag + " and " + pcB->tag);
							}*/
                        }
                }
        }

	Game::Update(timeDelta);

}

void BGE::PortalGame::Cleanup()
{
	Game::Cleanup();
}
<commit_msg>Walls (again)<commit_after>#include "PortalGame.h"
#include "PhysicsController.h"
#include "Sphere.h"
#include "PhysicsCamera.h"
#include "Box.h"
#include "Cylinder.h"
#include "Steerable3DController.h"
#include "Ground.h"
#include "Content.h"
#include <btBulletDynamicsCommon.h>
#include <gtc/quaternion.hpp>
#include <gtx/quaternion.hpp>
#include <gtx/euler_angles.hpp>
#include <gtx/norm.hpp>
#include "VectorDrawer.h"

using namespace BGE;

PortalGame::PortalGame(void)
{
	physicsFactory = NULL;
	dynamicsWorld = NULL;
	broadphase = NULL;
	dispatcher = NULL;
	solver = NULL;
	fullscreen = false;
}

PortalGame::~PortalGame(void)
{
}

std::shared_ptr<GameComponent> station;
//float theta = 0.0f;

bool PortalGame::Initialise()
{
	riftEnabled = false;
	// Set up the collision configuration and dispatcher
    collisionConfiguration = new btDefaultCollisionConfiguration();
    dispatcher = new btCollisionDispatcher(collisionConfiguration);

    // The world.
	btVector3 worldMin(-1000,-1000,-1000);
	btVector3 worldMax(1000,1000,1000);
	broadphase = new btAxisSweep3(worldMin,worldMax);
	solver = new btSequentialImpulseConstraintSolver();
	dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);
    dynamicsWorld->setGravity(btVector3(0,-9,0));

	width = 800;
	height = 600;

	physicsFactory = make_shared<PhysicsFactory>(dynamicsWorld);

	physicsFactory->CreateGroundPhysics();
	physicsFactory->CreateCameraPhysics();

	//std::shared_ptr<GameComponent> box = make_shared<Box>(1, 1, 1);
	//box->position = glm::vec3(0, 5, -20);
	//Attach(box);

	//non kinematic cyl
	// Stands for Box Objects
	shared_ptr<PhysicsController> colCyl_01 = physicsFactory->CreateCylinder(0.5,5, glm::vec3(5, 0, 0), glm::quat());
	//colCyl_01->tag="colObject_01";
	shared_ptr<PhysicsController> colBox_01 = physicsFactory->CreateBox(1,1,1, glm::vec3(5, 7, 0), glm::quat());
	colBox_01->tag="colObject2";

	shared_ptr<PhysicsController> colCyl_02 = physicsFactory->CreateCylinder(0.5,8, glm::vec3(12, 0, 0), glm::quat());

	shared_ptr<PhysicsController> colBox_02 = physicsFactory->CreateBox(1,1,1, glm::vec3(12, 10, 0), glm::quat());
	colBox_02->tag="colObject2";

	shared_ptr<PhysicsController> colCyl_03 = physicsFactory->CreateCylinder(0.5,10, glm::vec3(18, 0, 0), glm::quat());
	shared_ptr<PhysicsController> colBox_03 = physicsFactory->CreateBox(1,1,1, glm::vec3(18, 12, 0), glm::quat());
	colBox_03->tag="colObject2";

 	//box for collision
	shared_ptr<PhysicsController> colBox = physicsFactory->CreateBox(1,1,1, glm::vec3(5, 0, 0), glm::quat());
	/*shared_ptr<PhysicsController> colBox = physicsFactory->CreateBox(1,1,1, glm::vec3(5, 10, 0), glm::quat());
 	colBox->tag="colObject2";
+	*/

	// Ball to throw at Boxes
	shared_ptr<PhysicsController> colBall_01 = physicsFactory->CreateSphere(0.5,glm::vec3(5, 0, 10),glm::quat());
	colBall_01->tag="colObject1";

	//create walls for games
	//left wall for box 1
	shared_ptr<PhysicsController> leftWall1 = physicsFactory->CreateBox(0.5,10,15, glm::vec3(-10, 0, -20), glm::quat());
	leftWall1->diffuse = glm::vec3(1,0,1);
	//leftWall1

	//right wall for box 1
	shared_ptr<PhysicsController> rightWall1 = physicsFactory->CreateBox(0.5,10,15, glm::vec3(-2, 0, -20), glm::quat());
	rightWall1->diffuse = glm::vec3(1,0,1);

	//top wall for box 1
	shared_ptr<PhysicsController> topWall1 = physicsFactory->CreateBox(15,0.5,15, glm::vec3(-4, 0, -20), glm::quat());
	topWall1->diffuse = glm::vec3(1,0,1);

	//physicsFactory->CreateWall(glm::vec3(-20,0,20), 50, 10);

	 //Now some constraints
	/*shared_ptr<PhysicsController> box1 = physicsFactory->CreateBox(1,1,4, glm::vec3(5, 5, 0), glm::quat());
	shared_ptr<PhysicsController> box2 = physicsFactory->CreateBox(1,1,4, glm::vec3(5, 5, 5), glm::quat()); */
	//shared_ptr<PhysicsController> cap1 = physicsFactory->CreateCapsule(1,1, glm::vec3(5, 50, 5), glm::quat());
	//cap1->scale = glm::vec3(0.001,0.001,0.001);

	 //A hinge
	//btHingeConstraint * hinge = new btHingeConstraint(*box1->rigidBody, *box2->rigidBody, btVector3(0,0,2.5f),btVector3(0,0,-2.5f), btVector3(0,1,0), btVector3(0,1,0), true);
	//dynamicsWorld->addConstraint(hinge);

	//box1 = physicsFactory->CreateBox(1,1,4, glm::vec3(10, 5, 0), glm::quat());
	//box2 = physicsFactory->CreateBox(1,1,4, glm::vec3(10, 5, 5), glm::quat());
	//cap1 = physicsFactory->CreateCapsule(5,5, glm::vec3(5, 5, 5), glm::quat());

	//physicsFactory->CreateCylinder(10, 3, glm::vec3(0, 20, 0), glm::quat());

	///*std::shared_ptr<GameComponent> ship = make_shared<GameComponent>();
	//ship->ambient = glm::vec3(0.2f, 0.2, 0.2f);
	//ship->specular = glm::vec3(1.2f, 1.2f, 1.2f);
	//std::shared_ptr<Model> model = Content::LoadModel("cobramk3", glm::rotate(glm::mat4(1), 180.0f, GameComponent::basisUp));
	//std::shared_ptr<GameComponent> steerable = make_shared<Steerable3DController>(model);
	//steerable->position = glm::vec3(20, 5, -20);
	//std::shared_ptr<VectorDrawer> vectorDrawer = make_shared<VectorDrawer>();
	//vectorDrawer->scale = glm::vec3(5,5,10);
	//ship->Attach(steerable);
	//ship->Attach(model);
	//ship->Attach(vectorDrawer);
	//Attach(ship);*/

	//// Create a hierarchy
	//station = make_shared<GameComponent>();
	//station->worldMode = world_modes::from_self;
	//station->ambient = glm::vec3(0.2f, 0.2, 0.2f);
	//station->specular = glm::vec3(0,0,0);
	//station->scale = glm::vec3(2,2,2);
	//std::shared_ptr<Model> cmodel = Content::LoadModel("coriolis", glm::rotate(glm::mat4(1), 90.0f, GameComponent::basisUp));
	//station->Attach(cmodel);
	//station->Attach(make_shared<VectorDrawer>(glm::vec3(7,7,7)));
	//station->position = glm::vec3(40, 5, -20);
	//Attach(station);

	//// Add a child to the station and update by including the parent's world transform
	//std::shared_ptr<GameComponent> ship1 = make_shared<GameComponent>();
	//ship1->worldMode = world_modes::from_self_with_parent;
	//ship1->ambient = glm::vec3(0.2f, 0.2, 0.2f);
	//ship1->specular = glm::vec3(1.2f, 1.2f, 1.2f);
	//std::shared_ptr<Model> ana = Content::LoadModel("anaconda", glm::rotate(glm::mat4(1), 180.0f, GameComponent::basisUp));
	//ship1->Attach(ana);
	//ship1->position = glm::vec3(0, 0, -10);
	//station->Attach(ship1);

	//physicsFactory->CreateVehicle(glm::vec3(0,10,-30));

	// Create Inca Pyramid
	//position(), baseWidth, blockHeight, blockWidth, blockDepth
    //physicsFactory->CreateIncaPyramid(glm::vec3(20,0,-20), 6, 1.5, 1.5, 1.5);

	//Create Rag Doll
	//physicsFactory->CreateRagDoll(glm::vec3(25,0,-50));

	if (!Game::Initialise()) {
		return false;
	}

	camera->GetController()->position = glm::vec3(0,10, 0);

	return true;
}

void BGE::PortalGame::Update(float timeDelta)
{
	dynamicsWorld->stepSimulation(timeDelta,100);
	//station->Yaw(timeDelta * 20.0f);

	//collision detection check
	 int numManifolds = dynamicsWorld->getDispatcher()->getNumManifolds();
        for (int i=0;i<numManifolds;i++)
        {
                btPersistentManifold* contactManifold =  dynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i);
                btCollisionObject* obA = (btCollisionObject*)(contactManifold->getBody0());
				btCollisionObject* obB = (btCollisionObject*)(contactManifold->getBody1());
				// btCollisionObject* obA = (btCollisionObject*)(contactManifold->colCyl = physicsFactory->CreateCylinder(2,1, glm::vec3(5, 0, -10), glm::quat()); );
				//btCollisionObject* obB = (btCollisionObject*)(contactManifold->colBox = physicsFactory->CreateBox(1,1,1, glm::vec3(5, 0, 0), glm::quat()); );
                PhysicsController * pcA = reinterpret_cast<PhysicsController*>(obA->getUserPointer());
                PhysicsController * pcB = reinterpret_cast<PhysicsController*>(obB->getUserPointer());

                int numContacts = contactManifold->getNumContacts();
                if (numContacts > 0)
                {
                        if ((pcA != nullptr) && (pcB != nullptr))
                        {
							//PrintText("Collision between " + pcA->tag + " and " + pcB->tag);
							if (pcA->tag == "colObject1" && pcB->tag == "colObject2")
                            {
								  PrintText("Collision between " + pcA->tag + " and " + pcB->tag);
							}
							/*if (pcB->tag == "colObject1" && pcA->tag == "colObject2")
                            {
								  PrintText("Collision between " + pcA->tag + " and " + pcB->tag);
							}*/
                        }
                }
        }

	Game::Update(timeDelta);

}

void BGE::PortalGame::Cleanup()
{
	Game::Cleanup();
}
<|endoftext|>


<commit_before>/*
 *	filter≈
 *	External object for Max/Lydbaer
 *	Copyright © 2008 by Timothy Place
 *
 *	License: This code is licensed under the terms of the GNU LGPL
 *	http://www.gnu.org/licenses/lgpl.html
 */

#include "maxMulticore.h"
#define thisTTClass TTFilter

// For the filter≈ object, we wish to create our own class,
// which then encapsulates the various filters available in TTBlue.

class TTFilter : public TTAudioObject {
protected:
	TTAudioObjectPtr	actualFilterObject;		///< The actual filter object that this object is currently wrapping
	TTFloat64			frequency;				///< The center or cutoff frequency of the filter
	TTFloat64			q;						///< The width of the filter
	TTSymbolPtr			type;					///< The name of the current filter type

public:

	// Constructor
	TTFilter(TTUInt16 newMaxNumChannels)
		: TTAudioObject("filter", newMaxNumChannels), actualFilterObject(NULL)
	{
		registerAttributeWithSetter(frequency, kTypeFloat64);
		registerAttributeWithSetter(q, kTypeFloat64);
		registerAttributeWithSetter(type, kTypeSymbol);

		registerMessageWithArgument(getTypes);
		registerMessageSimple(clear);

		registerMessageWithArgument(updateMaxNumChannels);
		registerMessageSimple(updateSr);

		setAttributeValue(TT("maxNumChannels"), newMaxNumChannels);
		setAttributeValue(TT("type"), TT("lowpass.1"));
		setAttributeValue(TT("frequency"), 1000.0);
		setAttributeValue(TT("q"), 1.0);
		setProcessMethod(processAudio);
	}

	// Destructor
	virtual ~TTFilter()
	{
		;
	}

	TTErr setfrequency(const TTValue& newValue)
	{
		frequency = newValue;
		return actualFilterObject->setAttributeValue(TT("frequency"), frequency);
	}

	TTErr setq(const TTValue& newValue)
	{
		q = newValue;
		return actualFilterObject->setAttributeValue(TT("q"), q);
	}

	TTErr settype(const TTValue& newValue)
	{
		TTSymbolPtr newType = newValue;
		TTErr		err = kTTErrNone;

		// if the type didn't change, then don't change the filter
		if(newType == type)
			return kTTErrNone;

		type = newType;
		err = TTObjectInstantiate(type, &actualFilterObject, maxNumChannels);
		if(!err){
			// Now that we have our new filter, update it with the current state of the wrapper:
			actualFilterObject->setAttributeValue(TT("frequency"), frequency);
			err = actualFilterObject->setAttributeValue(TT("q"), q);
			if(err == kTTErrInvalidAttribute)
				err = actualFilterObject->setAttributeValue(TT("resonance"), q);
			actualFilterObject->setAttributeValue(TT("bypass"), this->attrBypass);
			actualFilterObject->setAttributeValue(TT("sr"), sr);
		}
		return err;
	}

	TTErr getTypes(TTValue& listOfFilterTypesToReturn)
	{
		return TTGetRegisteredClassNamesForTags(listOfFilterTypesToReturn, TT("filter"));
	}

	TTErr clear()
	{
		return actualFilterObject->sendMessage(TT("clear"));
	}

	TTErr updateMaxNumChannels(const TTValue& oldMaxNumChannels)
	{
		if(actualFilterObject)
			return actualFilterObject->setAttributeValue(kTTSym_maxNumChannels, maxNumChannels);
		else
			return kTTErrNone;
	}

	TTErr updateSr()
	{
		return actualFilterObject->setAttributeValue(kTTSym_sr, sr);
	}

	TTErr processAudio(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
	{
		return actualFilterObject->process(inputs, outputs);
	}

};

// Because we have created this overdriveExtended class outside of the main TTBlue framework,
// we have to define our own factory method that is used to create a new instance of our object.

TTObjectPtr instantiateTTFilter(TTSymbolPtr className, TTValue& arguments)
{
	return new TTFilter(arguments);
}

int main(void)
{
	TTMulticoreInit();

	// First, we have to register our custom subclass with the TTBlue framework.
	TTClassRegister(TT("filter"), "audio, processor, effect, lydbaer", &instantiateTTFilter);
	// Then we are able to wrap it as a Max class.
	return wrapAsMaxbaer(TT("filter"), "filter≈", NULL);
}

<commit_msg>filter≈ object is now compiling properly<commit_after>/*
 *	filter≈
 *	External object for Max/Lydbaer
 *	Copyright © 2008 by Timothy Place
 *
 *	License: This code is licensed under the terms of the GNU LGPL
 *	http://www.gnu.org/licenses/lgpl.html
 */

#include "maxMulticore.h"

#define thisTTClass			TTFilter
#define thisTTClassName		"filter"
#define thisTTClassTags		"audio, processor, filter, multicore"

// For the filter≈ object, we wish to create our own class,
// which then encapsulates the various filters available in TTBlue.

TTAUDIOCLASS(TTFilter)

protected:
	TTAudioObjectPtr	actualFilterObject;		///< The actual filter object that this object is currently wrapping
	TTFloat64			frequency;				///< The center or cutoff frequency of the filter
	TTFloat64			q;						///< The width of the filter
	TTSymbolPtr			type;					///< The name of the current filter type

public:

	TTErr setfrequency(const TTValue& newValue)
	{
		frequency = newValue;
		return actualFilterObject->setAttributeValue(TT("frequency"), frequency);
	}

	TTErr setq(const TTValue& newValue)
	{
		q = newValue;
		return actualFilterObject->setAttributeValue(TT("q"), q);
	}

	TTErr settype(const TTValue& newValue)
	{
		TTSymbolPtr newType = newValue;
		TTErr		err = kTTErrNone;

		// if the type didn't change, then don't change the filter
		if(newType == type)
			return kTTErrNone;

		type = newType;
		err = TTObjectInstantiate(type, &actualFilterObject, maxNumChannels);
		if(!err){
			// Now that we have our new filter, update it with the current state of the wrapper:
			actualFilterObject->setAttributeValue(TT("frequency"), frequency);
			err = actualFilterObject->setAttributeValue(TT("q"), q);
			if(err == kTTErrInvalidAttribute)
				err = actualFilterObject->setAttributeValue(TT("resonance"), q);
			actualFilterObject->setAttributeValue(TT("bypass"), this->attrBypass);
			actualFilterObject->setAttributeValue(TT("sr"), sr);
		}
		return err;
	}

	TTErr getTypes(TTValue& listOfFilterTypesToReturn)
	{
		return TTGetRegisteredClassNamesForTags(listOfFilterTypesToReturn, TT("filter"));
	}

	TTErr clear()
	{
		return actualFilterObject->sendMessage(TT("clear"));
	}

	TTErr updateMaxNumChannels(const TTValue& oldMaxNumChannels)
	{
		if(actualFilterObject)
			return actualFilterObject->setAttributeValue(kTTSym_maxNumChannels, maxNumChannels);
		else
			return kTTErrNone;
	}

	TTErr updateSr()
	{
		return actualFilterObject->setAttributeValue(kTTSym_sr, sr);
	}

	TTErr processAudio(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
	{
		return actualFilterObject->process(inputs, outputs);
	}

};

TT_AUDIO_CONSTRUCTOR_EXPORT,
	actualFilterObject(NULL)
{
	registerAttributeWithSetter(frequency, kTypeFloat64);
	registerAttributeWithSetter(q, kTypeFloat64);
	registerAttributeWithSetter(type, kTypeSymbol);

	registerMessageWithArgument(getTypes);
	registerMessageSimple(clear);

	registerMessageWithArgument(updateMaxNumChannels);
	registerMessageSimple(updateSr);

	setAttributeValue(TT("maxNumChannels"), arguments);
	setAttributeValue(TT("type"), TT("lowpass.1"));
	setAttributeValue(TT("frequency"), 1000.0);
	setAttributeValue(TT("q"), 1.0);
	setProcessMethod(processAudio);
}

// Destructor
TTFilter::~TTFilter()
{
	;
}

/*******************************************************************************/

int main(void)
{
	TTMulticoreInit();

	// First, we have to register our custom subclass with the Jamoma Foundation runtime.
	TTFilter::registerClass();

	// Then we are able to wrap it as a Max class.
	return wrapAsMaxbaer(TT("filter"), "filter≈", NULL);
}
<|endoftext|>


<commit_before>/*
 *  Copyright 2019-2020 Diligent Graphics LLC
 *  Copyright 2015-2019 Egor Yusov
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *  In no event and under no legal theory, whether in tort (including negligence),
 *  contract, or otherwise, unless required by applicable law (such as deliberate
 *  and grossly negligent acts) or agreed to in writing, shall any Contributor be
 *  liable for any damages, including any direct, indirect, special, incidental,
 *  or consequential damages of any character arising as a result of this License or
 *  out of the use or inability to use the software (including but not limited to damages
 *  for loss of goodwill, work stoppage, computer failure or malfunction, or any and
 *  all other commercial damages or losses), even if such Contributor has been advised
 *  of the possibility of such damages.
 */

#include "pch.h"

#include "FBOCache.hpp"
#include "RenderDeviceGLImpl.hpp"
#include "TextureBaseGL.hpp"
#include "GLContextState.hpp"

namespace Diligent
{

bool FBOCache::FBOCacheKey::operator==(const FBOCacheKey& Key) const
{
    if (Hash != 0 && Key.Hash != 0 && Hash != Key.Hash)
        return false;

    if (NumRenderTargets != Key.NumRenderTargets)
        return false;
    for (Uint32 rt = 0; rt < NumRenderTargets; ++rt)
    {
        if (RTIds[rt] != Key.RTIds[rt])
            return false;
        if (RTIds[rt])
        {
            if (!(RTVDescs[rt] == Key.RTVDescs[rt]))
                return false;
        }
    }
    if (DSId != Key.DSId)
        return false;
    if (DSId)
    {
        if (!(DSVDesc == Key.DSVDesc))
            return false;
    }
    return true;
}

std::size_t FBOCache::FBOCacheKeyHashFunc::operator()(const FBOCacheKey& Key) const
{
    if (Key.Hash == 0)
    {
        std::hash<TextureViewDesc> TexViewDescHasher;
        Key.Hash = 0;
        HashCombine(Key.Hash, Key.NumRenderTargets);
        for (Uint32 rt = 0; rt < Key.NumRenderTargets; ++rt)
        {
            HashCombine(Key.Hash, Key.RTIds[rt]);
            if (Key.RTIds[rt])
                HashCombine(Key.Hash, TexViewDescHasher(Key.RTVDescs[rt]));
        }
        HashCombine(Key.Hash, Key.DSId);
        if (Key.DSId)
            HashCombine(Key.Hash, TexViewDescHasher(Key.DSVDesc));
    }
    return Key.Hash;
}

FBOCache::FBOCache()
{
    m_Cache.max_load_factor(0.5f);
    m_TexIdToKey.max_load_factor(0.5f);
}

FBOCache::~FBOCache()
{
    VERIFY(m_Cache.empty(), "FBO cache is not empty. Are there any unreleased objects?");
    VERIFY(m_TexIdToKey.empty(), "TexIdToKey cache is not empty.");
}

void FBOCache::OnReleaseTexture(ITexture* pTexture)
{
    ThreadingTools::LockHelper CacheLock(m_CacheLockFlag);

    auto* pTexGL = ValidatedCast<TextureBaseGL>(pTexture);
    // Find all FBOs that this texture used in
    auto EqualRange = m_TexIdToKey.equal_range(pTexGL->GetUniqueID());
    for (auto It = EqualRange.first; It != EqualRange.second; ++It)
    {
        m_Cache.erase(It->second);
    }
    m_TexIdToKey.erase(EqualRange.first, EqualRange.second);
}

const GLObjectWrappers::GLFrameBufferObj& FBOCache::GetFBO(Uint32             NumRenderTargets,
                                                           TextureViewGLImpl* ppRTVs[],
                                                           TextureViewGLImpl* pDSV,
                                                           GLContextState&    ContextState)
{
    // Pop null render targets from the end of the list
    while (NumRenderTargets > 0 && ppRTVs[NumRenderTargets - 1] == nullptr)
        --NumRenderTargets;

    VERIFY(NumRenderTargets != 0 || pDSV != nullptr, "At least one render target or a depth-stencil buffer must be provided");

    // Lock the cache
    ThreadingTools::LockHelper CacheLock(m_CacheLockFlag);

    // Construct the key
    FBOCacheKey Key;
    VERIFY(NumRenderTargets < MAX_RENDER_TARGETS, "Too many render targets are being set");
    NumRenderTargets     = std::min(NumRenderTargets, MAX_RENDER_TARGETS);
    Key.NumRenderTargets = NumRenderTargets;
    for (Uint32 rt = 0; rt < NumRenderTargets; ++rt)
    {
        auto* pRTView = ppRTVs[rt];
        if (pRTView == nullptr)
            continue;

        auto* pColorTexGL = pRTView->GetTexture<TextureBaseGL>();
        pColorTexGL->TextureMemoryBarrier(
            GL_FRAMEBUFFER_BARRIER_BIT, // Reads and writes via framebuffer object attachments after the
                                        // barrier will reflect data written by shaders prior to the barrier.
                                        // Additionally, framebuffer writes issued after the barrier will wait
                                        // on the completion of all shader writes issued prior to the barrier.
            ContextState);

        Key.RTIds[rt]    = pColorTexGL->GetUniqueID();
        Key.RTVDescs[rt] = pRTView->GetDesc();
    }

    if (pDSV)
    {
        auto* pDepthTexGL = pDSV->GetTexture<TextureBaseGL>();
        pDepthTexGL->TextureMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT, ContextState);
        Key.DSId    = pDepthTexGL->GetUniqueID();
        Key.DSVDesc = pDSV->GetDesc();
    }

    // Try to find FBO in the map
    auto It = m_Cache.find(Key);
    if (It != m_Cache.end())
    {
        return It->second;
    }
    else
    {
        // Create a new FBO
        GLObjectWrappers::GLFrameBufferObj NewFBO(true);

        ContextState.BindFBO(NewFBO);

        // Initialize the FBO
        for (Uint32 rt = 0; rt < NumRenderTargets; ++rt)
        {
            if (auto* pRTView = ppRTVs[rt])
            {
                const auto& RTVDesc     = pRTView->GetDesc();
                auto*       pColorTexGL = pRTView->GetTexture<TextureBaseGL>();
                pColorTexGL->AttachToFramebuffer(RTVDesc, GL_COLOR_ATTACHMENT0 + rt);
            }
        }

        if (pDSV != nullptr)
        {
            const auto& DSVDesc         = pDSV->GetDesc();
            auto*       pDepthTexGL     = pDSV->GetTexture<TextureBaseGL>();
            GLenum      AttachmentPoint = 0;
            if (DSVDesc.Format == TEX_FORMAT_D32_FLOAT ||
                DSVDesc.Format == TEX_FORMAT_D16_UNORM)
            {
#ifdef DILIGENT_DEBUG
                {
                    const auto GLTexFmt = pDepthTexGL->GetGLTexFormat();
                    VERIFY(GLTexFmt == GL_DEPTH_COMPONENT32F || GLTexFmt == GL_DEPTH_COMPONENT16,
                           "Inappropriate internal texture format (", GLTexFmt,
                           ") for depth attachment. GL_DEPTH_COMPONENT32F or GL_DEPTH_COMPONENT16 is expected");
                }
#endif
                AttachmentPoint = GL_DEPTH_ATTACHMENT;
            }
            else if (DSVDesc.Format == TEX_FORMAT_D32_FLOAT_S8X24_UINT ||
                     DSVDesc.Format == TEX_FORMAT_D24_UNORM_S8_UINT)
            {
#ifdef DILIGENT_DEBUG
                {
                    const auto GLTexFmt = pDepthTexGL->GetGLTexFormat();
                    VERIFY(GLTexFmt == GL_DEPTH24_STENCIL8 || GLTexFmt == GL_DEPTH32F_STENCIL8,
                           "Inappropriate internal texture format (", GLTexFmt,
                           ") for depth-stencil attachment. GL_DEPTH24_STENCIL8 or GL_DEPTH32F_STENCIL8 is expected");
                }
#endif
                AttachmentPoint = GL_DEPTH_STENCIL_ATTACHMENT;
            }
            else
            {
                UNEXPECTED(GetTextureFormatAttribs(DSVDesc.Format).Name, " is not valid depth-stencil view format");
            }
            pDepthTexGL->AttachToFramebuffer(DSVDesc, AttachmentPoint);
        }

        // We now need to set mapping between shader outputs and
        // color attachments. This largely redundant step is performed
        // by glDrawBuffers()
        // clang-format off
        static const GLenum DrawBuffers[] =
        {
            GL_COLOR_ATTACHMENT0,
            GL_COLOR_ATTACHMENT1,
            GL_COLOR_ATTACHMENT2,
            GL_COLOR_ATTACHMENT3,
            GL_COLOR_ATTACHMENT4,
            GL_COLOR_ATTACHMENT5,
            GL_COLOR_ATTACHMENT6,
            GL_COLOR_ATTACHMENT7,
            GL_COLOR_ATTACHMENT8,
            GL_COLOR_ATTACHMENT9,
            GL_COLOR_ATTACHMENT10,
            GL_COLOR_ATTACHMENT11,
            GL_COLOR_ATTACHMENT12,
            GL_COLOR_ATTACHMENT13,
            GL_COLOR_ATTACHMENT14,
            GL_COLOR_ATTACHMENT15
        };
        // clang-format on

        // The state set by glDrawBuffers() is part of the state of the framebuffer.
        // So it can be set up once and left it set.
        glDrawBuffers(NumRenderTargets, DrawBuffers);
        CHECK_GL_ERROR("Failed to set draw buffers via glDrawBuffers()");

        GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
        if (Status != GL_FRAMEBUFFER_COMPLETE)
        {
            const Char* StatusString = "Unknown";
            switch (Status)
            {
                // clang-format off
                case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:         StatusString = "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";         break;
                case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: StatusString = "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; break;
                case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:        StatusString = "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER";        break;
                case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:        StatusString = "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER";        break;
                case GL_FRAMEBUFFER_UNSUPPORTED:                   StatusString = "GL_FRAMEBUFFER_UNSUPPORTED";                   break;
                case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:        StatusString = "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE";        break;
                case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:      StatusString = "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS";      break;
                    // clang-format on
            }
            LOG_ERROR("Framebuffer is incomplete. FB status: ", StatusString);
            UNEXPECTED("Framebuffer is incomplete");
        }

        auto NewElems = m_Cache.emplace(std::make_pair(Key, std::move(NewFBO)));
        // New element must be actually inserted
        VERIFY(NewElems.second, "New element was not inserted");
        if (Key.DSId != 0)
            m_TexIdToKey.insert(std::make_pair(Key.DSId, Key));
        for (Uint32 rt = 0; rt < NumRenderTargets; ++rt)
        {
            if (Key.RTIds[rt] != 0)
                m_TexIdToKey.insert(std::make_pair(Key.RTIds[rt], Key));
        }

        return NewElems.first->second;
    }
}

} // namespace Diligent
<commit_msg>The 'Key.Hash' variable was assigned the same value. ``` if (Key.Hash == 0){ Key.Hash = 0; } ```<commit_after>/*
 *  Copyright 2019-2020 Diligent Graphics LLC
 *  Copyright 2015-2019 Egor Yusov
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *  In no event and under no legal theory, whether in tort (including negligence),
 *  contract, or otherwise, unless required by applicable law (such as deliberate
 *  and grossly negligent acts) or agreed to in writing, shall any Contributor be
 *  liable for any damages, including any direct, indirect, special, incidental,
 *  or consequential damages of any character arising as a result of this License or
 *  out of the use or inability to use the software (including but not limited to damages
 *  for loss of goodwill, work stoppage, computer failure or malfunction, or any and
 *  all other commercial damages or losses), even if such Contributor has been advised
 *  of the possibility of such damages.
 */

#include "pch.h"

#include "FBOCache.hpp"
#include "RenderDeviceGLImpl.hpp"
#include "TextureBaseGL.hpp"
#include "GLContextState.hpp"

namespace Diligent
{

bool FBOCache::FBOCacheKey::operator==(const FBOCacheKey& Key) const
{
    if (Hash != 0 && Key.Hash != 0 && Hash != Key.Hash)
        return false;

    if (NumRenderTargets != Key.NumRenderTargets)
        return false;
    for (Uint32 rt = 0; rt < NumRenderTargets; ++rt)
    {
        if (RTIds[rt] != Key.RTIds[rt])
            return false;
        if (RTIds[rt])
        {
            if (!(RTVDescs[rt] == Key.RTVDescs[rt]))
                return false;
        }
    }
    if (DSId != Key.DSId)
        return false;
    if (DSId)
    {
        if (!(DSVDesc == Key.DSVDesc))
            return false;
    }
    return true;
}

std::size_t FBOCache::FBOCacheKeyHashFunc::operator()(const FBOCacheKey& Key) const
{
    if (Key.Hash == 0)
    {
        std::hash<TextureViewDesc> TexViewDescHasher;
        HashCombine(Key.Hash, Key.NumRenderTargets);
        for (Uint32 rt = 0; rt < Key.NumRenderTargets; ++rt)
        {
            HashCombine(Key.Hash, Key.RTIds[rt]);
            if (Key.RTIds[rt])
                HashCombine(Key.Hash, TexViewDescHasher(Key.RTVDescs[rt]));
        }
        HashCombine(Key.Hash, Key.DSId);
        if (Key.DSId)
            HashCombine(Key.Hash, TexViewDescHasher(Key.DSVDesc));
    }
    return Key.Hash;
}

FBOCache::FBOCache()
{
    m_Cache.max_load_factor(0.5f);
    m_TexIdToKey.max_load_factor(0.5f);
}

FBOCache::~FBOCache()
{
    VERIFY(m_Cache.empty(), "FBO cache is not empty. Are there any unreleased objects?");
    VERIFY(m_TexIdToKey.empty(), "TexIdToKey cache is not empty.");
}

void FBOCache::OnReleaseTexture(ITexture* pTexture)
{
    ThreadingTools::LockHelper CacheLock(m_CacheLockFlag);

    auto* pTexGL = ValidatedCast<TextureBaseGL>(pTexture);
    // Find all FBOs that this texture used in
    auto EqualRange = m_TexIdToKey.equal_range(pTexGL->GetUniqueID());
    for (auto It = EqualRange.first; It != EqualRange.second; ++It)
    {
        m_Cache.erase(It->second);
    }
    m_TexIdToKey.erase(EqualRange.first, EqualRange.second);
}

const GLObjectWrappers::GLFrameBufferObj& FBOCache::GetFBO(Uint32             NumRenderTargets,
                                                           TextureViewGLImpl* ppRTVs[],
                                                           TextureViewGLImpl* pDSV,
                                                           GLContextState&    ContextState)
{
    // Pop null render targets from the end of the list
    while (NumRenderTargets > 0 && ppRTVs[NumRenderTargets - 1] == nullptr)
        --NumRenderTargets;

    VERIFY(NumRenderTargets != 0 || pDSV != nullptr, "At least one render target or a depth-stencil buffer must be provided");

    // Lock the cache
    ThreadingTools::LockHelper CacheLock(m_CacheLockFlag);

    // Construct the key
    FBOCacheKey Key;
    VERIFY(NumRenderTargets < MAX_RENDER_TARGETS, "Too many render targets are being set");
    NumRenderTargets     = std::min(NumRenderTargets, MAX_RENDER_TARGETS);
    Key.NumRenderTargets = NumRenderTargets;
    for (Uint32 rt = 0; rt < NumRenderTargets; ++rt)
    {
        auto* pRTView = ppRTVs[rt];
        if (pRTView == nullptr)
            continue;

        auto* pColorTexGL = pRTView->GetTexture<TextureBaseGL>();
        pColorTexGL->TextureMemoryBarrier(
            GL_FRAMEBUFFER_BARRIER_BIT, // Reads and writes via framebuffer object attachments after the
                                        // barrier will reflect data written by shaders prior to the barrier.
                                        // Additionally, framebuffer writes issued after the barrier will wait
                                        // on the completion of all shader writes issued prior to the barrier.
            ContextState);

        Key.RTIds[rt]    = pColorTexGL->GetUniqueID();
        Key.RTVDescs[rt] = pRTView->GetDesc();
    }

    if (pDSV)
    {
        auto* pDepthTexGL = pDSV->GetTexture<TextureBaseGL>();
        pDepthTexGL->TextureMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT, ContextState);
        Key.DSId    = pDepthTexGL->GetUniqueID();
        Key.DSVDesc = pDSV->GetDesc();
    }

    // Try to find FBO in the map
    auto It = m_Cache.find(Key);
    if (It != m_Cache.end())
    {
        return It->second;
    }
    else
    {
        // Create a new FBO
        GLObjectWrappers::GLFrameBufferObj NewFBO(true);

        ContextState.BindFBO(NewFBO);

        // Initialize the FBO
        for (Uint32 rt = 0; rt < NumRenderTargets; ++rt)
        {
            if (auto* pRTView = ppRTVs[rt])
            {
                const auto& RTVDesc     = pRTView->GetDesc();
                auto*       pColorTexGL = pRTView->GetTexture<TextureBaseGL>();
                pColorTexGL->AttachToFramebuffer(RTVDesc, GL_COLOR_ATTACHMENT0 + rt);
            }
        }

        if (pDSV != nullptr)
        {
            const auto& DSVDesc         = pDSV->GetDesc();
            auto*       pDepthTexGL     = pDSV->GetTexture<TextureBaseGL>();
            GLenum      AttachmentPoint = 0;
            if (DSVDesc.Format == TEX_FORMAT_D32_FLOAT ||
                DSVDesc.Format == TEX_FORMAT_D16_UNORM)
            {
#ifdef DILIGENT_DEBUG
                {
                    const auto GLTexFmt = pDepthTexGL->GetGLTexFormat();
                    VERIFY(GLTexFmt == GL_DEPTH_COMPONENT32F || GLTexFmt == GL_DEPTH_COMPONENT16,
                           "Inappropriate internal texture format (", GLTexFmt,
                           ") for depth attachment. GL_DEPTH_COMPONENT32F or GL_DEPTH_COMPONENT16 is expected");
                }
#endif
                AttachmentPoint = GL_DEPTH_ATTACHMENT;
            }
            else if (DSVDesc.Format == TEX_FORMAT_D32_FLOAT_S8X24_UINT ||
                     DSVDesc.Format == TEX_FORMAT_D24_UNORM_S8_UINT)
            {
#ifdef DILIGENT_DEBUG
                {
                    const auto GLTexFmt = pDepthTexGL->GetGLTexFormat();
                    VERIFY(GLTexFmt == GL_DEPTH24_STENCIL8 || GLTexFmt == GL_DEPTH32F_STENCIL8,
                           "Inappropriate internal texture format (", GLTexFmt,
                           ") for depth-stencil attachment. GL_DEPTH24_STENCIL8 or GL_DEPTH32F_STENCIL8 is expected");
                }
#endif
                AttachmentPoint = GL_DEPTH_STENCIL_ATTACHMENT;
            }
            else
            {
                UNEXPECTED(GetTextureFormatAttribs(DSVDesc.Format).Name, " is not valid depth-stencil view format");
            }
            pDepthTexGL->AttachToFramebuffer(DSVDesc, AttachmentPoint);
        }

        // We now need to set mapping between shader outputs and
        // color attachments. This largely redundant step is performed
        // by glDrawBuffers()
        // clang-format off
        static const GLenum DrawBuffers[] =
        {
            GL_COLOR_ATTACHMENT0,
            GL_COLOR_ATTACHMENT1,
            GL_COLOR_ATTACHMENT2,
            GL_COLOR_ATTACHMENT3,
            GL_COLOR_ATTACHMENT4,
            GL_COLOR_ATTACHMENT5,
            GL_COLOR_ATTACHMENT6,
            GL_COLOR_ATTACHMENT7,
            GL_COLOR_ATTACHMENT8,
            GL_COLOR_ATTACHMENT9,
            GL_COLOR_ATTACHMENT10,
            GL_COLOR_ATTACHMENT11,
            GL_COLOR_ATTACHMENT12,
            GL_COLOR_ATTACHMENT13,
            GL_COLOR_ATTACHMENT14,
            GL_COLOR_ATTACHMENT15
        };
        // clang-format on

        // The state set by glDrawBuffers() is part of the state of the framebuffer.
        // So it can be set up once and left it set.
        glDrawBuffers(NumRenderTargets, DrawBuffers);
        CHECK_GL_ERROR("Failed to set draw buffers via glDrawBuffers()");

        GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
        if (Status != GL_FRAMEBUFFER_COMPLETE)
        {
            const Char* StatusString = "Unknown";
            switch (Status)
            {
                // clang-format off
                case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:         StatusString = "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";         break;
                case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: StatusString = "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; break;
                case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:        StatusString = "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER";        break;
                case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:        StatusString = "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER";        break;
                case GL_FRAMEBUFFER_UNSUPPORTED:                   StatusString = "GL_FRAMEBUFFER_UNSUPPORTED";                   break;
                case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:        StatusString = "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE";        break;
                case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:      StatusString = "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS";      break;
                    // clang-format on
            }
            LOG_ERROR("Framebuffer is incomplete. FB status: ", StatusString);
            UNEXPECTED("Framebuffer is incomplete");
        }

        auto NewElems = m_Cache.emplace(std::make_pair(Key, std::move(NewFBO)));
        // New element must be actually inserted
        VERIFY(NewElems.second, "New element was not inserted");
        if (Key.DSId != 0)
            m_TexIdToKey.insert(std::make_pair(Key.DSId, Key));
        for (Uint32 rt = 0; rt < NumRenderTargets; ++rt)
        {
            if (Key.RTIds[rt] != 0)
                m_TexIdToKey.insert(std::make_pair(Key.RTIds[rt], Key));
        }

        return NewElems.first->second;
    }
}

} // namespace Diligent
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright NumFOCUS
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include <iostream>
#include "itkObject.h"

#include "itkCommand.h"
#include "itkTestingMacros.h"

//
// This test is for testing the Command Observer functionality of the
// itk::Object class.
//

namespace
{

unsigned int onAnyCount = 0;

void
onAny(itk::Object *, const itk::EventObject &, void *)
{
  ++onAnyCount;
}

void
onAnyInvokeUser(itk::Object * o, const itk::EventObject &, void *)
{
  static bool invoke = true;
  if (invoke)
  {
    invoke = false;
    o->InvokeEvent(itk::UserEvent());
    invoke = true;
  }
}

void
onAnyConst(const itk::Object *, const itk::EventObject &, void *)
{
  ++onAnyCount;
}

void
onAnyThrow(itk::Object *, const itk::EventObject &, void *)
{
  throw;
}

void
onUserRemove(itk::Object * o, const itk::EventObject &, void * data)
{
  unsigned long idToRemove = *static_cast<unsigned long *>(data);
  o->RemoveObserver(idToRemove);
}

int
testDeleteObserverDuringEvent()
{
  itk::Object::Pointer o = itk::Object::New();

  unsigned long idToRemove;

  itk::CStyleCommand::Pointer removeCmd = itk::CStyleCommand::New();
  removeCmd->SetCallback(onUserRemove);
  removeCmd->SetObjectName("Remove Command");

  itk::CStyleCommand::Pointer cmd = itk::CStyleCommand::New();
  cmd->SetCallback(onAny);
  cmd->SetObjectName("Any Command 1");

  // Add Order 1
  o->AddObserver(itk::UserEvent(), removeCmd);
  idToRemove = o->AddObserver(itk::AnyEvent(), cmd);
  o->AddObserver(itk::AnyEvent(), cmd);
  removeCmd->SetClientData(&idToRemove);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 2);

  onAnyCount = 0;
  o->InvokeEvent(itk::UserEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 1);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 1);

  o->RemoveAllObservers();

  // Add Order 2
  idToRemove = o->AddObserver(itk::AnyEvent(), cmd);
  o->AddObserver(itk::UserEvent(), removeCmd);
  o->AddObserver(itk::AnyEvent(), cmd);
  removeCmd->SetClientData(&idToRemove);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 2);

  onAnyCount = 0;
  o->InvokeEvent(itk::UserEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 2);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 1);

  o->RemoveAllObservers();

  // Add Order 3
  idToRemove = o->AddObserver(itk::AnyEvent(), cmd);
  o->AddObserver(itk::AnyEvent(), cmd);
  o->AddObserver(itk::UserEvent(), removeCmd);
  removeCmd->SetClientData(&idToRemove);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 2);

  onAnyCount = 0;
  o->InvokeEvent(itk::UserEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 2);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 1);

  o->RemoveAllObservers();

  // Add Order 4
  o->AddObserver(itk::AnyEvent(), cmd);
  o->AddObserver(itk::UserEvent(), removeCmd);
  idToRemove = o->AddObserver(itk::AnyEvent(), cmd);
  removeCmd->SetClientData(&idToRemove);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 2);

  onAnyCount = 0;
  o->InvokeEvent(itk::UserEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 1);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 1);

  o->RemoveAllObservers();

  return EXIT_SUCCESS;
}

int
testCommandConstObject()
{

  itk::Object::Pointer      o = itk::Object::New();
  itk::Object::ConstPointer co = o;

  itk::CStyleCommand::Pointer cmd = itk::CStyleCommand::New();
  cmd->SetConstCallback(onAnyConst);
  cmd->SetObjectName("Any Command 1");

  itk::CStyleCommand::Pointer removeCmd = itk::CStyleCommand::New();
  removeCmd->SetCallback(onUserRemove);
  removeCmd->SetObjectName("Remove Command");

  co->AddObserver(itk::AnyEvent(), cmd);
  ITK_TEST_EXPECT_TRUE(co->HasObserver(itk::AnyEvent()));

  // the constant command doesn't get executed from the non-const
  // invocation
  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 0);

  onAnyCount = 0;
  co->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 1);

  return EXIT_SUCCESS;
}

int
testCommandRecursiveObject()
{
  // this test has an command invoking another event, while removing a
  // a Command.
  // This is a super-mean test that is not likely to really be used.

  itk::Object::Pointer      o = itk::Object::New();
  itk::Object::ConstPointer co = o;

  unsigned long idToRemove;

  itk::CStyleCommand::Pointer cmd = itk::CStyleCommand::New();
  cmd->SetCallback(onAny);
  cmd->SetObjectName("Any Command 1");

  itk::CStyleCommand::Pointer removeCmd = itk::CStyleCommand::New();
  removeCmd->SetCallback(onUserRemove);
  removeCmd->SetObjectName("Remove Command");

  itk::CStyleCommand::Pointer cmdInvoke = itk::CStyleCommand::New();
  cmdInvoke->SetCallback(onAnyInvokeUser);
  cmdInvoke->SetObjectName("Any Invoke User");

  // On 1 Remove 1
  idToRemove = o->AddObserver(itk::AnyEvent(), cmdInvoke);
  o->AddObserver(itk::UserEvent(), removeCmd);
  o->AddObserver(itk::AnyEvent(), cmd);
  removeCmd->SetClientData(&idToRemove);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 2);

  o->RemoveAllObservers();

  // On 1 Remove 2
  o->AddObserver(itk::AnyEvent(), cmdInvoke);
  idToRemove = o->AddObserver(itk::UserEvent(), removeCmd);
  o->AddObserver(itk::AnyEvent(), cmd);
  removeCmd->SetClientData(&idToRemove);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 2);

  o->RemoveAllObservers();

  // On 1 Remove 3
  o->AddObserver(itk::AnyEvent(), cmdInvoke);
  o->AddObserver(itk::UserEvent(), removeCmd);
  idToRemove = o->AddObserver(itk::AnyEvent(), cmd);
  removeCmd->SetClientData(&idToRemove);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 0);

  return EXIT_SUCCESS;
}

bool
testDeleteEventThrow()
{
  // check the case where an exception in thrown in the DeleteEvent
  itk::Object::Pointer o = itk::Object::New();

  itk::CStyleCommand::Pointer cmd = itk::CStyleCommand::New();
  cmd->SetCallback(onAnyThrow);

  o->AddObserver(itk::DeleteEvent(), cmd);
  return EXIT_SUCCESS;
}

int
testLambdaCommand()
{
  // check the case where an exception in thrown in the DeleteEvent
  itk::Object::Pointer o = itk::Object::New();

  int cnt = 0;
  o->AddObserver(itk::AnyEvent(), [&cnt](const itk::EventObject &) { ++cnt; });

  auto & objRef = *o.GetPointer();
  o->AddObserver(itk::AnyEvent(), [&objRef](const itk::EventObject & event) {
    std::cout << "Object: " << objRef.GetNameOfClass() << " Event: " << event << std::endl;
  });

  o->InvokeEvent(itk::AnyEvent());

  ITK_TEST_EXPECT_EQUAL(1, cnt);

  return EXIT_SUCCESS;
}

} // end namespace

int
itkCommandObserverObjectTest(int, char *[])
{
  bool ret = true;

  ret &= (testDeleteObserverDuringEvent() == EXIT_SUCCESS);
  ret &= (testCommandConstObject() == EXIT_SUCCESS);
  ret &= (testCommandRecursiveObject() == EXIT_SUCCESS);
  ret &= (testDeleteEventThrow() == EXIT_SUCCESS);
  ret &= (testLambdaCommand() == EXIT_SUCCESS);

  return ret ? EXIT_SUCCESS : EXIT_FAILURE;
}
<commit_msg>BUG: ASAN identified use after delete bug<commit_after>/*=========================================================================
 *
 *  Copyright NumFOCUS
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include <iostream>
#include "itkObject.h"

#include "itkCommand.h"
#include "itkTestingMacros.h"

//
// This test is for testing the Command Observer functionality of the
// itk::Object class.
//

namespace
{

unsigned int onAnyCount = 0;

void
onAny(itk::Object *, const itk::EventObject &, void *)
{
  ++onAnyCount;
}

void
onAnyInvokeUser(itk::Object * o, const itk::EventObject &, void *)
{
  static bool invoke = true;
  if (invoke)
  {
    invoke = false;
    o->InvokeEvent(itk::UserEvent());
    invoke = true;
  }
}

void
onAnyConst(const itk::Object *, const itk::EventObject &, void *)
{
  ++onAnyCount;
}

void
onAnyThrow(itk::Object *, const itk::EventObject &, void *)
{
  throw;
}

void
onUserRemove(itk::Object * o, const itk::EventObject &, void * data)
{
  unsigned long idToRemove = *static_cast<unsigned long *>(data);
  o->RemoveObserver(idToRemove);
}

int
testDeleteObserverDuringEvent()
{
  itk::Object::Pointer o = itk::Object::New();

  unsigned long idToRemove;

  itk::CStyleCommand::Pointer removeCmd = itk::CStyleCommand::New();
  removeCmd->SetCallback(onUserRemove);
  removeCmd->SetObjectName("Remove Command");

  itk::CStyleCommand::Pointer cmd = itk::CStyleCommand::New();
  cmd->SetCallback(onAny);
  cmd->SetObjectName("Any Command 1");

  // Add Order 1
  o->AddObserver(itk::UserEvent(), removeCmd);
  idToRemove = o->AddObserver(itk::AnyEvent(), cmd);
  o->AddObserver(itk::AnyEvent(), cmd);
  removeCmd->SetClientData(&idToRemove);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 2);

  onAnyCount = 0;
  o->InvokeEvent(itk::UserEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 1);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 1);

  o->RemoveAllObservers();

  // Add Order 2
  idToRemove = o->AddObserver(itk::AnyEvent(), cmd);
  o->AddObserver(itk::UserEvent(), removeCmd);
  o->AddObserver(itk::AnyEvent(), cmd);
  removeCmd->SetClientData(&idToRemove);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 2);

  onAnyCount = 0;
  o->InvokeEvent(itk::UserEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 2);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 1);

  o->RemoveAllObservers();

  // Add Order 3
  idToRemove = o->AddObserver(itk::AnyEvent(), cmd);
  o->AddObserver(itk::AnyEvent(), cmd);
  o->AddObserver(itk::UserEvent(), removeCmd);
  removeCmd->SetClientData(&idToRemove);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 2);

  onAnyCount = 0;
  o->InvokeEvent(itk::UserEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 2);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 1);

  o->RemoveAllObservers();

  // Add Order 4
  o->AddObserver(itk::AnyEvent(), cmd);
  o->AddObserver(itk::UserEvent(), removeCmd);
  idToRemove = o->AddObserver(itk::AnyEvent(), cmd);
  removeCmd->SetClientData(&idToRemove);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 2);

  onAnyCount = 0;
  o->InvokeEvent(itk::UserEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 1);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 1);

  o->RemoveAllObservers();

  return EXIT_SUCCESS;
}

int
testCommandConstObject()
{

  itk::Object::Pointer      o = itk::Object::New();
  itk::Object::ConstPointer co = o;

  itk::CStyleCommand::Pointer cmd = itk::CStyleCommand::New();
  cmd->SetConstCallback(onAnyConst);
  cmd->SetObjectName("Any Command 1");

  itk::CStyleCommand::Pointer removeCmd = itk::CStyleCommand::New();
  removeCmd->SetCallback(onUserRemove);
  removeCmd->SetObjectName("Remove Command");

  co->AddObserver(itk::AnyEvent(), cmd);
  ITK_TEST_EXPECT_TRUE(co->HasObserver(itk::AnyEvent()));

  // the constant command doesn't get executed from the non-const
  // invocation
  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 0);

  onAnyCount = 0;
  co->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 1);

  return EXIT_SUCCESS;
}

int
testCommandRecursiveObject()
{
  // this test has an command invoking another event, while removing a
  // a Command.
  // This is a super-mean test that is not likely to really be used.

  itk::Object::Pointer      o = itk::Object::New();
  itk::Object::ConstPointer co = o;

  unsigned long idToRemove;

  itk::CStyleCommand::Pointer cmd = itk::CStyleCommand::New();
  cmd->SetCallback(onAny);
  cmd->SetObjectName("Any Command 1");

  itk::CStyleCommand::Pointer removeCmd = itk::CStyleCommand::New();
  removeCmd->SetCallback(onUserRemove);
  removeCmd->SetObjectName("Remove Command");

  itk::CStyleCommand::Pointer cmdInvoke = itk::CStyleCommand::New();
  cmdInvoke->SetCallback(onAnyInvokeUser);
  cmdInvoke->SetObjectName("Any Invoke User");

  // On 1 Remove 1
  idToRemove = o->AddObserver(itk::AnyEvent(), cmdInvoke);
  o->AddObserver(itk::UserEvent(), removeCmd);
  o->AddObserver(itk::AnyEvent(), cmd);
  removeCmd->SetClientData(&idToRemove);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 2);

  o->RemoveAllObservers();

  // On 1 Remove 2
  o->AddObserver(itk::AnyEvent(), cmdInvoke);
  idToRemove = o->AddObserver(itk::UserEvent(), removeCmd);
  o->AddObserver(itk::AnyEvent(), cmd);
  removeCmd->SetClientData(&idToRemove);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 2);

  o->RemoveAllObservers();

  // On 1 Remove 3
  o->AddObserver(itk::AnyEvent(), cmdInvoke);
  o->AddObserver(itk::UserEvent(), removeCmd);
  idToRemove = o->AddObserver(itk::AnyEvent(), cmd);
  removeCmd->SetClientData(&idToRemove);

  onAnyCount = 0;
  o->InvokeEvent(itk::AnyEvent());
  ITK_TEST_EXPECT_TRUE(onAnyCount == 0);

  return EXIT_SUCCESS;
}

bool
testDeleteEventThrow()
{
  // check the case where an exception in thrown in the DeleteEvent
  itk::Object::Pointer o = itk::Object::New();

  itk::CStyleCommand::Pointer cmd = itk::CStyleCommand::New();
  cmd->SetCallback(onAnyThrow);

  o->AddObserver(itk::DeleteEvent(), cmd);
  return EXIT_SUCCESS;
}

int
testLambdaCommand()
{
  // NOTE: cnt needs to be defined BEFORE "o" because it MUST exist when the "DeleteEvent()" is causes the
  //      FIRST OBSERVER LAMBDA to be called.  If 'cnt' is defined after 'o' then when the scope
  //      ends, 'cnt' is deleted first, followed by deleting 'o' which tries to increment 'cnt' when
  //      the 'DeleteEvent' tries to be processed.
  int cnt = 0;
  int name_of_class_cnt = 0;

  {
    // check the case where an exception in thrown in the DeleteEvent
    itk::Object::Pointer o = itk::Object::New();
    /*----- FIRST OBSERVER LAMBDA */
    o->AddObserver(itk::AnyEvent(), [&cnt](const itk::EventObject &) { ++cnt; });

    auto & objRef = *o.GetPointer();
    /*----- SECOND OBSERVER LAMBDA */
    o->AddObserver(itk::AnyEvent(), [&objRef, &name_of_class_cnt](const itk::EventObject & event) {
      ++name_of_class_cnt;
      std::cout << "Ivocation # " << name_of_class_cnt << "\nObject: " << objRef.GetNameOfClass() << " Event: " << event
                << std::endl;
    });

    o->InvokeEvent(itk::AnyEvent());
    ITK_TEST_EXPECT_EQUAL(1, cnt);
    ITK_TEST_EXPECT_EQUAL(1, name_of_class_cnt);

  }                              // A DeleteEvent is called here! as object "o" is deleted
  ITK_TEST_EXPECT_EQUAL(2, cnt); // Verify that cnt really was incremented during DeleteEvent!
  ITK_TEST_EXPECT_EQUAL(2, name_of_class_cnt);
  return EXIT_SUCCESS;
}

} // end namespace

int
itkCommandObserverObjectTest(int, char *[])
{
  bool ret = true;

  ret &= (testDeleteObserverDuringEvent() == EXIT_SUCCESS);
  ret &= (testCommandConstObject() == EXIT_SUCCESS);
  ret &= (testCommandRecursiveObject() == EXIT_SUCCESS);
  ret &= (testDeleteEventThrow() == EXIT_SUCCESS);
  ret &= (testLambdaCommand() == EXIT_SUCCESS);

  return ret ? EXIT_SUCCESS : EXIT_FAILURE;
}
<|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 "QmitkNavigationToolCreationWidget.h"

//mitk headers
#include "mitkTrackingTypes.h"
#include <mitkSTLFileReader.h>
#include <mitkSurface.h>
#include "mitkNavigationData.h"
#include "mitkRenderingManager.h"

//qt headers
#include <qfiledialog.h>
#include <qmessagebox.h>
#include <QDialog>

//poco headers
#include <Poco/Path.h>

// vtk
#include <vtkSphereSource.h>
#include "vtkConeSource.h"

const std::string QmitkNavigationToolCreationWidget::VIEW_ID = "org.mitk.views.navigationtoolcreationwizardwidget";

QmitkNavigationToolCreationWidget::QmitkNavigationToolCreationWidget(QWidget* parent, Qt::WindowFlags f)
: QWidget(parent, f)
{
  m_Controls = NULL;
  m_AdvancedWidget = new QmitkNavigationToolCreationAdvancedWidget(this);
  m_AdvancedWidget->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
  m_AdvancedWidget->setWindowTitle("Tool Creation Advanced Options");
  m_AdvancedWidget->setModal(false);
  CreateQtPartControl(this);
  CreateConnections();
}

QmitkNavigationToolCreationWidget::~QmitkNavigationToolCreationWidget()
{
  delete m_AdvancedWidget;
}

void QmitkNavigationToolCreationWidget::CreateQtPartControl(QWidget *parent)
{
  if (!m_Controls)
  {
    // create GUI widgets
    m_Controls = new Ui::QmitkNavigationToolCreationWidgetControls;
    m_Controls->setupUi(parent);
  }
}

void QmitkNavigationToolCreationWidget::CreateConnections()
{
  if ( m_Controls )
  {
    connect( (QObject*)(m_Controls->m_cancel), SIGNAL(clicked()), this, SLOT(OnCancel()) );
    connect( (QObject*)(m_Controls->m_finished), SIGNAL(clicked()), this, SLOT(OnFinished()) );
    connect( (QObject*)(m_Controls->m_LoadSurface), SIGNAL(clicked()), this, SLOT(OnLoadSurface()) );
    connect( (QObject*)(m_Controls->m_LoadCalibrationFile), SIGNAL(clicked()), this, SLOT(OnLoadCalibrationFile()) );
    connect( (QObject*)(m_Controls->m_ShowAdvancedOptionsPB), SIGNAL(toggled(bool)), this, SLOT(OnShowAdvancedOptions(bool)) );
    connect( (QObject*)(m_AdvancedWidget), SIGNAL(DialogCloseRequested()), this, SLOT(OnProcessDialogCloseRequest()) );
    connect( (QObject*)(m_AdvancedWidget), SIGNAL(RetrieveDataForManualToolTipManipulation()), this, SLOT(OnRetrieveDataForManualTooltipManipulation()) );
  }
}

void QmitkNavigationToolCreationWidget::Initialize(mitk::DataStorage* dataStorage, std::string supposedIdentifier, std::string supposedName)
{
  m_DataStorage = dataStorage;

  //initialize UI components
  m_Controls->m_SurfaceChooser->SetDataStorage(m_DataStorage);
  m_Controls->m_SurfaceChooser->SetAutoSelectNewItems(true);
  m_Controls->m_SurfaceChooser->SetPredicate(mitk::NodePredicateDataType::New("Surface"));

  //set default data
  m_Controls->m_ToolNameEdit->setText(supposedName.c_str());
  m_Controls->m_CalibrationFileName->setText("none");
  m_Controls->m_Surface_Use_Sphere->setChecked(true);
  m_AdvancedWidget->SetDataStorage(m_DataStorage);

}

void QmitkNavigationToolCreationWidget::SetTrackingDeviceType(mitk::TrackingDeviceType type, bool changeable)
{
  switch(type)
  {
  case mitk::NDIAurora:
    m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(0);break;
  case mitk::NDIPolaris:
    m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(1);break;
  case mitk::ClaronMicron:
    m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(2);break;
  default:
    m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(0);
  }
  m_Controls->m_TrackingDeviceTypeChooser->setEnabled(changeable);
}

mitk::NavigationTool::Pointer QmitkNavigationToolCreationWidget::GetCreatedTool()
{
  return m_CreatedTool;
}

//##################################################################################
//############################## slots                  ############################
//##################################################################################

void QmitkNavigationToolCreationWidget::OnFinished()
{
  //here we create a new tool
  m_CreatedTool = mitk::NavigationTool::New();

  //create DataNode...
  mitk::DataNode::Pointer newNode = mitk::DataNode::New();
  if(m_Controls->m_Surface_Use_Sphere->isChecked())
  {
    //create small sphere and use it as surface
    mitk::Surface::Pointer mySphere = mitk::Surface::New();
    vtkConeSource *vtkData = vtkConeSource::New();
    vtkData->SetAngle(5.0);
    vtkData->SetResolution(50);
    vtkData->SetHeight(6.0f);
    vtkData->SetRadius(2.0f);
    vtkData->SetCenter(0.0, 0.0, 0.0);
    vtkData->Update();
    mySphere->SetVtkPolyData(vtkData->GetOutput());
    vtkData->Delete();
    newNode->SetData(mySphere);
  }
  else
  {
    newNode->SetData(m_Controls->m_SurfaceChooser->GetSelectedNode()->GetData());
  }
  newNode->SetName(m_Controls->m_ToolNameEdit->text().toLatin1());

  m_CreatedTool->SetDataNode(newNode);

  //fill NavigationTool object
  m_CreatedTool->SetCalibrationFile(m_Controls->m_CalibrationFileName->text().toAscii().data());
  m_CreatedTool->SetIdentifier(m_Controls->m_IdentifierEdit->text().toAscii().data());
  m_CreatedTool->SetSerialNumber(m_Controls->m_SerialNumberEdit->text().toAscii().data());

  //Tracking Device
  if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="NDI Aurora") m_CreatedTool->SetTrackingDeviceType(mitk::NDIAurora);
  else if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="NDI Polaris") m_CreatedTool->SetTrackingDeviceType(mitk::NDIPolaris);
  else if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="Claron Technology Micron Tracker") m_CreatedTool->SetTrackingDeviceType(mitk::ClaronMicron);
  else m_CreatedTool->SetTrackingDeviceType(mitk::TrackingSystemNotSpecified);

  //ToolType
  if (m_Controls->m_ToolTypeChooser->currentText()=="Instrument") m_CreatedTool->SetType(mitk::NavigationTool::Instrument);
  else if (m_Controls->m_ToolTypeChooser->currentText()=="Fiducial") m_CreatedTool->SetType(mitk::NavigationTool::Fiducial);
  else if (m_Controls->m_ToolTypeChooser->currentText()=="Skinmarker") m_CreatedTool->SetType(mitk::NavigationTool::Skinmarker);
  else m_CreatedTool->SetType(mitk::NavigationTool::Unknown);

  mitk::NavigationData::Pointer tempND = mitk::NavigationData::New(m_AdvancedWidget->GetManipulatedToolTip());
  m_CreatedTool->SetToolTipOrientation(tempND->GetOrientation());
  m_CreatedTool->SetToolTipPosition(tempND->GetPosition());

  emit NavigationToolFinished();
}

void QmitkNavigationToolCreationWidget::OnCancel()
{
  m_CreatedTool = NULL;

  emit Canceled();
}

void QmitkNavigationToolCreationWidget::OnLoadSurface()
{
  std::string filename = QFileDialog::getOpenFileName(NULL,tr("Open Surface"), "/", "*.stl").toLatin1().data();
  mitk::STLFileReader::Pointer stlReader = mitk::STLFileReader::New();
  try
  {
    stlReader->SetFileName( filename.c_str() );
    stlReader->Update();
  }
  catch (...)
  {
  }

  if ( stlReader->GetOutput() == NULL );
  else
  {
    mitk::DataNode::Pointer newNode = mitk::DataNode::New();
    newNode->SetName(filename);
    newNode->SetData(stlReader->GetOutput());
    m_DataStorage->Add(newNode);
  }
}

void QmitkNavigationToolCreationWidget::OnLoadCalibrationFile()
{
  m_Controls->m_CalibrationFileName->setText(QFileDialog::getOpenFileName(NULL,tr("Open Calibration File"), "/", "*.*"));
}

void QmitkNavigationToolCreationWidget::SetDefaultData(mitk::NavigationTool::Pointer DefaultTool)
{
  m_Controls->m_ToolNameEdit->setText(QString(DefaultTool->GetDataNode()->GetName().c_str()));
  m_Controls->m_IdentifierEdit->setText(QString(DefaultTool->GetIdentifier().c_str()));
  m_Controls->m_SerialNumberEdit->setText(QString(DefaultTool->GetSerialNumber().c_str()));
  m_AdvancedWidget->SetDefaultTooltip( DefaultTool->GetToolTipTransform() );
  switch(DefaultTool->GetTrackingDeviceType())
  {
  case mitk::NDIAurora:
    m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(0);break;
  case mitk::NDIPolaris:
    m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(1);break;
  case mitk::ClaronMicron:
    m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(2);break;
  default:
    m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(0);
  }
  m_Controls->m_CalibrationFileName->setText(QString(DefaultTool->GetCalibrationFile().c_str()));
  m_Controls->m_Surface_Use_Other->setChecked(true);
  switch(DefaultTool->GetType())
      {
      case mitk::NavigationTool::Instrument:
        m_Controls->m_ToolTypeChooser->setCurrentIndex(0); break;
      case mitk::NavigationTool::Fiducial:
        m_Controls->m_ToolTypeChooser->setCurrentIndex(1); break;
      case mitk::NavigationTool::Skinmarker:
        m_Controls->m_ToolTypeChooser->setCurrentIndex(2); break;
      case mitk::NavigationTool::Unknown:
        m_Controls->m_ToolTypeChooser->setCurrentIndex(3); break;
      }

  m_Controls->m_SurfaceChooser->SetSelectedNode(DefaultTool->GetDataNode());

}

//##################################################################################
//############################## internal help methods #############################
//##################################################################################
void QmitkNavigationToolCreationWidget::MessageBox(std::string s)
{
  QMessageBox msgBox;
  msgBox.setText(s.c_str());
  msgBox.exec();
}

void QmitkNavigationToolCreationWidget::OnShowAdvancedOptions(bool state)
{
  if(state)
  {
    m_AdvancedWidget->show();
    m_AdvancedWidget->SetDefaultTooltip(m_AdvancedWidget->GetManipulatedToolTip()); //use the last one, if there is one
    m_AdvancedWidget->ReInitialize();

    // reinit the views with the new nodes
    mitk::DataStorage::SetOfObjects::ConstPointer rs = m_DataStorage->GetAll();
    mitk::TimeGeometry::Pointer bounds = m_DataStorage->ComputeBoundingGeometry3D(rs, "visible");    // initialize the views to the bounding geometry
    mitk::RenderingManager::GetInstance()->InitializeViews(bounds);
  }
  else
  {
    m_AdvancedWidget->hide();
  }
}

void QmitkNavigationToolCreationWidget::OnProcessDialogCloseRequest()
{
  m_AdvancedWidget->hide();
  m_Controls->m_ShowAdvancedOptionsPB->setChecked(false);
}

void QmitkNavigationToolCreationWidget::OnRetrieveDataForManualTooltipManipulation()
{
  if(m_Controls->m_Surface_Use_Sphere->isChecked())
  {
    m_AdvancedWidget->SetToolTipSurface(true);
  }
  else
  {
    m_AdvancedWidget->SetToolTipSurface(false,
      dynamic_cast<mitk::DataNode*>(m_Controls->m_SurfaceChooser->GetSelectedNode().GetPointer()));
  }
}
<commit_msg>Filter extended to work on linux, too.<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 "QmitkNavigationToolCreationWidget.h"

//mitk headers
#include "mitkTrackingTypes.h"
#include <mitkSTLFileReader.h>
#include <mitkSurface.h>
#include "mitkNavigationData.h"
#include "mitkRenderingManager.h"

//qt headers
#include <qfiledialog.h>
#include <qmessagebox.h>
#include <QDialog>

//poco headers
#include <Poco/Path.h>

// vtk
#include <vtkSphereSource.h>
#include "vtkConeSource.h"

const std::string QmitkNavigationToolCreationWidget::VIEW_ID = "org.mitk.views.navigationtoolcreationwizardwidget";

QmitkNavigationToolCreationWidget::QmitkNavigationToolCreationWidget(QWidget* parent, Qt::WindowFlags f)
: QWidget(parent, f)
{
  m_Controls = NULL;
  m_AdvancedWidget = new QmitkNavigationToolCreationAdvancedWidget(this);
  m_AdvancedWidget->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
  m_AdvancedWidget->setWindowTitle("Tool Creation Advanced Options");
  m_AdvancedWidget->setModal(false);
  CreateQtPartControl(this);
  CreateConnections();
}

QmitkNavigationToolCreationWidget::~QmitkNavigationToolCreationWidget()
{
  delete m_AdvancedWidget;
}

void QmitkNavigationToolCreationWidget::CreateQtPartControl(QWidget *parent)
{
  if (!m_Controls)
  {
    // create GUI widgets
    m_Controls = new Ui::QmitkNavigationToolCreationWidgetControls;
    m_Controls->setupUi(parent);
  }
}

void QmitkNavigationToolCreationWidget::CreateConnections()
{
  if ( m_Controls )
  {
    connect( (QObject*)(m_Controls->m_cancel), SIGNAL(clicked()), this, SLOT(OnCancel()) );
    connect( (QObject*)(m_Controls->m_finished), SIGNAL(clicked()), this, SLOT(OnFinished()) );
    connect( (QObject*)(m_Controls->m_LoadSurface), SIGNAL(clicked()), this, SLOT(OnLoadSurface()) );
    connect( (QObject*)(m_Controls->m_LoadCalibrationFile), SIGNAL(clicked()), this, SLOT(OnLoadCalibrationFile()) );
    connect( (QObject*)(m_Controls->m_ShowAdvancedOptionsPB), SIGNAL(toggled(bool)), this, SLOT(OnShowAdvancedOptions(bool)) );
    connect( (QObject*)(m_AdvancedWidget), SIGNAL(DialogCloseRequested()), this, SLOT(OnProcessDialogCloseRequest()) );
    connect( (QObject*)(m_AdvancedWidget), SIGNAL(RetrieveDataForManualToolTipManipulation()), this, SLOT(OnRetrieveDataForManualTooltipManipulation()) );
  }
}

void QmitkNavigationToolCreationWidget::Initialize(mitk::DataStorage* dataStorage, std::string supposedIdentifier, std::string supposedName)
{
  m_DataStorage = dataStorage;

  //initialize UI components
  m_Controls->m_SurfaceChooser->SetDataStorage(m_DataStorage);
  m_Controls->m_SurfaceChooser->SetAutoSelectNewItems(true);
  m_Controls->m_SurfaceChooser->SetPredicate(mitk::NodePredicateDataType::New("Surface"));

  //set default data
  m_Controls->m_ToolNameEdit->setText(supposedName.c_str());
  m_Controls->m_CalibrationFileName->setText("none");
  m_Controls->m_Surface_Use_Sphere->setChecked(true);
  m_AdvancedWidget->SetDataStorage(m_DataStorage);

}

void QmitkNavigationToolCreationWidget::SetTrackingDeviceType(mitk::TrackingDeviceType type, bool changeable)
{
  switch(type)
  {
  case mitk::NDIAurora:
    m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(0);break;
  case mitk::NDIPolaris:
    m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(1);break;
  case mitk::ClaronMicron:
    m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(2);break;
  default:
    m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(0);
  }
  m_Controls->m_TrackingDeviceTypeChooser->setEnabled(changeable);
}

mitk::NavigationTool::Pointer QmitkNavigationToolCreationWidget::GetCreatedTool()
{
  return m_CreatedTool;
}

//##################################################################################
//############################## slots                  ############################
//##################################################################################

void QmitkNavigationToolCreationWidget::OnFinished()
{
  //here we create a new tool
  m_CreatedTool = mitk::NavigationTool::New();

  //create DataNode...
  mitk::DataNode::Pointer newNode = mitk::DataNode::New();
  if(m_Controls->m_Surface_Use_Sphere->isChecked())
  {
    //create small sphere and use it as surface
    mitk::Surface::Pointer mySphere = mitk::Surface::New();
    vtkConeSource *vtkData = vtkConeSource::New();
    vtkData->SetAngle(5.0);
    vtkData->SetResolution(50);
    vtkData->SetHeight(6.0f);
    vtkData->SetRadius(2.0f);
    vtkData->SetCenter(0.0, 0.0, 0.0);
    vtkData->Update();
    mySphere->SetVtkPolyData(vtkData->GetOutput());
    vtkData->Delete();
    newNode->SetData(mySphere);
  }
  else
  {
    newNode->SetData(m_Controls->m_SurfaceChooser->GetSelectedNode()->GetData());
  }
  newNode->SetName(m_Controls->m_ToolNameEdit->text().toLatin1());

  m_CreatedTool->SetDataNode(newNode);

  //fill NavigationTool object
  m_CreatedTool->SetCalibrationFile(m_Controls->m_CalibrationFileName->text().toAscii().data());
  m_CreatedTool->SetIdentifier(m_Controls->m_IdentifierEdit->text().toAscii().data());
  m_CreatedTool->SetSerialNumber(m_Controls->m_SerialNumberEdit->text().toAscii().data());

  //Tracking Device
  if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="NDI Aurora") m_CreatedTool->SetTrackingDeviceType(mitk::NDIAurora);
  else if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="NDI Polaris") m_CreatedTool->SetTrackingDeviceType(mitk::NDIPolaris);
  else if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="Claron Technology Micron Tracker") m_CreatedTool->SetTrackingDeviceType(mitk::ClaronMicron);
  else m_CreatedTool->SetTrackingDeviceType(mitk::TrackingSystemNotSpecified);

  //ToolType
  if (m_Controls->m_ToolTypeChooser->currentText()=="Instrument") m_CreatedTool->SetType(mitk::NavigationTool::Instrument);
  else if (m_Controls->m_ToolTypeChooser->currentText()=="Fiducial") m_CreatedTool->SetType(mitk::NavigationTool::Fiducial);
  else if (m_Controls->m_ToolTypeChooser->currentText()=="Skinmarker") m_CreatedTool->SetType(mitk::NavigationTool::Skinmarker);
  else m_CreatedTool->SetType(mitk::NavigationTool::Unknown);

  mitk::NavigationData::Pointer tempND = mitk::NavigationData::New(m_AdvancedWidget->GetManipulatedToolTip());
  m_CreatedTool->SetToolTipOrientation(tempND->GetOrientation());
  m_CreatedTool->SetToolTipPosition(tempND->GetPosition());

  emit NavigationToolFinished();
}

void QmitkNavigationToolCreationWidget::OnCancel()
{
  m_CreatedTool = NULL;

  emit Canceled();
}

void QmitkNavigationToolCreationWidget::OnLoadSurface()
{
  std::string filename = QFileDialog::getOpenFileName(NULL,tr("Open Surface"), "/", tr("STL (*.stl)")).toLatin1().data();
  mitk::STLFileReader::Pointer stlReader = mitk::STLFileReader::New();
  try
  {
    stlReader->SetFileName( filename.c_str() );
    stlReader->Update();
  }
  catch (...)
  {
  }

  if ( stlReader->GetOutput() == NULL );
  else
  {
    mitk::DataNode::Pointer newNode = mitk::DataNode::New();
    newNode->SetName(filename);
    newNode->SetData(stlReader->GetOutput());
    m_DataStorage->Add(newNode);
  }
}

void QmitkNavigationToolCreationWidget::OnLoadCalibrationFile()
{
  m_Controls->m_CalibrationFileName->setText(QFileDialog::getOpenFileName(NULL,tr("Open Calibration File"), "/", "*.*"));
}

void QmitkNavigationToolCreationWidget::SetDefaultData(mitk::NavigationTool::Pointer DefaultTool)
{
  m_Controls->m_ToolNameEdit->setText(QString(DefaultTool->GetDataNode()->GetName().c_str()));
  m_Controls->m_IdentifierEdit->setText(QString(DefaultTool->GetIdentifier().c_str()));
  m_Controls->m_SerialNumberEdit->setText(QString(DefaultTool->GetSerialNumber().c_str()));
  m_AdvancedWidget->SetDefaultTooltip( DefaultTool->GetToolTipTransform() );
  switch(DefaultTool->GetTrackingDeviceType())
  {
  case mitk::NDIAurora:
    m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(0);break;
  case mitk::NDIPolaris:
    m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(1);break;
  case mitk::ClaronMicron:
    m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(2);break;
  default:
    m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(0);
  }
  m_Controls->m_CalibrationFileName->setText(QString(DefaultTool->GetCalibrationFile().c_str()));
  m_Controls->m_Surface_Use_Other->setChecked(true);
  switch(DefaultTool->GetType())
      {
      case mitk::NavigationTool::Instrument:
        m_Controls->m_ToolTypeChooser->setCurrentIndex(0); break;
      case mitk::NavigationTool::Fiducial:
        m_Controls->m_ToolTypeChooser->setCurrentIndex(1); break;
      case mitk::NavigationTool::Skinmarker:
        m_Controls->m_ToolTypeChooser->setCurrentIndex(2); break;
      case mitk::NavigationTool::Unknown:
        m_Controls->m_ToolTypeChooser->setCurrentIndex(3); break;
      }

  m_Controls->m_SurfaceChooser->SetSelectedNode(DefaultTool->GetDataNode());

}

//##################################################################################
//############################## internal help methods #############################
//##################################################################################
void QmitkNavigationToolCreationWidget::MessageBox(std::string s)
{
  QMessageBox msgBox;
  msgBox.setText(s.c_str());
  msgBox.exec();
}

void QmitkNavigationToolCreationWidget::OnShowAdvancedOptions(bool state)
{
  if(state)
  {
    m_AdvancedWidget->show();
    m_AdvancedWidget->SetDefaultTooltip(m_AdvancedWidget->GetManipulatedToolTip()); //use the last one, if there is one
    m_AdvancedWidget->ReInitialize();

    // reinit the views with the new nodes
    mitk::DataStorage::SetOfObjects::ConstPointer rs = m_DataStorage->GetAll();
    mitk::TimeGeometry::Pointer bounds = m_DataStorage->ComputeBoundingGeometry3D(rs, "visible");    // initialize the views to the bounding geometry
    mitk::RenderingManager::GetInstance()->InitializeViews(bounds);
  }
  else
  {
    m_AdvancedWidget->hide();
  }
}

void QmitkNavigationToolCreationWidget::OnProcessDialogCloseRequest()
{
  m_AdvancedWidget->hide();
  m_Controls->m_ShowAdvancedOptionsPB->setChecked(false);
}

void QmitkNavigationToolCreationWidget::OnRetrieveDataForManualTooltipManipulation()
{
  if(m_Controls->m_Surface_Use_Sphere->isChecked())
  {
    m_AdvancedWidget->SetToolTipSurface(true);
  }
  else
  {
    m_AdvancedWidget->SetToolTipSurface(false,
      dynamic_cast<mitk::DataNode*>(m_Controls->m_SurfaceChooser->GetSelectedNode().GetPointer()));
  }
}
<|endoftext|>