<commit_before>#pragma once

#include "Renderer.h"
#include "Camera.h"
#include "View.h"
#include "Renderables/Renderable.h"
#include "Math/Vector3.h"

#include "GLBlaat/GL.h"
#include "GLBlaat/GLTexture.h"
#include "GLBlaat/GLTextureManager.h"
#include "GLBlaat/GLFramebuffer.h"
#include "GLBlaat/GLUtility.h"

#include <cassert>
#include <iostream>
#include <limits>

namespace NQVTK
{
	// ------------------------------------------------------------------------
	Renderer::Renderer() : camera(0), view(0), tm(0), fboTarget(0)
	{
		viewportX = 0;
		viewportY = 0;
		viewportWidth = 1;
		viewportHeight = 1;

		lightOffsetDirection = 270.0;
		lightRelativeToCamera = true;
	}

	// ------------------------------------------------------------------------
	Renderer::~Renderer()
	{
		delete camera;
		delete view;
		delete tm;
	}

	// ------------------------------------------------------------------------
	bool Renderer::Initialize()
	{
		glEnable(GL_CULL_FACE);
		glEnable(GL_DEPTH_TEST);

		// Make sure we have a camera
		GetCamera();

		if (!tm)
		{
			tm = GLTextureManager::New();
			if (!tm)
			{
				std::cerr << "Failed to create texture manager! " <<
					"Check hardware requirements..." << std::endl;
				return false;
			}
		}
		tm->BeginNewPass();

		return true;
	}

	// ------------------------------------------------------------------------
	void Renderer::Move(int x, int y)
	{
		SetViewport(x, y, viewportWidth, viewportHeight);
	}

	// ------------------------------------------------------------------------
	void Renderer::Resize(int w, int h)
	{
		SetViewport(viewportX, viewportY, w, h);
	}

	// ------------------------------------------------------------------------
	void Renderer::SetViewport(int x, int y, int w, int h)
	{
		viewportX = x;
		viewportY = y;
		viewportWidth = w;
		viewportHeight = h;

		glViewport(viewportX, viewportY, viewportWidth, viewportHeight);
		GetCamera()->aspect = static_cast<double>(w) / static_cast<double>(h);

		// NOTE: The target is never resized by the renderer it's assigned to,
		// it should be managed by its owner!
	}

	// ------------------------------------------------------------------------
	void Renderer::Clear()
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	}

	// ------------------------------------------------------------------------
	void Renderer::SetScene(Scene *scene)
	{
		assert(scene);
		SetView(new View(scene));
	}

	// ------------------------------------------------------------------------
	void Renderer::SetView(View *view)
	{
		assert(view);
		if (view == this->view) return;

		delete this->view;
		this->view = view;
	}

	// ------------------------------------------------------------------------
	Camera *Renderer::GetCamera()
	{
		// Create a default camera if we don't have one
		if (!camera)
		{
			camera = new Camera();
		}

		return camera;
	}

	// ------------------------------------------------------------------------
	void Renderer::SetCamera(Camera *cam)
	{
		if (camera) delete camera;
		camera = cam;
	}

	// ------------------------------------------------------------------------
	GLFramebuffer *Renderer::SetTarget(GLFramebuffer *target)
	{
		GLFramebuffer *oldTarget = this->fboTarget;
		this->fboTarget = target;
		return oldTarget;
	}

	// ------------------------------------------------------------------------
	void Renderer::DrawCamera()
	{
		// Get bounds for all visible renderables
		// TODO: this could be moved to the scene or the view
		const double inf = std::numeric_limits<double>::infinity();
		double bounds[] = {inf, -inf, inf, -inf, inf, -inf};
		if (view)
		{
			unsigned int numRenderables = view->GetNumberOfRenderables();
			for (unsigned int i = 0; i < numRenderables; ++i)
			{
				Renderable *renderable = view->GetRenderable(i);
				if (view->GetVisibility(i))
				{
					double rbounds[6];
					renderable->GetBounds(rbounds);
					for (int i = 0; i < 3; ++i)
					{
						if (rbounds[i*2] < bounds[i*2])
							bounds[i*2] = rbounds[i*2];

						if (rbounds[i*2+1] > bounds[i*2+1])
							bounds[i*2+1] = rbounds[i*2+1];
					}
				}
			}
		}

		camera->SetZPlanes(bounds);

		// Set up the camera (matrices)
		camera->Draw();
	}

	// ------------------------------------------------------------------------
	void Renderer::ResetTextures()
	{
		// Reset texture manager binding cache
		tm->BeginNewPass();
	}

	// ------------------------------------------------------------------------
	void Renderer::UpdateLighting()
	{
		if (lightRelativeToCamera)
		{
			camera->Update();
			const double DEGREES_TO_RADIANS = 0.0174532925199433;
			Vector3 viewDir = (camera->focus - camera->position);
			Vector3 sideDir = viewDir.cross(camera->up).normalized();
			Vector3 upDir = sideDir.cross(viewDir).normalized();
			Vector3 offset =
				-sin(lightOffsetDirection * DEGREES_TO_RADIANS) * sideDir -
				cos(lightOffsetDirection * DEGREES_TO_RADIANS) * upDir;
			offset *= viewDir.length() / 2.0;
			lightPos = camera->position + offset;
		}

		// Update OpenGL light direction
		Vector3 lightDir = (lightPos - camera->focus).normalized();
		float ldir[] = {
			static_cast<float>(lightDir.x),
			static_cast<float>(lightDir.y),
			static_cast<float>(lightDir.z),
			0.0f};
		glLightfv(GL_LIGHT0, GL_POSITION, ldir);
	}

	// ------------------------------------------------------------------------
	void Renderer::PrepareForRenderable(int objectId, Renderable *renderable)
	{
	}

	// ------------------------------------------------------------------------
	void Renderer::DrawRenderables()
	{
		if (!view) return;

		// Iterate over all renderables in the scene and draw them
		for (int objectId = 0; objectId < view->GetNumberOfRenderables();
			++objectId)
		{
			// Visibility implies that the renderable is not null
			if (view->GetVisibility(objectId))
			{
				Renderable *renderable = view->GetRenderable(objectId);
				PrepareForRenderable(objectId, renderable);
				renderable->Draw();
			}
		}
	}

	// ------------------------------------------------------------------------
	void Renderer::DrawTexture(GLTexture *tex,
			double xmin, double xmax, double ymin, double ymax)
	{
		if (!tex) return;

		glPushAttrib(GL_ALL_ATTRIB_BITS);

		glColor3d(1.0, 1.0, 1.0);
		glDisable(GL_DEPTH_TEST);
		glMatrixMode(GL_TEXTURE);
		glLoadIdentity();
		glMatrixMode(GL_MODELVIEW);
		tex->BindToCurrent();
		glEnable(tex->GetTextureTarget());
		if (tex->GetTextureTarget() == GL_TEXTURE_RECTANGLE_ARB)
		{
			glBegin(GL_QUADS);
			glTexCoord2d(0.0, 0.0);
			glVertex3d(xmin, ymin, 0.0);
			glTexCoord2d(tex->GetWidth(), 0.0);
			glVertex3d(xmax, ymin, 0.0);
			glTexCoord2d(tex->GetWidth(), tex->GetHeight());
			glVertex3d(xmax, ymax, 0.0);
			glTexCoord2d(0.0, tex->GetHeight());
			glVertex3d(xmin, ymax, 0.0);
			glEnd();
		}
		else
		{
			glBegin(GL_QUADS);
			glTexCoord2d(0.0, 0.0);
			glVertex3d(xmin, ymin, 0.0);
			glTexCoord2d(1.0, 0.0);
			glVertex3d(xmax, ymin, 0.0);
			glTexCoord2d(1.0, 1.0);
			glVertex3d(xmax, ymax, 0.0);
			glTexCoord2d(0.0, 1.0);
			glVertex3d(xmin, ymax, 0.0);
			glEnd();
		}
		glDisable(tex->GetTextureTarget());
		tex->UnbindCurrent();

		glPopAttrib();
	}
}
<commit_msg>Enable scene to be set to null.<commit_after>#pragma once

#include "Renderer.h"
#include "Camera.h"
#include "View.h"
#include "Renderables/Renderable.h"
#include "Math/Vector3.h"

#include "GLBlaat/GL.h"
#include "GLBlaat/GLTexture.h"
#include "GLBlaat/GLTextureManager.h"
#include "GLBlaat/GLFramebuffer.h"
#include "GLBlaat/GLUtility.h"

#include <cassert>
#include <iostream>
#include <limits>

namespace NQVTK
{
	// ------------------------------------------------------------------------
	Renderer::Renderer() : camera(0), view(0), tm(0), fboTarget(0)
	{
		viewportX = 0;
		viewportY = 0;
		viewportWidth = 1;
		viewportHeight = 1;

		lightOffsetDirection = 270.0;
		lightRelativeToCamera = true;
	}

	// ------------------------------------------------------------------------
	Renderer::~Renderer()
	{
		delete camera;
		delete view;
		delete tm;
	}

	// ------------------------------------------------------------------------
	bool Renderer::Initialize()
	{
		glEnable(GL_CULL_FACE);
		glEnable(GL_DEPTH_TEST);

		// Make sure we have a camera
		GetCamera();

		if (!tm)
		{
			tm = GLTextureManager::New();
			if (!tm)
			{
				std::cerr << "Failed to create texture manager! " <<
					"Check hardware requirements..." << std::endl;
				return false;
			}
		}
		tm->BeginNewPass();

		return true;
	}

	// ------------------------------------------------------------------------
	void Renderer::Move(int x, int y)
	{
		SetViewport(x, y, viewportWidth, viewportHeight);
	}

	// ------------------------------------------------------------------------
	void Renderer::Resize(int w, int h)
	{
		SetViewport(viewportX, viewportY, w, h);
	}

	// ------------------------------------------------------------------------
	void Renderer::SetViewport(int x, int y, int w, int h)
	{
		viewportX = x;
		viewportY = y;
		viewportWidth = w;
		viewportHeight = h;

		glViewport(viewportX, viewportY, viewportWidth, viewportHeight);
		GetCamera()->aspect = static_cast<double>(w) / static_cast<double>(h);

		// NOTE: The target is never resized by the renderer it's assigned to,
		// it should be managed by its owner!
	}

	// ------------------------------------------------------------------------
	void Renderer::Clear()
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	}

	// ------------------------------------------------------------------------
	void Renderer::SetScene(Scene *scene)
	{
		if (scene)
		{
			SetView(new View(scene));
		}
		else
		{
			SetView(0);
		}
	}

	// ------------------------------------------------------------------------
	void Renderer::SetView(View *view)
	{
		if (view == this->view) return;

		delete this->view;
		this->view = view;
	}

	// ------------------------------------------------------------------------
	Camera *Renderer::GetCamera()
	{
		// Create a default camera if we don't have one
		if (!camera)
		{
			camera = new Camera();
		}

		return camera;
	}

	// ------------------------------------------------------------------------
	void Renderer::SetCamera(Camera *cam)
	{
		if (camera) delete camera;
		camera = cam;
	}

	// ------------------------------------------------------------------------
	GLFramebuffer *Renderer::SetTarget(GLFramebuffer *target)
	{
		GLFramebuffer *oldTarget = this->fboTarget;
		this->fboTarget = target;
		return oldTarget;
	}

	// ------------------------------------------------------------------------
	void Renderer::DrawCamera()
	{
		// Get bounds for all visible renderables
		// TODO: this could be moved to the scene or the view
		const double inf = std::numeric_limits<double>::infinity();
		double bounds[] = {inf, -inf, inf, -inf, inf, -inf};
		if (view)
		{
			unsigned int numRenderables = view->GetNumberOfRenderables();
			for (unsigned int i = 0; i < numRenderables; ++i)
			{
				Renderable *renderable = view->GetRenderable(i);
				if (view->GetVisibility(i))
				{
					double rbounds[6];
					renderable->GetBounds(rbounds);
					for (int i = 0; i < 3; ++i)
					{
						if (rbounds[i*2] < bounds[i*2])
							bounds[i*2] = rbounds[i*2];

						if (rbounds[i*2+1] > bounds[i*2+1])
							bounds[i*2+1] = rbounds[i*2+1];
					}
				}
			}
		}

		camera->SetZPlanes(bounds);

		// Set up the camera (matrices)
		camera->Draw();
	}

	// ------------------------------------------------------------------------
	void Renderer::ResetTextures()
	{
		// Reset texture manager binding cache
		tm->BeginNewPass();
	}

	// ------------------------------------------------------------------------
	void Renderer::UpdateLighting()
	{
		if (lightRelativeToCamera)
		{
			camera->Update();
			const double DEGREES_TO_RADIANS = 0.0174532925199433;
			Vector3 viewDir = (camera->focus - camera->position);
			Vector3 sideDir = viewDir.cross(camera->up).normalized();
			Vector3 upDir = sideDir.cross(viewDir).normalized();
			Vector3 offset =
				-sin(lightOffsetDirection * DEGREES_TO_RADIANS) * sideDir -
				cos(lightOffsetDirection * DEGREES_TO_RADIANS) * upDir;
			offset *= viewDir.length() / 2.0;
			lightPos = camera->position + offset;
		}

		// Update OpenGL light direction
		Vector3 lightDir = (lightPos - camera->focus).normalized();
		float ldir[] = {
			static_cast<float>(lightDir.x),
			static_cast<float>(lightDir.y),
			static_cast<float>(lightDir.z),
			0.0f};
		glLightfv(GL_LIGHT0, GL_POSITION, ldir);
	}

	// ------------------------------------------------------------------------
	void Renderer::PrepareForRenderable(int objectId, Renderable *renderable)
	{
	}

	// ------------------------------------------------------------------------
	void Renderer::DrawRenderables()
	{
		if (!view) return;

		// Iterate over all renderables in the scene and draw them
		for (int objectId = 0; objectId < view->GetNumberOfRenderables();
			++objectId)
		{
			// Visibility implies that the renderable is not null
			if (view->GetVisibility(objectId))
			{
				Renderable *renderable = view->GetRenderable(objectId);
				PrepareForRenderable(objectId, renderable);
				renderable->Draw();
			}
		}
	}

	// ------------------------------------------------------------------------
	void Renderer::DrawTexture(GLTexture *tex,
			double xmin, double xmax, double ymin, double ymax)
	{
		if (!tex) return;

		glPushAttrib(GL_ALL_ATTRIB_BITS);

		glColor3d(1.0, 1.0, 1.0);
		glDisable(GL_DEPTH_TEST);
		glMatrixMode(GL_TEXTURE);
		glLoadIdentity();
		glMatrixMode(GL_MODELVIEW);
		tex->BindToCurrent();
		glEnable(tex->GetTextureTarget());
		if (tex->GetTextureTarget() == GL_TEXTURE_RECTANGLE_ARB)
		{
			glBegin(GL_QUADS);
			glTexCoord2d(0.0, 0.0);
			glVertex3d(xmin, ymin, 0.0);
			glTexCoord2d(tex->GetWidth(), 0.0);
			glVertex3d(xmax, ymin, 0.0);
			glTexCoord2d(tex->GetWidth(), tex->GetHeight());
			glVertex3d(xmax, ymax, 0.0);
			glTexCoord2d(0.0, tex->GetHeight());
			glVertex3d(xmin, ymax, 0.0);
			glEnd();
		}
		else
		{
			glBegin(GL_QUADS);
			glTexCoord2d(0.0, 0.0);
			glVertex3d(xmin, ymin, 0.0);
			glTexCoord2d(1.0, 0.0);
			glVertex3d(xmax, ymin, 0.0);
			glTexCoord2d(1.0, 1.0);
			glVertex3d(xmax, ymax, 0.0);
			glTexCoord2d(0.0, 1.0);
			glVertex3d(xmin, ymax, 0.0);
			glEnd();
		}
		glDisable(tex->GetTextureTarget());
		tex->UnbindCurrent();

		glPopAttrib();
	}
}
<|endoftext|>


<commit_before>#include "BinaryTree.h"

template<class Node> Tree<Node>::Tree()
{
	root->x = 0;
	root->left = root->right = NULL;
}
template<class Node> Tree<Node>::Tree(Node* node)
{
	root->x = node->x;
	root->left = node->left;
	root->right = node->right;
}
template<class Node> Tree<Node>::Tree(const Tree &node)
{
	root->x = node.root->x;
	root->left = node.root->left;
	root->right = node.root->right;
}
template<class Node> int Tree<Node>::x_()const
{
	return root->x;
}
template<class Node> Node* Tree<Node>::left_()const
{
	return root->left;
}
template<class Node> Node* Tree<Node>::right_()const
{
	return root->right;
}
template<class Node> void Tree<Node>::add(Node* newEl)
{
	Node* El = NULL;
	Node* curEl = root;
	while (curEl != NULL)
	{
		El = curEl;
		if (newEl->x >= curEl->x)
			curEl = curEl->right;
		else
			curEl = curEl->left;
	}
	if (newEl->x >= El->x)
		El->right = newEl;
	else
		El->left = newEl;
}
template<class Node> Tree Tree<Node>::search(int x)
{
	Node* curEl = root;
	while (curEl != NULL)
	{
		if (curEl->x == x)
			return curEl;
		else
		{
			if (x >= curEl->x)
				curEl = curEl->right;
			else
				curEl = curEl->left;
		}
	}
	return nullptr;
}
template<class Node> void Tree<Node>::fIn(string filename)
{
	ifstream fin;
	fin.open(filename);
	Node* newEl = NULL;
	if (!fin.is_open())
		cout << "The file isn't find" << endl;
	if (fin.eof()) return;
	else fin >> root->x;
	while (!fin.eof())
	{
		fin >> newEl->x;
		add(newEl);
	}
	fin.close();
}
template<class Node> void Tree<Node>::fOut(string filename)const
{
	ofstream fout;
	fout.open(filename);
	Out(root);
	fout.close();
}
template<class Node> void Tree<Node>::Out(Node* curEl)const
{
	curEl = root;
	if (curEl != NULL)
	{
		cout << curEl->x;
		Out(curEl->left);
		Out(curEl->right);
	}
}
<commit_msg>Update BinaryTree.cpp<commit_after>#include "BinaryTree.h"

template<class Node> Tree<Node>::Tree()
{
	root->x = 0;
	root->left = root->right = NULL;
}
template<class Node> Tree<Node>::Tree(Node* node)
{
	root->x = node->x;
	root->left = node->left;
	root->right = node->right;
}
template<class Node> Tree<Node>::Tree(const Tree &node)
{
	root->x = node.root->x;
	root->left = node.root->left;
	root->right = node.root->right;
}
template<class Node> int Tree<Node>::x_()const
{
	return root->x;
}
template<class Node> Node* Tree<Node>::left_()const
{
	return root->left;
}
template<class Node> Node* Tree<Node>::right_()const
{
	return root->right;
}
template<class Node> void Tree<Node>::add(Node* newEl)
{
	Node* El = NULL;
	Node* curEl = root;
	while (curEl != NULL)
	{
		El = curEl;
		if (newEl->x >= curEl->x)
			curEl = curEl->right;
		else
			curEl = curEl->left;
	}
	if (newEl->x >= El->x)
		El->right = newEl;
	else
		El->left = newEl;
}
template<class Node> Tree Tree<Node>::search(int x)
{
	Node* curEl = root;
	while (curEl != NULL)
	{
		if (curEl->x == x)
			return curEl;
		else
		{
			if (x >= curEl->x)
				curEl = curEl->right;
			else
				curEl = curEl->left;
		}
	}
	return nullptr;
}
template<class Node> void Tree<Node>::fIn(string filename)
{
	ifstream fin;
	fin.open(filename);
	Node* newEl = NULL;
	if (!fin.is_open())
		cout << "The file isn't find" << endl;
	if (fin.eof()) return;
	else fin >> root->x;
	while (!fin.eof())
	{
		fin >> newEl->x;
		add(newEl);
	}
	fin.close();
}
template<class Node> void Tree<Node>::fOut(string filename)const
{
	ofstream fout;
	fout.open(filename);
	Out(root);
	fout.close();
}
template<class Node> void Tree<Node>::Out(Node* curEl)const
{
	curEl = root;
	if (curEl != NULL)
	{
		cout << curEl->x << endl;
		Out(curEl->left);
		Out(curEl->right);
	}
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2008, Image Engine Design Inc. 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 Image Engine Design nor the names of any
//       other contributors to this software 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 OWNER 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 <boost/python.hpp>
#include <cassert>

#include "boost/static_assert.hpp"

#include "IECore/LineSegment.h"
#include "IECore/bindings/LineSegmentBinding.h"

using namespace boost::python;

namespace IECore
{

template<class L>
static const char *typeName()
{
	BOOST_STATIC_ASSERT( sizeof(L) == 0 );
	return "";
}

template<>
static const char *typeName<LineSegment2f>()
{
	return "LineSegment2f";
}

template<>
static const char *typeName<LineSegment2d>()
{
	return "LineSegment2d";
}

template<>
static const char *typeName<LineSegment3f>()
{
	return "LineSegment3f";
}

template<>
static const char *typeName<LineSegment3d>()
{
	return "LineSegment3d";
}

template<class L>
static std::string repr( L &x )
{
	std::stringstream s;

	s << "IECore." << typeName<L>() << "( ";

	object item0( x.p0 );
	assert( item.attr0( "__repr__" ) != object() );
	s << call_method< std::string >( item0.ptr(), "__repr__" ) << ", ";

	object item1( x.p1 );
	assert( item.attr1( "__repr__" ) != object() );
	s << call_method< std::string >( item1.ptr(), "__repr__" ) << " )";

	return s.str();
}

template<class L>
static tuple closestPoints( const L &l, const L &l2 )
{
	typename L::Point a, b;
	a = l.closestPoints( l2, b );
	return make_tuple( a, b );
}

template<typename Vec>
static void bind3D()
{
	typedef typename Vec::BaseType BaseType;
	typedef LineSegment<Vec> L;
	typedef Imath::Matrix44<BaseType> M;

	const char *name = typeName< L >();

	class_<L>( name )
		.def( init<L>() )
		.def( init<Vec, Vec>() )
		.def_readwrite( "p0", &L::p0 )
		.def_readwrite( "p1", &L::p1 )
		.def( "__repr__", &repr<L> )
		.def( "__call__", &L::operator() )
		.def( "direction", &L::direction )
		.def( "normalizedDirection", &L::normalizedDirection )
		.def( "length", &L::length )
		.def( "length2", &L::length2 )
		.def( "closestPointTo", &L::closestPointTo )
		.def( "closestPoints", &closestPoints<L> )
		.def( "distanceTo", (typename L::BaseType (L::*)( const Vec & ) const)&L::distanceTo )
		.def( "distanceTo", (typename L::BaseType (L::*)( const L & ) const)&L::distanceTo )
		.def( "distance2To", (typename L::BaseType (L::*)( const Vec & ) const)&L::distance2To )
		.def( "distance2To", (typename L::BaseType (L::*)( const L & ) const)&L::distance2To )
		.def( self *= M() )
		.def( self * M() )
		.def( self == self )
		.def( self != self )
		/// \todo Bind the intersect methods when we have a binding for ImathPlane
	;

}

template<typename Vec>
static void bind2D()
{
	typedef typename Vec::BaseType BaseType;
	typedef LineSegment<Vec> L;
	typedef Imath::Matrix33<BaseType> M;

	const char *name = typeName< L >();

	class_<L>( name )
		.def( init<L>() )
		.def( init<Vec, Vec>() )
		.def_readwrite( "p0", &L::p0 )
		.def_readwrite( "p1", &L::p1 )
		.def( "__repr__", &repr<L> )
		.def( "__call__", &L::operator() )
		.def( "direction", &L::direction )
		.def( "normalizedDirection", &L::normalizedDirection )
		.def( "length", &L::length )
		.def( "length2", &L::length2 )
		.def( "closestPointTo", &L::closestPointTo )
		.def( "distanceTo", (typename L::BaseType (L::*)( const Vec & ) const)&L::distanceTo )
		.def( "distance2To", (typename L::BaseType (L::*)( const Vec & ) const)&L::distance2To )
		.def( self *= M() )
		.def( self * M() )
		.def( self == self )
		.def( self != self )
	;

}

void bindLineSegment()
{
	bind3D<Imath::V3f>();
	bind3D<Imath::V3d>();
	bind2D<Imath::V2f>();
	bind2D<Imath::V2d>();
}

} // namespace IECore
<commit_msg>Fixed typos.<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2008, Image Engine Design Inc. 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 Image Engine Design nor the names of any
//       other contributors to this software 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 OWNER 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 <boost/python.hpp>
#include <cassert>

#include "boost/static_assert.hpp"

#include "IECore/LineSegment.h"
#include "IECore/bindings/LineSegmentBinding.h"

using namespace boost::python;

namespace IECore
{

template<class L>
static const char *typeName()
{
	BOOST_STATIC_ASSERT( sizeof(L) == 0 );
	return "";
}

template<>
static const char *typeName<LineSegment2f>()
{
	return "LineSegment2f";
}

template<>
static const char *typeName<LineSegment2d>()
{
	return "LineSegment2d";
}

template<>
static const char *typeName<LineSegment3f>()
{
	return "LineSegment3f";
}

template<>
static const char *typeName<LineSegment3d>()
{
	return "LineSegment3d";
}

template<class L>
static std::string repr( L &x )
{
	std::stringstream s;

	s << "IECore." << typeName<L>() << "( ";

	object item0( x.p0 );
	assert( item0.attr( "__repr__" ) != object() );
	s << call_method< std::string >( item0.ptr(), "__repr__" ) << ", ";

	object item1( x.p1 );
	assert( item1.attr( "__repr__" ) != object() );
	s << call_method< std::string >( item1.ptr(), "__repr__" ) << " )";

	return s.str();
}

template<class L>
static tuple closestPoints( const L &l, const L &l2 )
{
	typename L::Point a, b;
	a = l.closestPoints( l2, b );
	return make_tuple( a, b );
}

template<typename Vec>
static void bind3D()
{
	typedef typename Vec::BaseType BaseType;
	typedef LineSegment<Vec> L;
	typedef Imath::Matrix44<BaseType> M;

	const char *name = typeName< L >();

	class_<L>( name )
		.def( init<L>() )
		.def( init<Vec, Vec>() )
		.def_readwrite( "p0", &L::p0 )
		.def_readwrite( "p1", &L::p1 )
		.def( "__repr__", &repr<L> )
		.def( "__call__", &L::operator() )
		.def( "direction", &L::direction )
		.def( "normalizedDirection", &L::normalizedDirection )
		.def( "length", &L::length )
		.def( "length2", &L::length2 )
		.def( "closestPointTo", &L::closestPointTo )
		.def( "closestPoints", &closestPoints<L> )
		.def( "distanceTo", (typename L::BaseType (L::*)( const Vec & ) const)&L::distanceTo )
		.def( "distanceTo", (typename L::BaseType (L::*)( const L & ) const)&L::distanceTo )
		.def( "distance2To", (typename L::BaseType (L::*)( const Vec & ) const)&L::distance2To )
		.def( "distance2To", (typename L::BaseType (L::*)( const L & ) const)&L::distance2To )
		.def( self *= M() )
		.def( self * M() )
		.def( self == self )
		.def( self != self )
		/// \todo Bind the intersect methods when we have a binding for ImathPlane
	;

}

template<typename Vec>
static void bind2D()
{
	typedef typename Vec::BaseType BaseType;
	typedef LineSegment<Vec> L;
	typedef Imath::Matrix33<BaseType> M;

	const char *name = typeName< L >();

	class_<L>( name )
		.def( init<L>() )
		.def( init<Vec, Vec>() )
		.def_readwrite( "p0", &L::p0 )
		.def_readwrite( "p1", &L::p1 )
		.def( "__repr__", &repr<L> )
		.def( "__call__", &L::operator() )
		.def( "direction", &L::direction )
		.def( "normalizedDirection", &L::normalizedDirection )
		.def( "length", &L::length )
		.def( "length2", &L::length2 )
		.def( "closestPointTo", &L::closestPointTo )
		.def( "distanceTo", (typename L::BaseType (L::*)( const Vec & ) const)&L::distanceTo )
		.def( "distance2To", (typename L::BaseType (L::*)( const Vec & ) const)&L::distance2To )
		.def( self *= M() )
		.def( self * M() )
		.def( self == self )
		.def( self != self )
	;

}

void bindLineSegment()
{
	bind3D<Imath::V3f>();
	bind3D<Imath::V3d>();
	bind2D<Imath::V2f>();
	bind2D<Imath::V2d>();
}

} // namespace IECore
<|endoftext|>


<commit_before><commit_msg>Sketcher: [skip ci] fix computing of hotspot of sketcher icons on macOS<commit_after><|endoftext|>


<commit_before>#include "Railfence.h"

/**
 * Sets the key to use
 * @param key - the key to use
 * @return - True if the key is valid and False otherwise
 */
bool Railfence::setKey(const string& mykey)
{ 	// validate the key, check if its empty
	if ((!mykey.empty()))
	{
		key = atoi(mykey.c_str());
		return true;
	}
	else
		return false;
}

/**
 * Encrypts a plaintext string
 * @param plaintext - the plaintext string
 * @return - the encrypted ciphertext string
 */
string Railfence::encrypt(const string& plaintext)
{
	string ciphertext = "";

	vector<string> ctext(key, ""); // To contain the letters in the string for Railfence

	for (unsigned int i = 0; i < plaintext.size(); i++)
	{
		ctext.at(i % key).push_back(plaintext.at(i)); // Repeat and loop through each vector string and pushback a character
	}

	for (vector<string>::iterator it = ctext.begin(); it != ctext.end(); ++it)
	{
		ciphertext.append(*it); // Concatenate all the strings in order
	}

	return ciphertext;
}

/**
 * Decrypts a string of ciphertext
 * @param cipherText - the ciphertext
 * @return - the plaintext
 */
string Railfence::decrypt(const string& cipherText)
{
	string plaintext = "";

	vector<string> ptext(key, ""); // To contain the letters in the string for Railfence

	int textlength = cipherText.size() / key; // Store length of the string that is split by the size of the key
	int remainder = cipherText.size() % key; // Used to fill the remaining characters onto the first row
	int stringcount = 0;

	ptext.at(0).append(cipherText.substr(0,textlength + remainder)); // Append the first row with the remainder
	stringcount = textlength + remainder;

	for (unsigned int i = 1; i < key; i++)
	{
		ptext.at(i).append(cipherText.substr(stringcount,textlength)); // Append each vector row with the string split by key (textlength)
		stringcount += textlength;
	}

	// Go through every vector element, check if string is not empty, push back the first character and erase it.
	for (unsigned int i = 0; i <= textlength; i++)
	{
		for (unsigned int j = 0; j < key; j++)
		{
			if (!ptext.at(j).empty())
			{
				plaintext.push_back(ptext.at(j).at(0));
				ptext.at(j).erase(0,1);
			}
		}
	}

	return plaintext;
}
<commit_msg>Railfence - Fixed bug length<commit_after>#include "Railfence.h"

/**
 * Sets the key to use
 * @param key - the key to use
 * @return - True if the key is valid and False otherwise
 */
bool Railfence::setKey(const string& mykey)
{ 	// validate the key, check if its empty
	if ((!mykey.empty()))
	{
		key = atoi(mykey.c_str());
		return true;
	}
	else
		return false;
}

/**
 * Encrypts a plaintext string
 * @param plaintext - the plaintext string
 * @return - the encrypted ciphertext string
 */
string Railfence::encrypt(const string& plaintext)
{
	string ciphertext = "";

	vector<string> ctext(key, ""); // To contain the letters in the string for Railfence

	for (unsigned int i = 0; i < plaintext.size(); i++)
	{
		ctext.at(i % key).push_back(plaintext.at(i)); // Repeat and loop through each vector string and pushback a character
	}

	for (vector<string>::iterator it = ctext.begin(); it != ctext.end(); ++it)
	{
		ciphertext.append(*it); // Concatenate all the strings in order
	}

	return ciphertext;
}

/**
 * Decrypts a string of ciphertext
 * @param cipherText - the ciphertext
 * @return - the plaintext
 */
string Railfence::decrypt(const string& cipherText)
{
	string plaintext = "";

	vector<string> ptext(key, ""); // To contain the letters in the string for Railfence

	int textlength = cipherText.size() / key; // Store length of the string that is split by the size of the key
	int remainder = cipherText.size() % key; // Used to fill the remaining characters onto the first row
	int stringcount = 0;

	ptext.at(0).append(cipherText.substr(0,textlength + remainder)); // Append the first row with the remainder
	stringcount = textlength + remainder;

	for (unsigned int i = 1; i < key; i++)
	{
		ptext.at(i).append(cipherText.substr(stringcount,textlength)); // Append each vector row with the string split by key (textlength)
		stringcount += textlength;
	}

	// Go through every vector element, check if string is not empty, push back the first character and erase it.
	for (unsigned int i = 0; i < textlength + remainder; i++)
	{
		for (unsigned int j = 0; j < key; j++)
		{
			if (!ptext.at(j).empty())
			{
				plaintext.push_back(ptext.at(j).at(0));
				ptext.at(j).erase(0,1);
			}
		}
	}

	return plaintext;
}
<|endoftext|>


<commit_before>{
  TProof::Open("pod://");
  if (!gProof) return;

  TDSet *manual_dset = new TDSet("TTree", "deuterons");
  TString user[3] = {"m/mpuccio","m/masera","s/sbufalin"};
  for (int i = 0; i < 3; ++i)
  {
    TString ddset = Form("Find;BasePath=/alice/cern.ch/user/%s/NucleiPbPb2011test/output;FileName=*/root_archive.zip;Anchor=mpuccio_Flowdnt.root;Tree=/deuterons;Mode=local",user[i].Data());

    TFileCollection *fc = gProof->GetDataSet(ddset.Data());

  // Create TDSet manually (terrible hack): apparently PROOF is stupid
  // and cannot create it correctly
    TFileInfo *fi;
    TIter next( fc->GetList() );
    while (( fi = (TFileInfo *)next() )) {
      const char *fn = fi->GetCurrentUrl()->GetUrl();
      Printf("adding: %s", fn);
      manual_dset->Add( fn );
    }
  }

  gSystem->Load("AODSelector.cxx++g");

  const double kCent[5] = {0.,10.,20.,40.,60.};
  const double kBins[29] = {
    0.4f,0.5f,0.6f,0.7f,0.8f,0.9f,1.0f,1.1f,1.2f,1.4f,
    1.6f,1.8f,2.0f,2.2f,2.4f,2.6f,2.8f,3.0f,3.2f,3.4f,
    3.6f,3.8f,4.0f,4.2f,4.4f,5.0f,6.0f,8.0f,10.f
  };
  AODSelector *sel = new AODSelector();
  sel->SetPtBins(29,kBins);
  sel->SetCentBins(5,kCent);
  sel->SetOutputOption("deuterons3cent",kTRUE);
  // Process the TDset
  gProof->Process(manual_dset, sel);

}
<commit_msg>Correct way to invoke macro compilation<commit_after>{
  TProof::Open("pod://");
  if (!gProof) return;

  TDSet *manual_dset = new TDSet("TTree", "deuterons");
  TString user[3] = {"m/mpuccio","m/masera","s/sbufalin"};
  for (int i = 0; i < 3; ++i)
  {
    TString ddset = Form("Find;BasePath=/alice/cern.ch/user/%s/NucleiPbPb2011test/output;FileName=*/root_archive.zip;Anchor=mpuccio_Flowdnt.root;Tree=/deuterons;Mode=local",user[i].Data());

    TFileCollection *fc = gProof->GetDataSet(ddset.Data());

  // Create TDSet manually (terrible hack): apparently PROOF is stupid
  // and cannot create it correctly
    TFileInfo *fi;
    TIter next( fc->GetList() );
    while (( fi = (TFileInfo *)next() )) {
      const char *fn = fi->GetCurrentUrl()->GetUrl();
      Printf("adding: %s", fn);
      manual_dset->Add( fn );
    }
  }

  gROOT->LoadMacro("AODSelector.cxx++g");

  const double kCent[5] = {0.,10.,20.,40.,60.};
  const double kBins[29] = {
    0.4f,0.5f,0.6f,0.7f,0.8f,0.9f,1.0f,1.1f,1.2f,1.4f,
    1.6f,1.8f,2.0f,2.2f,2.4f,2.6f,2.8f,3.0f,3.2f,3.4f,
    3.6f,3.8f,4.0f,4.2f,4.4f,5.0f,6.0f,8.0f,10.f
  };
  AODSelector *sel = new AODSelector();
  sel->SetPtBins(29,kBins);
  sel->SetCentBins(5,kCent);
  sel->SetOutputOption("deuterons3cent",kTRUE);
  // Process the TDset
  gProof->Process(manual_dset, sel);

}
<|endoftext|>


<commit_before>// File:      SalomeApp_PreferencesDlg.cxx
// Author:    Sergey TELKOV

#include "SalomeApp_PreferencesDlg.h"

#include "SalomeApp_Preferences.h"

#include <qvbox.h>
#include <qlayout.h>

/*!
  Constructor.
*/
SalomeApp_PreferencesDlg::SalomeApp_PreferencesDlg( SalomeApp_Preferences* prefs, QWidget* parent )
: QtxDialog( parent, 0, true, false, OK | Close | Apply ),
myPrefs( prefs )
{
  setCaption( tr( "CAPTION" ) );

  QVBoxLayout* main = new QVBoxLayout( mainFrame(), 5 );

  QVBox* base = new QVBox( mainFrame() );
  main->addWidget( base );

  myPrefs->reparent( base, QPoint( 0, 0 ), true );

  setFocusProxy( myPrefs );

  setButtonPosition( Right, Close );

  setDialogFlags( AlignOnce );

  connect( this, SIGNAL( dlgHelp() ),  this, SLOT( onHelp() ) );
  connect( this, SIGNAL( dlgApply() ), this, SLOT( onApply() ) );
}

/*!
  Destructor.
*/
SalomeApp_PreferencesDlg::~SalomeApp_PreferencesDlg()
{
  if ( !myPrefs )
    return;

  myPrefs->reparent( 0, QPoint( 0, 0 ), false );
  myPrefs = 0;
}

/*!Show dialog.*/
void SalomeApp_PreferencesDlg::show()
{
  myPrefs->retrieve();
  myPrefs->toBackup();

  QtxDialog::show();
}

/*!Store preferences on accept.*/
void SalomeApp_PreferencesDlg::accept()
{
  QtxDialog::accept();

  myPrefs->store();
}

/*!Reject. Restore preferences from backup.*/
void SalomeApp_PreferencesDlg::reject()
{
  QtxDialog::reject();

  myPrefs->fromBackup();
}

/*!Do nothing.*/
void SalomeApp_PreferencesDlg::onHelp()
{
}

/*!Store preferences on apply.*/
void SalomeApp_PreferencesDlg::onApply()
{
  myPrefs->store();
}
<commit_msg>PAL10121 - apply in preferences dialog didn't work<commit_after>// File:      SalomeApp_PreferencesDlg.cxx
// Author:    Sergey TELKOV

#include "SalomeApp_PreferencesDlg.h"

#include "SalomeApp_Preferences.h"

#include <qvbox.h>
#include <qlayout.h>

/*!
  Constructor.
*/
SalomeApp_PreferencesDlg::SalomeApp_PreferencesDlg( SalomeApp_Preferences* prefs, QWidget* parent )
: QtxDialog( parent, 0, true, false, OK | Close | Apply ),
myPrefs( prefs )
{
  setCaption( tr( "CAPTION" ) );

  QVBoxLayout* main = new QVBoxLayout( mainFrame(), 5 );

  QVBox* base = new QVBox( mainFrame() );
  main->addWidget( base );

  myPrefs->reparent( base, QPoint( 0, 0 ), true );

  setFocusProxy( myPrefs );

  setButtonPosition( Right, Close );

  setDialogFlags( AlignOnce );

  connect( this, SIGNAL( dlgHelp() ),  this, SLOT( onHelp() ) );
  connect( this, SIGNAL( dlgApply() ), this, SLOT( onApply() ) );
}

/*!
  Destructor.
*/
SalomeApp_PreferencesDlg::~SalomeApp_PreferencesDlg()
{
  if ( !myPrefs )
    return;

  myPrefs->reparent( 0, QPoint( 0, 0 ), false );
  myPrefs = 0;
}

/*!Show dialog.*/
void SalomeApp_PreferencesDlg::show()
{
  myPrefs->retrieve();
  myPrefs->toBackup();

  QtxDialog::show();
}

/*!Store preferences on accept.*/
void SalomeApp_PreferencesDlg::accept()
{
  QtxDialog::accept();

  myPrefs->store();
}

/*!Reject. Restore preferences from backup.*/
void SalomeApp_PreferencesDlg::reject()
{
  QtxDialog::reject();

  myPrefs->fromBackup();
}

/*!Do nothing.*/
void SalomeApp_PreferencesDlg::onHelp()
{
}

/*!Store preferences on apply.*/
void SalomeApp_PreferencesDlg::onApply()
{
  myPrefs->store();
  myPrefs->toBackup();
}
<|endoftext|>


<commit_before>/********************************************************************
 * Copyright © 2016 Computational Molecular Biology Group,          *
 *                  Freie Universität Berlin (GER)                  *
 *                                                                  *
 * This file is part of ReaDDy.                                     *
 *                                                                  *
 * ReaDDy is free software: you can redistribute it and/or modify   *
 * it under the terms of the GNU Lesser General Public License as   *
 * published by the Free Software Foundation, either version 3 of   *
 * the License, or (at your option) any later version.              *
 *                                                                  *
 * This program is distributed in the hope that it will be useful,  *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
 * GNU Lesser General Public License for more details.              *
 *                                                                  *
 * You should have received a copy of the GNU Lesser General        *
 * Public License along with this program. If not, see              *
 * <http://www.gnu.org/licenses/>.                                  *
 ********************************************************************/

/**
 * @file CPUCalculateForces.cpp
 * @author clonker
 * @date 1/3/18
 */

#include "readdy/kernel/cpu/actions/CPUCalculateForces.h"

namespace readdy {
namespace kernel {
namespace cpu {
namespace actions {

void CPUCalculateForces::perform(const util::PerformanceNode &node) {
    auto t = node.timeit();

    const auto &ctx = kernel->context();

    auto &stateModel = kernel->getCPUKernelStateModel();
    auto neighborList = stateModel.getNeighborList();
    auto data = stateModel.getParticleData();
    auto taf = kernel->getTopologyActionFactory();
    auto &topologies = stateModel.topologies();

    stateModel.energy() = 0;
    stateModel.virial() = Matrix33{{{0, 0, 0, 0, 0, 0, 0, 0, 0}}};

    const auto &potOrder1 = ctx.potentials().potentialsOrder1();
    const auto &potOrder2 = ctx.potentials().potentialsOrder2();
    if (!potOrder1.empty() || !potOrder2.empty() || !stateModel.topologies().empty()) {
        {
            // todo maybe optimize this by transposing data structure
            auto tClear = node.subnode("clear forces").timeit();
            std::for_each(data->begin(), data->end(), [](auto &entry) {
                entry.force = {0, 0, 0};
            });
        }
        {
            auto &pool = data->pool();
            std::vector<std::promise<scalar>> promises;
            std::vector<std::promise<Matrix33>> virialPromises;
            // 1st order pot + topologies = 2*pool size
            // 2nd order pot <= nl.nCells
            size_t nThreads = pool.size();
            auto numberTasks = (!potOrder1.empty() ? nThreads : 0)
                               + (!potOrder2.empty() ? nThreads : 0)
                               + (!topologies.empty() ? nThreads : 0);
            {
                const auto &nTasks = node.subnode("create tasks");
                auto tTasks = nTasks.timeit();
                size_t nCells = neighborList->nCells();
                promises.reserve(numberTasks);
                virialPromises.reserve(!potOrder2.empty() ? nThreads : 0);
                if (!potOrder1.empty()) {
                    // 1st order pot
                    auto tO1 = nTasks.subnode("order1").timeit();
                    std::vector<std::function<void(std::size_t)>> tasks;
                    tasks.reserve(nThreads);

                    const std::size_t grainSize = data->size() / nThreads;
                    auto it = data->begin();
                    for (auto i = 0_z; i < nThreads - 1; ++i) {
                        auto itNext = std::min(it + grainSize, data->end());
                        if (it != itNext) {
                            promises.emplace_back();
                            auto dataBounds = std::make_tuple(it, itNext);
                            tasks.push_back(pool.pack(calculate_order1, dataBounds, std::ref(promises.back()), data,
                                                      ctx.potentials().potentialsOrder1(),
                                                      ctx.shortestDifferenceFun()));
                        }
                        it = itNext;
                    }
                    if (it != data->end()) {
                        promises.emplace_back();
                        auto dataBounds = std::make_tuple(it, data->end());
                        tasks.push_back(pool.pack(calculate_order1, dataBounds, std::ref(promises.back()), data,
                                                  ctx.potentials().potentialsOrder1(), ctx.shortestDifferenceFun()));
                    }
                    {
                        auto tPush = nTasks.subnode("execute order 1 tasks and wait").timeit();
                        auto futures = pool.pushAll(std::move(tasks));
                        std::vector<util::thread::joining_future<void>> joiningFutures;
                        std::transform(futures.begin(), futures.end(), std::back_inserter(joiningFutures),
                                       [](auto &&future) {
                                           return util::thread::joining_future<void>{std::move(future)};
                                       });
                    }
                }
                if (!topologies.empty()) {
                    auto tTops = nTasks.subnode("topologies").timeit();
                    std::vector<std::function<void(std::size_t)>> tasks;
                    tasks.reserve(nThreads);
                    const std::size_t grainSize = topologies.size() / nThreads;
                    auto it = topologies.cbegin();
                    for (auto i = 0_z; i < nThreads - 1; ++i) {
                        auto itNext = std::min(it + grainSize, topologies.cend());
                        if (it != itNext) {
                            promises.emplace_back();
                            auto bounds = std::make_tuple(it, itNext);
                            tasks.push_back(
                                    pool.pack(calculate_topologies, bounds, taf, std::ref(promises.back())));
                        }
                        it = itNext;
                    }
                    if (it != topologies.cend()) {
                        promises.emplace_back();
                        auto bounds = std::make_tuple(it, topologies.cend());
                        tasks.push_back(pool.pack(calculate_topologies, bounds, taf, std::ref(promises.back())));
                    }
                    {
                        auto tPush = nTasks.subnode("execute topology tasks and wait").timeit();
                        auto futures = pool.pushAll(std::move(tasks));
                        std::vector<util::thread::joining_future<void>> joiningFutures;
                        std::transform(futures.begin(), futures.end(), std::back_inserter(joiningFutures),
                                       [](auto &&future) {
                                           return util::thread::joining_future<void>{std::move(future)};
                                       });
                    }
                }
                if (!potOrder2.empty()) {
                    auto tO2 = nTasks.subnode("order2").timeit();
                    std::vector<std::function<void(std::size_t)>> tasks;
                    tasks.reserve(nThreads);
                    auto granularity = nThreads;
                    const std::size_t grainSize = nCells / granularity;
                    auto it = 0_z;
                    for (auto i = 0_z; i < granularity - 1; ++i) {
                        auto itNext = std::min(it + grainSize, nCells);
                        if (it != itNext) {
                            promises.emplace_back();
                            virialPromises.emplace_back();
                            if(ctx.recordVirial()) {
                                tasks.push_back(pool.pack(
                                        calculate_order2<true>, std::make_tuple(it, itNext), data,
                                        std::cref(*neighborList), std::ref(promises.back()),
                                        std::ref(virialPromises.back()), ctx.potentials().potentialsOrder2(),
                                        ctx.shortestDifferenceFun()
                                ));
                            } else {
                                tasks.push_back(pool.pack(
                                        calculate_order2<false>, std::make_tuple(it, itNext), data,
                                        std::cref(*neighborList), std::ref(promises.back()),
                                        std::ref(virialPromises.back()), ctx.potentials().potentialsOrder2(),
                                        ctx.shortestDifferenceFun()
                                ));
                            }
                        }
                        it = itNext;
                    }
                    if (it != nCells) {
                        promises.emplace_back();
                        virialPromises.emplace_back();
                        if(ctx.recordVirial()) {
                            tasks.push_back(pool.pack(
                                    calculate_order2<true>, std::make_tuple(it, nCells), data, std::cref(*neighborList),
                                    std::ref(promises.back()), std::ref(virialPromises.back()),
                                    ctx.potentials().potentialsOrder2(), ctx.shortestDifferenceFun()
                            ));
                        } else {
                            tasks.push_back(pool.pack(
                                    calculate_order2<false>, std::make_tuple(it, nCells), data, std::cref(*neighborList),
                                    std::ref(promises.back()), std::ref(virialPromises.back()),
                                    ctx.potentials().potentialsOrder2(), ctx.shortestDifferenceFun()
                            ));
                        }
                    }
                    {
                        auto tPush = nTasks.subnode("execute order 2 tasks and wait").timeit();
                        auto futures = pool.pushAll(std::move(tasks));
                        std::vector<util::thread::joining_future<void>> joiningFutures;
                        std::transform(futures.begin(), futures.end(), std::back_inserter(joiningFutures),
                                       [](auto &&future) {
                                           return util::thread::joining_future<void>{std::move(future)};
                                       });
                    }
                }
            }

            {
                auto tFutures = node.subnode("get energy futures").timeit();
                for (auto &f : promises) {
                    stateModel.energy() += f.get_future().get();
                }
            }
            {
                auto tVirialFutures = node.subnode("get virial futures").timeit();
                for (auto &f : virialPromises) {
                    stateModel.virial() += f.get_future().get();
                }
            }
        }
    }
}

template<bool COMPUTE_VIRIAL>
void CPUCalculateForces::calculate_order2(std::size_t, nl_bounds nlBounds,
                                          CPUStateModel::data_type *data, const CPUStateModel::neighbor_list &nl,
                                          std::promise<scalar> &energyPromise, std::promise<Matrix33> &virialPromise,
                                          model::potentials::PotentialRegistry::potential_o2_registry pot2,
                                          model::Context::shortest_dist_fun d) {
    scalar energyUpdate = 0.0;
    Matrix33 virialUpdate{{{0, 0, 0, 0, 0, 0, 0, 0, 0}}};

    //
    // 2nd order potentials
    //
    for (auto cell = std::get<0>(nlBounds); cell < std::get<1>(nlBounds); ++cell) {
        for (auto particleIt = nl.particlesBegin(cell); particleIt != nl.particlesEnd(cell); ++particleIt) {
            auto &entry = data->entry_at(*particleIt);
            if (entry.deactivated) {
                log::critical("deactivated particle in neighbor list!");
                continue;
            }

            nl.forEachNeighbor(*particleIt, cell, [&](auto neighborIndex) {
                auto &neighbor = data->entry_at(neighborIndex);
                if (!neighbor.deactivated) {
                    auto &force = entry.force;
                    const auto &myPos = entry.pos;

                    //
                    // 2nd order potentials
                    //
                    scalar mySecondOrderEnergy = 0.;
                    auto potit = pot2.find(std::tie(entry.type, neighbor.type));
                    if (potit != pot2.end()) {
                        auto x_ij = d(myPos, neighbor.pos);
                        auto distSquared = x_ij * x_ij;
                        for (const auto &potential : potit->second) {
                            if (distSquared < potential->getCutoffRadiusSquared()) {
                                Vec3 forceUpdate{0, 0, 0};
                                potential->calculateForceAndEnergy(forceUpdate, mySecondOrderEnergy, x_ij);
                                force += forceUpdate;
                                if(COMPUTE_VIRIAL && *particleIt < neighborIndex) {
                                    virialUpdate += math::outerProduct(-1.*x_ij, force);
                                }
                            }
                        }
                    }

                    // The contribution of second order potentials must be halved since we parallelize over particles.
                    // Thus every particle pair potential is seen twice
                    energyUpdate += 0.5 * mySecondOrderEnergy;
                } else {
                    log::critical("disabled neighbour");
                }
            });
        }

    }

    energyPromise.set_value(energyUpdate);
    virialPromise.set_value(virialUpdate);

}

void CPUCalculateForces::calculate_topologies(std::size_t, top_bounds topBounds,
                                              model::top::TopologyActionFactory *taf,
                                              std::promise<scalar> &energyPromise) {
    scalar energyUpdate = 0.0;
    for (auto it = std::get<0>(topBounds); it != std::get<1>(topBounds); ++it) {
        const auto &top = *it;
        if (!top->isDeactivated()) {
            for (const auto &bondedPot : top->getBondedPotentials()) {
                auto energy = bondedPot->createForceAndEnergyAction(taf)->perform(top.get());
                energyUpdate += energy;
            }
            for (const auto &anglePot : top->getAnglePotentials()) {
                auto energy = anglePot->createForceAndEnergyAction(taf)->perform(top.get());
                energyUpdate += energy;
            }
            for (const auto &torsionPot : top->getTorsionPotentials()) {
                auto energy = torsionPot->createForceAndEnergyAction(taf)->perform(top.get());
                energyUpdate += energy;
            }
        }
    }

    energyPromise.set_value(energyUpdate);
}

void CPUCalculateForces::calculate_order1(std::size_t, data_bounds dataBounds,
                                          std::promise<scalar> &energyPromise, CPUStateModel::data_type *data,
                                          model::potentials::PotentialRegistry::potential_o1_registry pot1,
                                          model::Context::shortest_dist_fun d) {
    scalar energyUpdate = 0.0;

    //
    // 1st order potentials
    //
    for (auto it = std::get<0>(dataBounds); it != std::get<1>(dataBounds); ++it) {
        auto &entry = *it;
        if (!entry.deactivated) {
            auto &force = entry.force;
            force = {c_::zero, c_::zero, c_::zero};
            const auto &myPos = entry.pos;
            auto find_it = pot1.find(entry.type);
            if (find_it != pot1.end()) {
                for (const auto &potential : find_it->second) {
                    potential->calculateForceAndEnergy(force, energyUpdate, myPos);
                }
            }
        }
    }
    energyPromise.set_value(energyUpdate);
}
}
}
}
}
<commit_msg>fix in virial computation<commit_after>/********************************************************************
 * Copyright © 2016 Computational Molecular Biology Group,          *
 *                  Freie Universität Berlin (GER)                  *
 *                                                                  *
 * This file is part of ReaDDy.                                     *
 *                                                                  *
 * ReaDDy is free software: you can redistribute it and/or modify   *
 * it under the terms of the GNU Lesser General Public License as   *
 * published by the Free Software Foundation, either version 3 of   *
 * the License, or (at your option) any later version.              *
 *                                                                  *
 * This program is distributed in the hope that it will be useful,  *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
 * GNU Lesser General Public License for more details.              *
 *                                                                  *
 * You should have received a copy of the GNU Lesser General        *
 * Public License along with this program. If not, see              *
 * <http://www.gnu.org/licenses/>.                                  *
 ********************************************************************/

/**
 * @file CPUCalculateForces.cpp
 * @author clonker
 * @date 1/3/18
 */

#include "readdy/kernel/cpu/actions/CPUCalculateForces.h"

namespace readdy {
namespace kernel {
namespace cpu {
namespace actions {

void CPUCalculateForces::perform(const util::PerformanceNode &node) {
    auto t = node.timeit();

    const auto &ctx = kernel->context();

    auto &stateModel = kernel->getCPUKernelStateModel();
    auto neighborList = stateModel.getNeighborList();
    auto data = stateModel.getParticleData();
    auto taf = kernel->getTopologyActionFactory();
    auto &topologies = stateModel.topologies();

    stateModel.energy() = 0;
    stateModel.virial() = Matrix33{{{0, 0, 0, 0, 0, 0, 0, 0, 0}}};

    const auto &potOrder1 = ctx.potentials().potentialsOrder1();
    const auto &potOrder2 = ctx.potentials().potentialsOrder2();
    if (!potOrder1.empty() || !potOrder2.empty() || !stateModel.topologies().empty()) {
        {
            // todo maybe optimize this by transposing data structure
            auto tClear = node.subnode("clear forces").timeit();
            std::for_each(data->begin(), data->end(), [](auto &entry) {
                entry.force = {0, 0, 0};
            });
        }
        {
            auto &pool = data->pool();
            std::vector<std::promise<scalar>> promises;
            std::vector<std::promise<Matrix33>> virialPromises;
            // 1st order pot + topologies = 2*pool size
            // 2nd order pot <= nl.nCells
            size_t nThreads = pool.size();
            auto numberTasks = (!potOrder1.empty() ? nThreads : 0)
                               + (!potOrder2.empty() ? nThreads : 0)
                               + (!topologies.empty() ? nThreads : 0);
            {
                const auto &nTasks = node.subnode("create tasks");
                auto tTasks = nTasks.timeit();
                size_t nCells = neighborList->nCells();
                promises.reserve(numberTasks);
                virialPromises.reserve(!potOrder2.empty() ? nThreads : 0);
                if (!potOrder1.empty()) {
                    // 1st order pot
                    auto tO1 = nTasks.subnode("order1").timeit();
                    std::vector<std::function<void(std::size_t)>> tasks;
                    tasks.reserve(nThreads);

                    const std::size_t grainSize = data->size() / nThreads;
                    auto it = data->begin();
                    for (auto i = 0_z; i < nThreads - 1; ++i) {
                        auto itNext = std::min(it + grainSize, data->end());
                        if (it != itNext) {
                            promises.emplace_back();
                            auto dataBounds = std::make_tuple(it, itNext);
                            tasks.push_back(pool.pack(calculate_order1, dataBounds, std::ref(promises.back()), data,
                                                      ctx.potentials().potentialsOrder1(),
                                                      ctx.shortestDifferenceFun()));
                        }
                        it = itNext;
                    }
                    if (it != data->end()) {
                        promises.emplace_back();
                        auto dataBounds = std::make_tuple(it, data->end());
                        tasks.push_back(pool.pack(calculate_order1, dataBounds, std::ref(promises.back()), data,
                                                  ctx.potentials().potentialsOrder1(), ctx.shortestDifferenceFun()));
                    }
                    {
                        auto tPush = nTasks.subnode("execute order 1 tasks and wait").timeit();
                        auto futures = pool.pushAll(std::move(tasks));
                        std::vector<util::thread::joining_future<void>> joiningFutures;
                        std::transform(futures.begin(), futures.end(), std::back_inserter(joiningFutures),
                                       [](auto &&future) {
                                           return util::thread::joining_future<void>{std::move(future)};
                                       });
                    }
                }
                if (!topologies.empty()) {
                    auto tTops = nTasks.subnode("topologies").timeit();
                    std::vector<std::function<void(std::size_t)>> tasks;
                    tasks.reserve(nThreads);
                    const std::size_t grainSize = topologies.size() / nThreads;
                    auto it = topologies.cbegin();
                    for (auto i = 0_z; i < nThreads - 1; ++i) {
                        auto itNext = std::min(it + grainSize, topologies.cend());
                        if (it != itNext) {
                            promises.emplace_back();
                            auto bounds = std::make_tuple(it, itNext);
                            tasks.push_back(
                                    pool.pack(calculate_topologies, bounds, taf, std::ref(promises.back())));
                        }
                        it = itNext;
                    }
                    if (it != topologies.cend()) {
                        promises.emplace_back();
                        auto bounds = std::make_tuple(it, topologies.cend());
                        tasks.push_back(pool.pack(calculate_topologies, bounds, taf, std::ref(promises.back())));
                    }
                    {
                        auto tPush = nTasks.subnode("execute topology tasks and wait").timeit();
                        auto futures = pool.pushAll(std::move(tasks));
                        std::vector<util::thread::joining_future<void>> joiningFutures;
                        std::transform(futures.begin(), futures.end(), std::back_inserter(joiningFutures),
                                       [](auto &&future) {
                                           return util::thread::joining_future<void>{std::move(future)};
                                       });
                    }
                }
                if (!potOrder2.empty()) {
                    auto tO2 = nTasks.subnode("order2").timeit();
                    std::vector<std::function<void(std::size_t)>> tasks;
                    tasks.reserve(nThreads);
                    auto granularity = nThreads;
                    const std::size_t grainSize = nCells / granularity;
                    auto it = 0_z;
                    for (auto i = 0_z; i < granularity - 1; ++i) {
                        auto itNext = std::min(it + grainSize, nCells);
                        if (it != itNext) {
                            promises.emplace_back();
                            virialPromises.emplace_back();
                            if(ctx.recordVirial()) {
                                tasks.push_back(pool.pack(
                                        calculate_order2<true>, std::make_tuple(it, itNext), data,
                                        std::cref(*neighborList), std::ref(promises.back()),
                                        std::ref(virialPromises.back()), ctx.potentials().potentialsOrder2(),
                                        ctx.shortestDifferenceFun()
                                ));
                            } else {
                                tasks.push_back(pool.pack(
                                        calculate_order2<false>, std::make_tuple(it, itNext), data,
                                        std::cref(*neighborList), std::ref(promises.back()),
                                        std::ref(virialPromises.back()), ctx.potentials().potentialsOrder2(),
                                        ctx.shortestDifferenceFun()
                                ));
                            }
                        }
                        it = itNext;
                    }
                    if (it != nCells) {
                        promises.emplace_back();
                        virialPromises.emplace_back();
                        if(ctx.recordVirial()) {
                            tasks.push_back(pool.pack(
                                    calculate_order2<true>, std::make_tuple(it, nCells), data, std::cref(*neighborList),
                                    std::ref(promises.back()), std::ref(virialPromises.back()),
                                    ctx.potentials().potentialsOrder2(), ctx.shortestDifferenceFun()
                            ));
                        } else {
                            tasks.push_back(pool.pack(
                                    calculate_order2<false>, std::make_tuple(it, nCells), data, std::cref(*neighborList),
                                    std::ref(promises.back()), std::ref(virialPromises.back()),
                                    ctx.potentials().potentialsOrder2(), ctx.shortestDifferenceFun()
                            ));
                        }
                    }
                    {
                        auto tPush = nTasks.subnode("execute order 2 tasks and wait").timeit();
                        auto futures = pool.pushAll(std::move(tasks));
                        std::vector<util::thread::joining_future<void>> joiningFutures;
                        std::transform(futures.begin(), futures.end(), std::back_inserter(joiningFutures),
                                       [](auto &&future) {
                                           return util::thread::joining_future<void>{std::move(future)};
                                       });
                    }
                }
            }

            {
                auto tFutures = node.subnode("get energy futures").timeit();
                for (auto &f : promises) {
                    stateModel.energy() += f.get_future().get();
                }
            }
            {
                auto tVirialFutures = node.subnode("get virial futures").timeit();
                for (auto &f : virialPromises) {
                    stateModel.virial() += f.get_future().get();
                }
            }
        }
    }
}

template<bool COMPUTE_VIRIAL>
void CPUCalculateForces::calculate_order2(std::size_t, nl_bounds nlBounds,
                                          CPUStateModel::data_type *data, const CPUStateModel::neighbor_list &nl,
                                          std::promise<scalar> &energyPromise, std::promise<Matrix33> &virialPromise,
                                          model::potentials::PotentialRegistry::potential_o2_registry pot2,
                                          model::Context::shortest_dist_fun d) {
    scalar energyUpdate = 0.0;
    Matrix33 virialUpdate{{{0, 0, 0, 0, 0, 0, 0, 0, 0}}};

    //
    // 2nd order potentials
    //
    for (auto cell = std::get<0>(nlBounds); cell < std::get<1>(nlBounds); ++cell) {
        for (auto particleIt = nl.particlesBegin(cell); particleIt != nl.particlesEnd(cell); ++particleIt) {
            auto &entry = data->entry_at(*particleIt);
            if (entry.deactivated) {
                log::critical("deactivated particle in neighbor list!");
                continue;
            }

            nl.forEachNeighbor(*particleIt, cell, [&](auto neighborIndex) {
                auto &neighbor = data->entry_at(neighborIndex);
                if (!neighbor.deactivated) {
                    auto &force = entry.force;
                    const auto &myPos = entry.pos;

                    //
                    // 2nd order potentials
                    //
                    scalar mySecondOrderEnergy = 0.;
                    auto potit = pot2.find(std::tie(entry.type, neighbor.type));
                    if (potit != pot2.end()) {
                        auto x_ij = d(myPos, neighbor.pos);
                        auto distSquared = x_ij * x_ij;
                        for (const auto &potential : potit->second) {
                            if (distSquared < potential->getCutoffRadiusSquared()) {
                                Vec3 forceUpdate{0, 0, 0};
                                potential->calculateForceAndEnergy(forceUpdate, mySecondOrderEnergy, x_ij);
                                force += forceUpdate;
                                if(COMPUTE_VIRIAL && *particleIt < neighborIndex) {
                                    virialUpdate += math::outerProduct(-1.*x_ij, forceUpdate);
                                }
                            }
                        }
                    }

                    // The contribution of second order potentials must be halved since we parallelize over particles.
                    // Thus every particle pair potential is seen twice
                    energyUpdate += 0.5 * mySecondOrderEnergy;
                } else {
                    log::critical("disabled neighbour");
                }
            });
        }

    }

    energyPromise.set_value(energyUpdate);
    virialPromise.set_value(virialUpdate);

}

void CPUCalculateForces::calculate_topologies(std::size_t, top_bounds topBounds,
                                              model::top::TopologyActionFactory *taf,
                                              std::promise<scalar> &energyPromise) {
    scalar energyUpdate = 0.0;
    for (auto it = std::get<0>(topBounds); it != std::get<1>(topBounds); ++it) {
        const auto &top = *it;
        if (!top->isDeactivated()) {
            for (const auto &bondedPot : top->getBondedPotentials()) {
                auto energy = bondedPot->createForceAndEnergyAction(taf)->perform(top.get());
                energyUpdate += energy;
            }
            for (const auto &anglePot : top->getAnglePotentials()) {
                auto energy = anglePot->createForceAndEnergyAction(taf)->perform(top.get());
                energyUpdate += energy;
            }
            for (const auto &torsionPot : top->getTorsionPotentials()) {
                auto energy = torsionPot->createForceAndEnergyAction(taf)->perform(top.get());
                energyUpdate += energy;
            }
        }
    }

    energyPromise.set_value(energyUpdate);
}

void CPUCalculateForces::calculate_order1(std::size_t, data_bounds dataBounds,
                                          std::promise<scalar> &energyPromise, CPUStateModel::data_type *data,
                                          model::potentials::PotentialRegistry::potential_o1_registry pot1,
                                          model::Context::shortest_dist_fun d) {
    scalar energyUpdate = 0.0;

    //
    // 1st order potentials
    //
    for (auto it = std::get<0>(dataBounds); it != std::get<1>(dataBounds); ++it) {
        auto &entry = *it;
        if (!entry.deactivated) {
            auto &force = entry.force;
            force = {c_::zero, c_::zero, c_::zero};
            const auto &myPos = entry.pos;
            auto find_it = pot1.find(entry.type);
            if (find_it != pot1.end()) {
                for (const auto &potential : find_it->second) {
                    potential->calculateForceAndEnergy(force, energyUpdate, myPos);
                }
            }
        }
    }
    energyPromise.set_value(energyUpdate);
}
}
}
}
}
<|endoftext|>


<commit_before>#pragma once

//std
#include <algorithm>

//glm
#include <glm\glm.hpp>
#include <glm\ext.hpp>

//mandala
#include "collision.hpp"
#include "input_event.hpp"
#include "gui_node.hpp"
#include "gpu.hpp"

#if defined(DEBUG)
#include "line_renderer.hpp"
#endif

namespace mandala
{
    void gui_node_t::orphan()
    {
        if (parent.get() == nullptr)
        {
            throw std::exception("cannot orphan a node with no parent");
        }

        auto parent_children_itr = std::find(parent->children.begin(), parent->children.end(), parent);

        if (parent_children_itr == parent->children.end())
        {
            throw std::exception("parent does not have this node as a child");
        }

        //remove node from parent's child list
        parent->children.erase(parent_children_itr);

        //TODO: might be able to forego dirtying parent if removing this node doesn't
        //affect positioning of sibling elements or sizing of parent element
        //if (dock_mode != gui_dock_mode_e::NONE)

        //mark parent as dirty
        parent->dirty();

        //unparent
        parent = nullptr;

        //uproot
        root = nullptr;

        //mark as dirty
        dirty();
    }

    void gui_node_t::adopt(const boost::shared_ptr<gui_node_t>& node)
    {
        if (node == nullptr)
        {
            throw std::invalid_argument("node cannot be null");
        }

        if (node.get() == this)
        {
            throw std::invalid_argument("nodes cannot adopt themselves");
        }

        if (node->has_parent())
        {
            //orphan node from parent
            node->orphan();
        }

        const auto children_itr = std::find(children.begin(), children.end(), node);

        if (children_itr != children.end())
        {
            throw std::exception("node is already a child");
        }

        //add node to child list
        children.push_back(node);

        //set node's new parent
        node->parent = shared_from_this();

        //set node's new root
        node->root = root ? root : shared_from_this();

        //mark as dirty
        dirty();
    }

    void gui_node_t::clean()
    {
        std::function<void(boost::shared_ptr<gui_node_t>&, aabb2_t&)> clean_node = [&clean_node](boost::shared_ptr<gui_node_t>& node, aabb2_t& sibling_bounds)
        {
            node->on_clean_begin();

            auto absolute_desired_size = node->desired_size;

            if (node->get_size_modes_real().get_x() == gui_size_mode_e::RELATIVE)
            {
                if (node->has_parent())
                {
                    absolute_desired_size.x *= node->parent->bounds.size().x - node->parent->padding.horizontal();
                }
                else
                {
                    absolute_desired_size.x *= sibling_bounds.size().x;
                }
            }

            if (node->get_size_modes_real().get_y() == gui_size_mode_e::RELATIVE)
            {
                if (node->has_parent())
                {
                    absolute_desired_size.y *= node->parent->bounds.size().y - node->parent->padding.vertical();
                }
                else
                {
                    absolute_desired_size.y *= sibling_bounds.size().y;
                }
            }

            if (node->get_size_modes_real().get_x() == gui_size_mode_e::AXIS_SCALE)
            {
                switch (node->dock_mode)
                {
                case gui_dock_mode_e::LEFT:
                case gui_dock_mode_e::RIGHT:
                    absolute_desired_size.x = sibling_bounds.height() * node->desired_size.x;
                    break;
                case gui_dock_mode_e::NONE:
                    absolute_desired_size.x *= absolute_desired_size.y;
                    break;
                default:
                    break;
                }
            }
            else if (node->get_size_modes_real().get_y() == gui_size_mode_e::AXIS_SCALE)
            {
                switch (node->dock_mode)
                {
                case gui_dock_mode_e::BOTTOM:
                case gui_dock_mode_e::TOP:
                    absolute_desired_size.y = sibling_bounds.width() * node->desired_size.y;
                    break;
                case gui_dock_mode_e::NONE:
                    absolute_desired_size.y *= absolute_desired_size.x;
                    break;
                default:
                    break;
                }
            }

            switch (node->dock_mode)
            {
            case gui_dock_mode_e::BOTTOM:
                node->bounds.min = sibling_bounds.min;
                node->bounds.max.x = sibling_bounds.max.x;
                node->bounds.max.y = sibling_bounds.min.y + absolute_desired_size.y + node->padding.vertical();

                node->bounds -= node->margin;

                sibling_bounds.min.y += node->bounds.height() + node->margin.vertical();

                break;
            case gui_dock_mode_e::FILL:
                node->bounds = sibling_bounds - node->margin;

                break;
            case gui_dock_mode_e::LEFT:
                node->bounds.min = sibling_bounds.min;
                node->bounds.max.x = sibling_bounds.min.x + absolute_desired_size.x + node->padding.horizontal();
                node->bounds.max.y = sibling_bounds.max.y;

                node->bounds -= node->margin;

                sibling_bounds.min.x += node->bounds.width() + node->margin.horizontal();

                break;
            case gui_dock_mode_e::RIGHT:
                node->bounds.min.x = sibling_bounds.max.x - absolute_desired_size.x - node->padding.horizontal();
                node->bounds.min.y = sibling_bounds.min.y;
                node->bounds.max = sibling_bounds.max;

                node->bounds -= node->margin;

                sibling_bounds.max.x -= node->bounds.width() + node->margin.horizontal();

                break;
            case gui_dock_mode_e::TOP:
                node->bounds.min.x = sibling_bounds.min.x;
                node->bounds.min.y = sibling_bounds.max.y - absolute_desired_size.y - node->padding.vertical();
                node->bounds.max = sibling_bounds.max;

                node->bounds -= node->margin;

                sibling_bounds.max.y -= node->bounds.height() + node->margin.vertical();

                break;
            default:
                node->bounds.min = vec2_t(0);
                node->bounds.max = absolute_desired_size;

                if (node->has_parent())
                {
                    node->bounds += vec2_t(node->parent->padding.left, node->parent->padding.bottom);
                }

                vec2_t anchor_location;
                vec2_t anchor_translation;

                if ((node->anchor_flags & GUI_ANCHOR_FLAG_HORIZONTAL) == GUI_ANCHOR_FLAG_HORIZONTAL)
                {
                    anchor_location.x = (sibling_bounds.max.x - sibling_bounds.min.x) / 2;
                    anchor_translation.x = -((absolute_desired_size.x / 2) + ((node->margin.right - node->margin.left) / 2));
                }
                else
                {
                    if ((node->anchor_flags & GUI_ANCHOR_FLAG_LEFT) == GUI_ANCHOR_FLAG_LEFT)
                    {
                        anchor_location.x = sibling_bounds.min.x;
                        anchor_translation.x = node->margin.left;
                    }
                    else if ((node->anchor_flags & GUI_ANCHOR_FLAG_RIGHT) == GUI_ANCHOR_FLAG_RIGHT)
                    {
                        anchor_location.x = sibling_bounds.max.x;
                        anchor_translation.x = -(absolute_desired_size.x + node->margin.right);
                    }
                }

                if ((node->anchor_flags & GUI_ANCHOR_FLAG_VERTICAL) == GUI_ANCHOR_FLAG_VERTICAL)
                {
                    anchor_location.y = (sibling_bounds.max.y - sibling_bounds.min.y) / 2;
                    anchor_translation.y = -((absolute_desired_size.y / 2) + ((node->margin.top - node->margin.bottom) / 2));
                }
                else
                {
                    if ((node->anchor_flags & GUI_ANCHOR_FLAG_BOTTOM) == GUI_ANCHOR_FLAG_BOTTOM)
                    {
                        anchor_location.y = sibling_bounds.min.y;
                        anchor_translation.y = node->margin.bottom;
                    }
                    else if ((node->anchor_flags & GUI_ANCHOR_FLAG_TOP) == GUI_ANCHOR_FLAG_TOP)
                    {
                        anchor_location.y = sibling_bounds.max.y;
                        anchor_translation.y = -(absolute_desired_size.y + node->margin.top);
                    }
                }

                node->bounds += anchor_location + anchor_translation + node->anchor_offset;

                break;
            }

            node->size = node->bounds.size();

            auto children_bounds = node->bounds - node->padding;

            for (auto child : node->children)
            {
                clean_node(child, children_bounds);
            }

            node->is_dirty = false;

            node->on_clean_end();
        };

        //HACK: something is amiss with this way of doing things.
        //margins can be accumulated with every tick unless we
        //pad the bounds passed into clean_node. this seems incorrect,
        //but will work for now.
        auto padded_bounds = bounds + margin;

        clean_node(shared_from_this(), padded_bounds);
    }

    void gui_node_t::tick(float32_t dt)
    {
        on_tick_begin(dt);

        for (auto child : children)
        {
            child->tick(dt);
        }

        on_tick_end(dt);
    }

    bool gui_node_t::on_input_event(input_event_t& input_event)
    {
        for (auto children_itr = children.begin(); children_itr != children.end(); ++children_itr)
        {
            if ((*children_itr)->on_input_event(input_event))
            {
                return true;
            }
        }

        return false;
    }

    const gui_size_modes_t gui_node_t::get_size_modes_real() const
    {
        auto real_size_modes = size_modes;

        if (real_size_modes.get_x() == gui_size_mode_e::INHERIT)
        {
            if (parent)
            {
                real_size_modes.set_x(parent->get_size_modes_real().get_x());
            }
            else
            {
                real_size_modes.set_x(gui_size_mode_e::ABSOLUTE);
            }
        }

        if (real_size_modes.get_y() == gui_size_mode_e::INHERIT)
        {
            if (parent)
            {
                real_size_modes.set_y(parent->get_size_modes_real().get_y());
            }
            else
            {
                real_size_modes.set_y(gui_size_mode_e::ABSOLUTE);
            }
        }

        return real_size_modes;
    }

    void gui_node_t::dirty()
    {
        if (is_dirty)
        {
            return;
        }

        is_dirty = true;

        if (parent)
        {
            parent->dirty();
        }
    }

    void gui_node_t::render(mat4_t world_matrix, mat4_t view_projection_matrix)
    {
        if (is_hidden)
        {
            return;
        }

        //TODO: debug rendering?

        bool should_clip = this->should_clip;    //temporary variable in case value changes during render calls somehow

        if (should_clip)
        {
            //stencil
            auto gpu_stencil_state = gpu.stencil.get_state();

            gpu_stencil_state.is_enabled = true;

            gpu_stencil_state.function.func = gpu_t::stencil_function_e::NEVER;
            gpu_stencil_state.function.ref = 1;
            gpu_stencil_state.function.mask = 0xFF;

            gpu_stencil_state.operations.fail = gpu_t::stencil_operation_e::REPLACE;
            gpu_stencil_state.operations.zfail = gpu_t::stencil_operation_e::KEEP;
            gpu_stencil_state.operations.zpass = gpu_t::stencil_operation_e::KEEP;

            gpu_stencil_state.mask = 0xFF;

            gpu.stencil.push_state(gpu_stencil_state);

            //color
            auto gpu_color_state = gpu.color.get_state();

            gpu_color_state.mask.r = false;
            gpu_color_state.mask.g = false;
            gpu_color_state.mask.b = false;
            gpu_color_state.mask.a = false;

            gpu.color.push_state(gpu_color_state);

            //depth
            auto gpu_depth_state = gpu.depth.get_state();

            gpu_depth_state.should_write_mask = false;

            gpu.depth.push_state(gpu_depth_state);

            gpu.clear(gpu_t::CLEAR_FLAG_DEPTH | gpu_t::CLEAR_FLAG_STENCIL);

            render_rectangle(world_matrix, view_projection_matrix, rectangle_t(bounds), true);

            gpu.color.pop_state();
            gpu.depth.pop_state();

            gpu_stencil_state.mask = 0;
            gpu_stencil_state.function.func = gpu_t::stencil_function_e::NOTEQUAL;
            gpu_stencil_state.function.ref = 0;
            gpu_stencil_state.function.mask = 0xFF;

            gpu.stencil.pop_state();
            gpu.stencil.push_state(gpu_stencil_state);
        }

        //TODO: configure this to be enable-able in-game
#if defined(DEBUG)
        render_rectangle(world_matrix, view_projection_matrix, rectangle_t(bounds));
#endif

        on_render_begin(world_matrix, view_projection_matrix);

        for (auto& child : children)
        {
            child->render(world_matrix, view_projection_matrix);
        }

        on_render_end(world_matrix, view_projection_matrix);

        if (should_clip)
        {
            gpu.stencil.pop_state();
        }
    }
}
<commit_msg>fix for bad anchoring when using horizontal or vertical anchor flags<commit_after>#pragma once

//std
#include <algorithm>

//glm
#include <glm\glm.hpp>
#include <glm\ext.hpp>

//mandala
#include "collision.hpp"
#include "input_event.hpp"
#include "gui_node.hpp"
#include "gpu.hpp"

#if defined(DEBUG)
#include "line_renderer.hpp"
#endif

namespace mandala
{
    void gui_node_t::orphan()
    {
        if (parent.get() == nullptr)
        {
            throw std::exception("cannot orphan a node with no parent");
        }

        auto parent_children_itr = std::find(parent->children.begin(), parent->children.end(), parent);

        if (parent_children_itr == parent->children.end())
        {
            throw std::exception("parent does not have this node as a child");
        }

        //remove node from parent's child list
        parent->children.erase(parent_children_itr);

        //TODO: might be able to forego dirtying parent if removing this node doesn't
        //affect positioning of sibling elements or sizing of parent element
        //if (dock_mode != gui_dock_mode_e::NONE)

        //mark parent as dirty
        parent->dirty();

        //unparent
        parent = nullptr;

        //uproot
        root = nullptr;

        //mark as dirty
        dirty();
    }

    void gui_node_t::adopt(const boost::shared_ptr<gui_node_t>& node)
    {
        if (node == nullptr)
        {
            throw std::invalid_argument("node cannot be null");
        }

        if (node.get() == this)
        {
            throw std::invalid_argument("nodes cannot adopt themselves");
        }

        if (node->has_parent())
        {
            //orphan node from parent
            node->orphan();
        }

        const auto children_itr = std::find(children.begin(), children.end(), node);

        if (children_itr != children.end())
        {
            throw std::exception("node is already a child");
        }

        //add node to child list
        children.push_back(node);

        //set node's new parent
        node->parent = shared_from_this();

        //set node's new root
        node->root = root ? root : shared_from_this();

        //mark as dirty
        dirty();
    }

    void gui_node_t::clean()
    {
        std::function<void(boost::shared_ptr<gui_node_t>&, aabb2_t&)> clean_node = [&clean_node](boost::shared_ptr<gui_node_t>& node, aabb2_t& sibling_bounds)
        {
            node->on_clean_begin();

            auto absolute_desired_size = node->desired_size;

            if (node->get_size_modes_real().get_x() == gui_size_mode_e::RELATIVE)
            {
                if (node->has_parent())
                {
                    absolute_desired_size.x *= node->parent->bounds.size().x - node->parent->padding.horizontal();
                }
                else
                {
                    absolute_desired_size.x *= sibling_bounds.size().x;
                }
            }

            if (node->get_size_modes_real().get_y() == gui_size_mode_e::RELATIVE)
            {
                if (node->has_parent())
                {
                    absolute_desired_size.y *= node->parent->bounds.size().y - node->parent->padding.vertical();
                }
                else
                {
                    absolute_desired_size.y *= sibling_bounds.size().y;
                }
            }

            if (node->get_size_modes_real().get_x() == gui_size_mode_e::AXIS_SCALE)
            {
                switch (node->dock_mode)
                {
                case gui_dock_mode_e::LEFT:
                case gui_dock_mode_e::RIGHT:
                    absolute_desired_size.x = sibling_bounds.height() * node->desired_size.x;
                    break;
                case gui_dock_mode_e::NONE:
                    absolute_desired_size.x *= absolute_desired_size.y;
                    break;
                default:
                    break;
                }
            }
            else if (node->get_size_modes_real().get_y() == gui_size_mode_e::AXIS_SCALE)
            {
                switch (node->dock_mode)
                {
                case gui_dock_mode_e::BOTTOM:
                case gui_dock_mode_e::TOP:
                    absolute_desired_size.y = sibling_bounds.width() * node->desired_size.y;
                    break;
                case gui_dock_mode_e::NONE:
                    absolute_desired_size.y *= absolute_desired_size.x;
                    break;
                default:
                    break;
                }
            }

            switch (node->dock_mode)
            {
            case gui_dock_mode_e::BOTTOM:
                node->bounds.min = sibling_bounds.min;
                node->bounds.max.x = sibling_bounds.max.x;
                node->bounds.max.y = sibling_bounds.min.y + absolute_desired_size.y + node->padding.vertical();

                node->bounds -= node->margin;

                sibling_bounds.min.y += node->bounds.height() + node->margin.vertical();

                break;
            case gui_dock_mode_e::FILL:
                node->bounds = sibling_bounds - node->margin;

                break;
            case gui_dock_mode_e::LEFT:
                node->bounds.min = sibling_bounds.min;
                node->bounds.max.x = sibling_bounds.min.x + absolute_desired_size.x + node->padding.horizontal();
                node->bounds.max.y = sibling_bounds.max.y;

                node->bounds -= node->margin;

                sibling_bounds.min.x += node->bounds.width() + node->margin.horizontal();

                break;
            case gui_dock_mode_e::RIGHT:
                node->bounds.min.x = sibling_bounds.max.x - absolute_desired_size.x - node->padding.horizontal();
                node->bounds.min.y = sibling_bounds.min.y;
                node->bounds.max = sibling_bounds.max;

                node->bounds -= node->margin;

                sibling_bounds.max.x -= node->bounds.width() + node->margin.horizontal();

                break;
            case gui_dock_mode_e::TOP:
                node->bounds.min.x = sibling_bounds.min.x;
                node->bounds.min.y = sibling_bounds.max.y - absolute_desired_size.y - node->padding.vertical();
                node->bounds.max = sibling_bounds.max;

                node->bounds -= node->margin;

                sibling_bounds.max.y -= node->bounds.height() + node->margin.vertical();

                break;
            default:
                node->bounds.min = vec2_t(0);
                node->bounds.max = absolute_desired_size;

                vec2_t anchor_location;
                vec2_t anchor_translation;

                if ((node->anchor_flags & GUI_ANCHOR_FLAG_HORIZONTAL) == GUI_ANCHOR_FLAG_HORIZONTAL)
                {
                    anchor_location.x = sibling_bounds.min.x + (sibling_bounds.width() / 2);
                    anchor_translation.x = -((absolute_desired_size.x / 2) + ((node->margin.right - node->margin.left) / 2));
                }
                else
                {
                    if ((node->anchor_flags & GUI_ANCHOR_FLAG_LEFT) == GUI_ANCHOR_FLAG_LEFT)
                    {
                        anchor_location.x = sibling_bounds.min.x;
                        anchor_translation.x = node->margin.left;
                    }
                    else if ((node->anchor_flags & GUI_ANCHOR_FLAG_RIGHT) == GUI_ANCHOR_FLAG_RIGHT)
                    {
                        anchor_location.x = sibling_bounds.max.x;
                        anchor_translation.x = -(absolute_desired_size.x + node->margin.right);
                    }
                }

                if ((node->anchor_flags & GUI_ANCHOR_FLAG_VERTICAL) == GUI_ANCHOR_FLAG_VERTICAL)
                {
                    anchor_location.y = sibling_bounds.min.y + (sibling_bounds.height() / 2);
                    anchor_translation.y = -((absolute_desired_size.y / 2) + ((node->margin.top - node->margin.bottom) / 2));
                }
                else
                {
                    if ((node->anchor_flags & GUI_ANCHOR_FLAG_BOTTOM) == GUI_ANCHOR_FLAG_BOTTOM)
                    {
                        anchor_location.y = sibling_bounds.min.y;
                        anchor_translation.y = node->margin.bottom;
                    }
                    else if ((node->anchor_flags & GUI_ANCHOR_FLAG_TOP) == GUI_ANCHOR_FLAG_TOP)
                    {
                        anchor_location.y = sibling_bounds.max.y;
                        anchor_translation.y = -(absolute_desired_size.y + node->margin.top);
                    }
                }

                node->bounds += anchor_location + anchor_translation + node->anchor_offset;

                break;
            }

            node->size = node->bounds.size();

            auto children_bounds = node->bounds - node->padding;

            for (auto child : node->children)
            {
                clean_node(child, children_bounds);
            }

            node->is_dirty = false;

            node->on_clean_end();
        };

        //HACK: something is amiss with this way of doing things.
        //margins can be accumulated with every tick unless we
        //pad the bounds passed into clean_node. this seems incorrect,
        //but will work for now.
        auto padded_bounds = bounds + margin;

        clean_node(shared_from_this(), padded_bounds);
    }

    void gui_node_t::tick(float32_t dt)
    {
        on_tick_begin(dt);

        for (auto child : children)
        {
            child->tick(dt);
        }

        on_tick_end(dt);
    }

    bool gui_node_t::on_input_event(input_event_t& input_event)
    {
        for (auto children_itr = children.begin(); children_itr != children.end(); ++children_itr)
        {
            if ((*children_itr)->on_input_event(input_event))
            {
                return true;
            }
        }

        return false;
    }

    const gui_size_modes_t gui_node_t::get_size_modes_real() const
    {
        auto real_size_modes = size_modes;

        if (real_size_modes.get_x() == gui_size_mode_e::INHERIT)
        {
            if (parent)
            {
                real_size_modes.set_x(parent->get_size_modes_real().get_x());
            }
            else
            {
                real_size_modes.set_x(gui_size_mode_e::ABSOLUTE);
            }
        }

        if (real_size_modes.get_y() == gui_size_mode_e::INHERIT)
        {
            if (parent)
            {
                real_size_modes.set_y(parent->get_size_modes_real().get_y());
            }
            else
            {
                real_size_modes.set_y(gui_size_mode_e::ABSOLUTE);
            }
        }

        return real_size_modes;
    }

    void gui_node_t::dirty()
    {
        if (is_dirty)
        {
            return;
        }

        is_dirty = true;

        if (parent)
        {
            parent->dirty();
        }
    }

    void gui_node_t::render(mat4_t world_matrix, mat4_t view_projection_matrix)
    {
        if (is_hidden)
        {
            return;
        }

        //TODO: debug rendering?

        bool should_clip = this->should_clip;    //temporary variable in case value changes during render calls somehow

        if (should_clip)
        {
            //stencil
            auto gpu_stencil_state = gpu.stencil.get_state();

            gpu_stencil_state.is_enabled = true;

            gpu_stencil_state.function.func = gpu_t::stencil_function_e::NEVER;
            gpu_stencil_state.function.ref = 1;
            gpu_stencil_state.function.mask = 0xFF;

            gpu_stencil_state.operations.fail = gpu_t::stencil_operation_e::REPLACE;
            gpu_stencil_state.operations.zfail = gpu_t::stencil_operation_e::KEEP;
            gpu_stencil_state.operations.zpass = gpu_t::stencil_operation_e::KEEP;

            gpu_stencil_state.mask = 0xFF;

            gpu.stencil.push_state(gpu_stencil_state);

            //color
            auto gpu_color_state = gpu.color.get_state();

            gpu_color_state.mask.r = false;
            gpu_color_state.mask.g = false;
            gpu_color_state.mask.b = false;
            gpu_color_state.mask.a = false;

            gpu.color.push_state(gpu_color_state);

            //depth
            auto gpu_depth_state = gpu.depth.get_state();

            gpu_depth_state.should_write_mask = false;

            gpu.depth.push_state(gpu_depth_state);

            gpu.clear(gpu_t::CLEAR_FLAG_DEPTH | gpu_t::CLEAR_FLAG_STENCIL);

            render_rectangle(world_matrix, view_projection_matrix, rectangle_t(bounds), true);

            gpu.color.pop_state();
            gpu.depth.pop_state();

            gpu_stencil_state.mask = 0;
            gpu_stencil_state.function.func = gpu_t::stencil_function_e::NOTEQUAL;
            gpu_stencil_state.function.ref = 0;
            gpu_stencil_state.function.mask = 0xFF;

            gpu.stencil.pop_state();
            gpu.stencil.push_state(gpu_stencil_state);
        }

        //TODO: configure this to be enable-able in-game
#if defined(DEBUG)
        render_rectangle(world_matrix, view_projection_matrix, rectangle_t(bounds));
#endif

        on_render_begin(world_matrix, view_projection_matrix);

        for (auto& child : children)
        {
            child->render(world_matrix, view_projection_matrix);
        }

        on_render_end(world_matrix, view_projection_matrix);

        if (should_clip)
        {
            gpu.stencil.pop_state();
        }
    }
}
<|endoftext|>