<commit_before>/*
	Copyright (c) 2013-2014 Sam Hardeman

	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	THE SOFTWARE.
*/

#include "Modules.h"
#include "OpCodeHandler.h"
#include "NetworkControl.h"
#include "PacketSender.h"
#include "Packet.h"
#include "Client.h"

#include "IceNetServer.h"
#include "IceNetTypedefs.h"

#include <time.h>

namespace IceNet
{
	unsigned short RandomID( void )
	{
		unsigned short id = 0;

		while ( 1 )
		{
			id = rand() & USHRT_MAX;
			if ( id <= 256 ) continue;

			break;
		}

		return id;
	}

	THREAD_FUNC ListenerEntry( void* ptr )
	{
		srand( (unsigned int) time( 0 ) );
		rand();

		while ( true )
		{
			// Poll for stop condition
			if ( NetworkControl::GetSingleton()->m_StopRequestedEvent.Wait( 0 ) )
			{
				break;
			}

			sockaddr tcpOrigin;

#ifdef _WIN32
			int size = (int) sizeof( sockaddr );
#endif

#ifdef __linux__
			socklen_t size = (socklen_t) sizeof( sockaddr );
#endif
			// Accept a new connection (blocking)
			SOCKET clientSock = accept( NetworkControl::GetSingleton()->m_SocketTCP, 0, 0 );

			// Get some data from the peer
			getpeername( clientSock, &tcpOrigin, &size );

			// If something went wrong, simply continue;
			if ( clientSock == -1 )
			{
				continue;
			}

			unsigned short publicId = RandomID();
			unsigned short privateId = RandomID();

			while ( NetworkControl::GetSingleton()->m_PublicIdClientMap[ publicId ] != 0 ) publicId = RandomID();
			while ( NetworkControl::GetSingleton()->m_PrivateIdClientMap[ privateId ] != 0 ) privateId = RandomID();

			// Create a new client
			Client* newClientObj = NetworkControl::GetSingleton()->AddClient( publicId, privateId, false, clientSock );

			// Copy the origin data
			newClientObj->m_IP = inet_ntoa( ( (sockaddr_in*) &tcpOrigin )->sin_addr );

			// Call the callback if it exists
			VOID_WITH_CLIENT_PARAM fun = ServerSide::GetOnAddClient();
			if ( fun != 0 ) fun( newClientObj );

			// Ship the new client's IDs back.
			Packet* sendidpack = new Packet();

			sendidpack->SetOpCodeInternal( OpCodeHandler::GET_ID );
			sendidpack->AddDataStreaming<unsigned short>( (unsigned short) newClientObj->m_PublicId );
			sendidpack->AddDataStreaming<unsigned short>( (unsigned short) newClientObj->m_PrivateId );
			sendidpack->SetUDPEnabled( false );

			newClientObj->GetSenderObject()->AddToQueue( sendidpack );

			// Broadcast the public ID to all other clients.
			if ( !( NetworkControl::GetSingleton()->GetFlags() & NetworkControl::VENDOR_MODE ) )
			{
                Packet* broadcast = new Packet();

                broadcast->SetOpCodeInternal( OpCodeHandler::ADD_CLIENT );
                broadcast->AddDataStreaming<unsigned short>( (unsigned short) newClientObj->m_PublicId );
                broadcast->SetClientPrivateId( newClientObj->m_PrivateId );
                broadcast->SetFlag( Packet::PF_EXCLUDEORIGIN );
                sendidpack->SetUDPEnabled( false );

                NetworkControl::GetSingleton()->BroadcastToAll( broadcast );
            }

			if ( !( NetworkControl::GetSingleton()->GetFlags() & NetworkControl::VENDOR_MODE ) && NetworkControl::GetSingleton()->m_ClientIds.size() > 0 )
			{
				for ( unsigned int i = 0; i < NetworkControl::GetSingleton()->m_ClientIds.size(); i++ )
				{
					if ( NetworkControl::GetSingleton()->m_ClientIds[i].cc_PublicId != publicId )
					{
						Packet* pack = new Packet();

						pack->SetOpCodeInternal( OpCodeHandler::ADD_CLIENT );
						pack->AddDataStreaming<unsigned short>( (unsigned short) NetworkControl::GetSingleton()->m_ClientIds[i].cc_PublicId );

						newClientObj->GetSenderObject()->AddToQueue( pack );
					}
				}
			}
		}

		return 1;
	}
};
<commit_msg>Indentation error.<commit_after>/*
	Copyright (c) 2013-2014 Sam Hardeman

	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	THE SOFTWARE.
*/

#include "Modules.h"
#include "OpCodeHandler.h"
#include "NetworkControl.h"
#include "PacketSender.h"
#include "Packet.h"
#include "Client.h"

#include "IceNetServer.h"
#include "IceNetTypedefs.h"

#include <time.h>

namespace IceNet
{
	unsigned short RandomID( void )
	{
		unsigned short id = 0;

		while ( 1 )
		{
			id = rand() & USHRT_MAX;
			if ( id <= 256 ) continue;

			break;
		}

		return id;
	}

	THREAD_FUNC ListenerEntry( void* ptr )
	{
		srand( (unsigned int) time( 0 ) );
		rand();

		while ( true )
		{
			// Poll for stop condition
			if ( NetworkControl::GetSingleton()->m_StopRequestedEvent.Wait( 0 ) )
			{
				break;
			}

			sockaddr tcpOrigin;

#ifdef _WIN32
			int size = (int) sizeof( sockaddr );
#endif

#ifdef __linux__
			socklen_t size = (socklen_t) sizeof( sockaddr );
#endif
			// Accept a new connection (blocking)
			SOCKET clientSock = accept( NetworkControl::GetSingleton()->m_SocketTCP, 0, 0 );

			// Get some data from the peer
			getpeername( clientSock, &tcpOrigin, &size );

			// If something went wrong, simply continue;
			if ( clientSock == -1 )
			{
				continue;
			}

			unsigned short publicId = RandomID();
			unsigned short privateId = RandomID();

			while ( NetworkControl::GetSingleton()->m_PublicIdClientMap[ publicId ] != 0 ) publicId = RandomID();
			while ( NetworkControl::GetSingleton()->m_PrivateIdClientMap[ privateId ] != 0 ) privateId = RandomID();

			// Create a new client
			Client* newClientObj = NetworkControl::GetSingleton()->AddClient( publicId, privateId, false, clientSock );

			// Copy the origin data
			newClientObj->m_IP = inet_ntoa( ( (sockaddr_in*) &tcpOrigin )->sin_addr );

			// Call the callback if it exists
			VOID_WITH_CLIENT_PARAM fun = ServerSide::GetOnAddClient();
			if ( fun != 0 ) fun( newClientObj );

			// Ship the new client's IDs back.
			Packet* sendidpack = new Packet();

			sendidpack->SetOpCodeInternal( OpCodeHandler::GET_ID );
			sendidpack->AddDataStreaming<unsigned short>( (unsigned short) newClientObj->m_PublicId );
			sendidpack->AddDataStreaming<unsigned short>( (unsigned short) newClientObj->m_PrivateId );
			sendidpack->SetUDPEnabled( false );

			newClientObj->GetSenderObject()->AddToQueue( sendidpack );

			// Broadcast the public ID to all other clients.
			if ( !( NetworkControl::GetSingleton()->GetFlags() & NetworkControl::VENDOR_MODE ) )
			{
				Packet* broadcast = new Packet();

                		broadcast->SetOpCodeInternal( OpCodeHandler::ADD_CLIENT );
                		broadcast->AddDataStreaming<unsigned short>( (unsigned short) newClientObj->m_PublicId );
                		broadcast->SetClientPrivateId( newClientObj->m_PrivateId );
                		broadcast->SetFlag( Packet::PF_EXCLUDEORIGIN );
                		sendidpack->SetUDPEnabled( false );

                		NetworkControl::GetSingleton()->BroadcastToAll( broadcast );
            		}

			if ( !( NetworkControl::GetSingleton()->GetFlags() & NetworkControl::VENDOR_MODE ) && NetworkControl::GetSingleton()->m_ClientIds.size() > 0 )
			{
				for ( unsigned int i = 0; i < NetworkControl::GetSingleton()->m_ClientIds.size(); i++ )
				{
					if ( NetworkControl::GetSingleton()->m_ClientIds[i].cc_PublicId != publicId )
					{
						Packet* pack = new Packet();

						pack->SetOpCodeInternal( OpCodeHandler::ADD_CLIENT );
						pack->AddDataStreaming<unsigned short>( (unsigned short) NetworkControl::GetSingleton()->m_ClientIds[i].cc_PublicId );

						newClientObj->GetSenderObject()->AddToQueue( pack );
					}
				}
			}
		}

		return 1;
	}
};
<|endoftext|>


<commit_before>#include "vuniformslay.h"

#include <Tempest/UniformsLayout>
#include "vdevice.h"
#include "gapi/shaderreflection.h"

using namespace Tempest;
using namespace Tempest::Detail;

VUniformsLay::VUniformsLay(VDevice& dev, const std::vector<UniformsLayout::Binding>& comp)
  : dev(dev.device) {
  ShaderReflection::merge(lay, pb, comp);
  if(lay.size()<=32) {
    VkDescriptorSetLayoutBinding bind[32]={};
    implCreate(bind);
    } else {
    std::unique_ptr<VkDescriptorSetLayoutBinding[]> bind(new VkDescriptorSetLayoutBinding[lay.size()]);
    implCreate(bind.get());
    }
  for(auto& i:lay)
    if(i.cls==UniformsLayout::SsboR  ||
       i.cls==UniformsLayout::SsboRW ||
       i.cls==UniformsLayout::ImgR   ||
       i.cls==UniformsLayout::ImgRW ) {
      hasSSBO = true;
      }
  }

VUniformsLay::VUniformsLay(VDevice& dev, const std::vector<UniformsLayout::Binding>* sh[], size_t cnt)
  : dev(dev.device) {
  ShaderReflection::merge(lay, pb, sh, cnt);
  if(lay.size()<=32) {
    VkDescriptorSetLayoutBinding bind[32]={};
    implCreate(bind);
    } else {
    std::unique_ptr<VkDescriptorSetLayoutBinding[]> bind(new VkDescriptorSetLayoutBinding[lay.size()]);
    implCreate(bind.get());
    }
  }

VUniformsLay::~VUniformsLay() {
  for(auto& i:pool)
    vkDestroyDescriptorPool(dev,i.impl,nullptr);
  vkDestroyDescriptorSetLayout(dev,impl,nullptr);
  }

void VUniformsLay::implCreate(VkDescriptorSetLayoutBinding* bind) {
  static const VkDescriptorType types[] = {
    VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
    VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
    VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
    VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
    VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
    VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
    };

  uint32_t count = 0;
  for(size_t i=0;i<lay.size();++i){
    auto& b=bind[i];
    auto& e=lay[i];

    if(e.stage==UniformsLayout::Stage(0))
      continue;

    b.binding         = e.layout;
    b.descriptorCount = 1;
    b.descriptorType  = types[e.cls];

    b.stageFlags      = 0;
    if(e.stage&UniformsLayout::Compute)
      b.stageFlags |= VK_SHADER_STAGE_COMPUTE_BIT;
    if(e.stage&UniformsLayout::Vertex)
      b.stageFlags |= VK_SHADER_STAGE_VERTEX_BIT;
    if(e.stage&UniformsLayout::Control)
      b.stageFlags |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
    if(e.stage&UniformsLayout::Evaluate)
      b.stageFlags |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
    if(e.stage&UniformsLayout::Geometry)
      b.stageFlags |= VK_SHADER_STAGE_GEOMETRY_BIT;
    if(e.stage&UniformsLayout::Fragment)
      b.stageFlags |= VK_SHADER_STAGE_FRAGMENT_BIT;
    ++count;
    }

  VkDescriptorSetLayoutCreateInfo info={};
  info.sType        = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
  info.bindingCount = count;
  info.pBindings    = bind;

  vkAssert(vkCreateDescriptorSetLayout(dev,&info,nullptr,&impl));
  }

<commit_msg>fixup<commit_after>#include "vuniformslay.h"

#include <Tempest/UniformsLayout>
#include "vdevice.h"
#include "gapi/shaderreflection.h"

using namespace Tempest;
using namespace Tempest::Detail;

VUniformsLay::VUniformsLay(VDevice& dev, const std::vector<UniformsLayout::Binding>& comp)
  : dev(dev.device) {
  ShaderReflection::merge(lay, pb, comp);
  if(lay.size()<=32) {
    VkDescriptorSetLayoutBinding bind[32]={};
    implCreate(bind);
    } else {
    std::unique_ptr<VkDescriptorSetLayoutBinding[]> bind(new VkDescriptorSetLayoutBinding[lay.size()]);
    implCreate(bind.get());
    }
  for(auto& i:lay)
    if(i.cls==UniformsLayout::SsboR  ||
       i.cls==UniformsLayout::SsboRW ||
       i.cls==UniformsLayout::ImgR   ||
       i.cls==UniformsLayout::ImgRW ) {
      hasSSBO = true;
      }
  }

VUniformsLay::VUniformsLay(VDevice& dev, const std::vector<UniformsLayout::Binding>* sh[], size_t cnt)
  : dev(dev.device) {
  ShaderReflection::merge(lay, pb, sh, cnt);
  if(lay.size()<=32) {
    VkDescriptorSetLayoutBinding bind[32]={};
    implCreate(bind);
    } else {
    std::unique_ptr<VkDescriptorSetLayoutBinding[]> bind(new VkDescriptorSetLayoutBinding[lay.size()]);
    implCreate(bind.get());
    }
  }

VUniformsLay::~VUniformsLay() {
  for(auto& i:pool)
    vkDestroyDescriptorPool(dev,i.impl,nullptr);
  vkDestroyDescriptorSetLayout(dev,impl,nullptr);
  }

void VUniformsLay::implCreate(VkDescriptorSetLayoutBinding* bind) {
  static const VkDescriptorType types[] = {
    VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
    VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
    VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
    VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
    VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
    VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
    };

  uint32_t count = 0;
  for(size_t i=0;i<lay.size();++i){
    auto& b=bind[count];
    auto& e=lay[i];

    if(e.stage==UniformsLayout::Stage(0))
      continue;

    b.binding         = e.layout;
    b.descriptorCount = 1;
    b.descriptorType  = types[e.cls];

    b.stageFlags      = 0;
    if(e.stage&UniformsLayout::Compute)
      b.stageFlags |= VK_SHADER_STAGE_COMPUTE_BIT;
    if(e.stage&UniformsLayout::Vertex)
      b.stageFlags |= VK_SHADER_STAGE_VERTEX_BIT;
    if(e.stage&UniformsLayout::Control)
      b.stageFlags |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
    if(e.stage&UniformsLayout::Evaluate)
      b.stageFlags |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
    if(e.stage&UniformsLayout::Geometry)
      b.stageFlags |= VK_SHADER_STAGE_GEOMETRY_BIT;
    if(e.stage&UniformsLayout::Fragment)
      b.stageFlags |= VK_SHADER_STAGE_FRAGMENT_BIT;
    ++count;
    }

  VkDescriptorSetLayoutCreateInfo info={};
  info.sType        = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
  info.bindingCount = count;
  info.pBindings    = bind;

  vkAssert(vkCreateDescriptorSetLayout(dev,&info,nullptr,&impl));
  }

<|endoftext|>


<commit_before>#include "scrollwidget.h"

#include <Tempest/Platform>
#include <Tempest/Layout>

using namespace Tempest;

struct ScrollWidget::BoxLayout: public Tempest::LinearLayout {
  BoxLayout(ScrollWidget* sc,Orientation ori ):LinearLayout(ori), sc(sc){}

  void applyLayout() {
    sc->complexLayout();
    }

  void commitLayout() {
    LinearLayout::applyLayout();
    }

  Size wrapContent(Widget& ow, Orientation orient, bool inParent) {
    const Widget* root=inParent ? sc : nullptr;
    int sw=0,sh=0;

    int vcount = 0;
    for(size_t i=0;i<ow.widgetsCount();i++) {
      auto& wx = ow.widget(i);
      if( !wx.isVisible() )
        continue;
      vcount++;
      Size s = wx.sizeHint();
      if(orient==Horizontal){
        sw += s.w;
        sh = std::max(sh,s.h);
        } else {
        sw = std::max(sw,s.w);
        sh += s.h;
        }
      }

    if(orient==Horizontal) {
      if(vcount>0)
        sw += (vcount-1)*ow.spacing();
      if(root)
        sh=std::max(sh,root->h());
      } else {
      if(vcount>0)
        sh += (vcount-1)*ow.spacing();
      if(root)
        sw=std::max(sw,root->w());
      }

    const Margin& m = ow.margins();
    if(orient==Horizontal)
      sw += m.xMargin(); else
      sh += m.yMargin();
    return Size(sw,sh);
    }

  ScrollWidget* sc = nullptr;
  };

struct ScrollWidget::ProxyLayout : public Tempest::Layout {
  ProxyLayout(ScrollWidget* sc):sc(sc){}

  void applyLayout() {
    sc->complexLayout();
    }

  ScrollWidget* sc = nullptr;
  };

ScrollWidget::ScrollWidget()
  :ScrollWidget(Vertical) {
  }

ScrollWidget::ScrollWidget(Orientation ori)
  : sbH(Horizontal), sbV(Vertical), vert(AsNeed), hor(AsNeed)  {
  layoutBusy=true;

  const Style::UIIntefaceCategory cat=style().idiom().category;
  if( cat==Style::UIIntefacePhone || cat==Style::UIIntefacePC ){
    vert=AlwaysOff;
    hor =AlwaysOff;
    }
  setSizePolicy(Preferred);

  sbH.onValueChanged.bind(this, static_cast<void(ScrollWidget::*)(int)>(&ScrollWidget::scrollH));
  sbV.onValueChanged.bind(this, static_cast<void(ScrollWidget::*)(int)>(&ScrollWidget::scrollV));

  setHscrollViewMode(this->hor );
  setVscrollViewMode(this->vert);

  helper.addWidget(&cen);
  addWidget(&helper);
  addWidget(&sbH);
  addWidget(&sbV);

  cenLay = new BoxLayout(this,ori);
  cen.setLayout(cenLay);
  helper. setLayout(new Tempest::Layout());
  Widget::setLayout(new ProxyLayout (this));

  layoutBusy=false;
  }

ScrollWidget::~ScrollWidget() {
  helper.takeWidget(&cen);
  takeWidget(&helper);
  takeWidget(&sbH);
  takeWidget(&sbV);
  }

bool ScrollWidget::updateScrolls(Orientation orient,bool noRetry) {
  using std::max;
  using std::min;

  const Margin& m     = margins();
  const Widget* first = findFirst();
  const Widget* last  = findLast();

  Size content = cenLay->wrapContent(cen,orient,false);

  bool needScH = (hor ==AlwaysOn || content.w>helper.w());
  bool needScV = (vert==AlwaysOn || content.h>helper.h());
  bool hasScH  = needScH && (hor !=AlwaysOff);
  bool hasScV  = needScV && (vert!=AlwaysOff);

  emplace(helper,
          hasScH ? &sbH : nullptr,
          hasScV ? &sbV : nullptr,
          Rect(m.left,m.top,w()-m.xMargin(),h()-m.yMargin()));

  const Size hsize=helper.size();
  if( !noRetry ) {
    if(hasScH != (hor ==AlwaysOn || content.w>hsize.w) && (hor!=AlwaysOff))
      return false;
    if(hasScV != (vert==AlwaysOn || content.h>hsize.h) && (vert!=AlwaysOff))
      return false;
    }

  if( !needScH && !needScV ) {
    sbH.setValue(0);
    sbV.setValue(0);
    cen.setPosition(0,0);
    } else
  if( !needScH ) {
    sbH.setValue(0);
    cen.setPosition(0,cen.y());
    } else
  if( !needScV ) {
    sbV.setValue(0);
    cen.setPosition(cen.x(),0);
    }
  sbH.setVisible(hasScH);
  sbV.setVisible(hasScV);
  cen.applyLayout();

  if(orient==Vertical) {
    int min=0;
    int max=std::max(content.h-hsize.h,0);

    if(scBeforeBeginV && first)
      min-=std::max(0,hsize.h-first->h());
    if(scAfterEndV && last)
      max+=std::max(0,hsize.h-last->h());
    sbV.setRange(min,max);
    sbH.setRange(0,cen.w());
    } else {
    int min=0;
    int max=std::max(content.w-hsize.w,0);

    if(scBeforeBeginH && first)
      min-=std::max(0,hsize.w-first->w());
    if(scAfterEndV && last)
      max+=std::max(0,hsize.w-last->w());
    sbH.setRange(min,max);
    sbV.setRange(cen.h(),0);
    }

  if(sbH.range()>0) {
    const double percent=hsize.w/double(sbH.range()+hsize.w);
    sbH.setCentralButtonSize(int(sbH.centralAreaSize()*percent));
    }
  if(sbV.range()>0) {
    const double percent=hsize.h/double(sbV.range()+hsize.h);
    sbV.setCentralButtonSize(int(sbV.centralAreaSize()*percent));
    }

  return true;
  }

void ScrollWidget::emplace(Widget &cen, Widget *scH, Widget *scV, const Rect& place) {
  int sp = spacing();
  int dx = scV==nullptr ? 0 : (scV->sizeHint().w);
  int dy = scH==nullptr ? 0 : (scH->sizeHint().h);

  if(scH)
    scH->setGeometry(place.x,place.y+place.h-dy,place.w-dx,dy);
  if(scV)
    scV->setGeometry(place.x+place.w-dx,place.y,dx,place.h-dy);

  if(dx>0)
    dx+=sp;
  if(dy>0)
    dy+=sp;
  cen.setGeometry(place.x,place.y,std::max(0,place.w-dx),std::max(0,place.h-dy));
  }

Widget *ScrollWidget::findFirst() {
  size_t sz = cen.widgetsCount();
  for(size_t i=0;i<sz;++i){
    if(cen.widget(i).isVisible())
      return &cen.widget(i);
    }
  return nullptr;
  }

Widget *ScrollWidget::findLast() {
  for(size_t i=cen.widgetsCount();i>0;){
    i--;
    if(cen.widget(i).isVisible())
      return &cen.widget(i);
    }
  return nullptr;
  }

Tempest::Widget &ScrollWidget::centralWidget() {
  return cen;
  }

void ScrollWidget::setLayout(Orientation ori) {
  layoutBusy=true;
  cenLay = new BoxLayout(this,ori);
  cen.setLayout(cenLay);
  layoutBusy=false;
  applyLayout();
  }

void ScrollWidget::hideScrollBars() {
  setScrollBarsVisible(false,false);
  }

void ScrollWidget::setScrollBarsVisible(bool vh, bool vv) {
  if(vh==sbH.isVisible() && vv==sbV.isVisible())
    return;

  sbH.setVisible(vh);
  sbV.setVisible(vv);
  }

void ScrollWidget::setVscrollViewMode(ScrollViewMode mode) {
  vert = mode;
  applyLayout();
  }

void ScrollWidget::setHscrollViewMode(ScrollViewMode mode) {
  hor = mode;
  applyLayout();
  }

void ScrollWidget::scrollAfterEndH(bool s) {
  scAfterEndH = s;
  applyLayout();
  }

bool ScrollWidget::hasScrollAfterEndH() const {
  return scAfterEndH;
  }

void ScrollWidget::scrollBeforeBeginH(bool s) {
  scBeforeBeginH = s;
  applyLayout();
  }

bool ScrollWidget::hasScrollBeforeBeginH() const {
  return scBeforeBeginH;
  }

void ScrollWidget::scrollAfterEndV(bool s) {
  scAfterEndV = s;
  applyLayout();
  }

bool ScrollWidget::hasScrollAfterEndV() const {
  return scAfterEndV;
  }

void ScrollWidget::scrollBeforeBeginV(bool s) {
  scBeforeBeginV = s;
  applyLayout();
  }

bool ScrollWidget::hasScrollBeforeBeginV() const {
  return scBeforeBeginV;
  }

void ScrollWidget::mouseWheelEvent(Tempest::MouseEvent &e) {
  if(!isEnabled())
    return;

  if( !rect().contains(e.x+x(), e.y+y()) || !sbV.isVisible() ) {
    e.ignore();
    return;
    }

  if(e.delta>0)
    sbV.setValue(sbV.value() - sbV.largeStep()); else
  if(e.delta<0)
    sbV.setValue(sbV.value() + sbV.largeStep());
  }

void ScrollWidget::mouseMoveEvent(Tempest::MouseEvent &e) {
  e.ignore();
  }

void ScrollWidget::scrollH( int v ) {
  sbH.setValue( v );
  cen.setPosition(-sbH.value(), cen.y());
  }

void ScrollWidget::scrollV(int v) {
  sbV.setValue( v );
  cen.setPosition(cen.x(), -sbV.value());
  }

int ScrollWidget::scrollH() const {
  return -cen.x();
  }

int ScrollWidget::scrollV() const {
  return -cen.y();
  }

void ScrollWidget::complexLayout() {
  if(layoutBusy)
    return;

  Orientation orient = cenLay->orientation();

  layoutBusy=true;
  helper.setGeometry(0,0,w(),h());
  wrapContent();
  cenLay->commitLayout();

  static const int tryCound=3;
  for(int i=1;i<=tryCound;++i)
    if(updateScrolls(orient,i==tryCound))
      break;
  layoutBusy=false;
  }

void ScrollWidget::wrapContent() {
  SizePolicy spolicy;
  auto wrap = contentAreaSize();
  spolicy.maxSize=wrap;
  spolicy.minSize=wrap;
  if(cenLay->orientation()==Horizontal) {
    spolicy.typeH  =Fixed;
    spolicy.typeV  =Preferred;
    } else {
    spolicy.typeH  =Preferred;
    spolicy.typeV  =Fixed;
    }

  cen.resize(wrap);
  }

Size ScrollWidget::contentAreaSize() {
  return cenLay->wrapContent(cen,cenLay->orientation(),true);
  }
<commit_msg>scrollwidget fix<commit_after>#include "scrollwidget.h"

#include <Tempest/Platform>
#include <Tempest/Layout>

using namespace Tempest;

struct ScrollWidget::BoxLayout: public Tempest::LinearLayout {
  BoxLayout(ScrollWidget* sc,Orientation ori ):LinearLayout(ori), sc(sc){}

  void applyLayout() {
    sc->complexLayout();
    }

  void commitLayout() {
    LinearLayout::applyLayout();
    }

  Size wrapContent(Widget& ow, Orientation orient, bool inParent) {
    const Widget* root=inParent ? sc : nullptr;
    int sw=0,sh=0;

    int vcount = 0;
    for(size_t i=0;i<ow.widgetsCount();i++) {
      auto& wx = ow.widget(i);
      if( !wx.isVisible() )
        continue;
      vcount++;
      Size s   = wx.sizeHint();
      Size min = wx.minSize();
      s.w = std::max(s.w,min.w);
      s.h = std::max(s.h,min.h);

      if(orient==Horizontal){
        sw += s.w;
        sh = std::max(sh,s.h);
        } else {
        sw = std::max(sw,s.w);
        sh += s.h;
        }
      }

    if(orient==Horizontal) {
      if(vcount>0)
        sw += (vcount-1)*ow.spacing();
      if(root)
        sh=std::max(sh,root->h());
      } else {
      if(vcount>0)
        sh += (vcount-1)*ow.spacing();
      if(root)
        sw=std::max(sw,root->w());
      }

    const Margin& m = ow.margins();
    if(orient==Horizontal)
      sw += m.xMargin(); else
      sh += m.yMargin();
    return Size(sw,sh);
    }

  ScrollWidget* sc = nullptr;
  };

struct ScrollWidget::ProxyLayout : public Tempest::Layout {
  ProxyLayout(ScrollWidget* sc):sc(sc){}

  void applyLayout() {
    sc->complexLayout();
    }

  ScrollWidget* sc = nullptr;
  };

ScrollWidget::ScrollWidget()
  :ScrollWidget(Vertical) {
  }

ScrollWidget::ScrollWidget(Orientation ori)
  : sbH(Horizontal), sbV(Vertical), vert(AsNeed), hor(AsNeed)  {
  layoutBusy=true;

  const Style::UIIntefaceCategory cat=style().idiom().category;
  if( cat==Style::UIIntefacePhone || cat==Style::UIIntefacePC ){
    vert=AlwaysOff;
    hor =AlwaysOff;
    }
  setSizePolicy(Preferred);

  sbH.onValueChanged.bind(this, static_cast<void(ScrollWidget::*)(int)>(&ScrollWidget::scrollH));
  sbV.onValueChanged.bind(this, static_cast<void(ScrollWidget::*)(int)>(&ScrollWidget::scrollV));

  setHscrollViewMode(this->hor );
  setVscrollViewMode(this->vert);

  helper.addWidget(&cen);
  addWidget(&helper);
  addWidget(&sbH);
  addWidget(&sbV);

  cenLay = new BoxLayout(this,ori);
  cen.setLayout(cenLay);
  helper. setLayout(new Tempest::Layout());
  Widget::setLayout(new ProxyLayout (this));

  layoutBusy=false;
  }

ScrollWidget::~ScrollWidget() {
  helper.takeWidget(&cen);
  takeWidget(&helper);
  takeWidget(&sbH);
  takeWidget(&sbV);
  }

bool ScrollWidget::updateScrolls(Orientation orient,bool noRetry) {
  using std::max;
  using std::min;

  const Margin& m     = margins();
  const Widget* first = findFirst();
  const Widget* last  = findLast();

  Size content = cenLay->wrapContent(cen,orient,false);

  bool needScH = (hor ==AlwaysOn || content.w>helper.w());
  bool needScV = (vert==AlwaysOn || content.h>helper.h());
  bool hasScH  = needScH && (hor !=AlwaysOff);
  bool hasScV  = needScV && (vert!=AlwaysOff);

  emplace(helper,
          hasScH ? &sbH : nullptr,
          hasScV ? &sbV : nullptr,
          Rect(m.left,m.top,w()-m.xMargin(),h()-m.yMargin()));

  const Size hsize=helper.size();
  if( !noRetry ) {
    if(hasScH != (hor ==AlwaysOn || content.w>hsize.w) && (hor!=AlwaysOff))
      return false;
    if(hasScV != (vert==AlwaysOn || content.h>hsize.h) && (vert!=AlwaysOff))
      return false;
    }

  if( !needScH && !needScV ) {
    sbH.setValue(0);
    sbV.setValue(0);
    cen.setPosition(0,0);
    } else
  if( !needScH ) {
    sbH.setValue(0);
    cen.setPosition(0,cen.y());
    } else
  if( !needScV ) {
    sbV.setValue(0);
    cen.setPosition(cen.x(),0);
    }
  sbH.setVisible(hasScH);
  sbV.setVisible(hasScV);
  cen.applyLayout();

  if(orient==Vertical) {
    int min=0;
    int max=std::max(content.h-hsize.h,0);

    if(scBeforeBeginV && first)
      min-=std::max(0,hsize.h-first->h());
    if(scAfterEndV && last)
      max+=std::max(0,hsize.h-last->h());
    sbV.setRange(min,max);
    sbH.setRange(0,cen.w());
    } else {
    int min=0;
    int max=std::max(content.w-hsize.w,0);

    if(scBeforeBeginH && first)
      min-=std::max(0,hsize.w-first->w());
    if(scAfterEndV && last)
      max+=std::max(0,hsize.w-last->w());
    sbH.setRange(min,max);
    sbV.setRange(cen.h(),0);
    }

  if(sbH.range()>0) {
    const double percent=hsize.w/double(sbH.range()+hsize.w);
    sbH.setCentralButtonSize(int(sbH.centralAreaSize()*percent));
    }
  if(sbV.range()>0) {
    const double percent=hsize.h/double(sbV.range()+hsize.h);
    sbV.setCentralButtonSize(int(sbV.centralAreaSize()*percent));
    }

  return true;
  }

void ScrollWidget::emplace(Widget &cen, Widget *scH, Widget *scV, const Rect& place) {
  int sp = spacing();
  int dx = scV==nullptr ? 0 : (scV->sizeHint().w);
  int dy = scH==nullptr ? 0 : (scH->sizeHint().h);

  if(scH)
    scH->setGeometry(place.x,place.y+place.h-dy,place.w-dx,dy);
  if(scV)
    scV->setGeometry(place.x+place.w-dx,place.y,dx,place.h-dy);

  if(dx>0)
    dx+=sp;
  if(dy>0)
    dy+=sp;
  cen.setGeometry(place.x,place.y,std::max(0,place.w-dx),std::max(0,place.h-dy));
  }

Widget *ScrollWidget::findFirst() {
  size_t sz = cen.widgetsCount();
  for(size_t i=0;i<sz;++i){
    if(cen.widget(i).isVisible())
      return &cen.widget(i);
    }
  return nullptr;
  }

Widget *ScrollWidget::findLast() {
  for(size_t i=cen.widgetsCount();i>0;){
    i--;
    if(cen.widget(i).isVisible())
      return &cen.widget(i);
    }
  return nullptr;
  }

Tempest::Widget &ScrollWidget::centralWidget() {
  return cen;
  }

void ScrollWidget::setLayout(Orientation ori) {
  layoutBusy=true;
  cenLay = new BoxLayout(this,ori);
  cen.setLayout(cenLay);
  layoutBusy=false;
  applyLayout();
  }

void ScrollWidget::hideScrollBars() {
  setScrollBarsVisible(false,false);
  }

void ScrollWidget::setScrollBarsVisible(bool vh, bool vv) {
  if(vh==sbH.isVisible() && vv==sbV.isVisible())
    return;

  sbH.setVisible(vh);
  sbV.setVisible(vv);
  }

void ScrollWidget::setVscrollViewMode(ScrollViewMode mode) {
  vert = mode;
  applyLayout();
  }

void ScrollWidget::setHscrollViewMode(ScrollViewMode mode) {
  hor = mode;
  applyLayout();
  }

void ScrollWidget::scrollAfterEndH(bool s) {
  scAfterEndH = s;
  applyLayout();
  }

bool ScrollWidget::hasScrollAfterEndH() const {
  return scAfterEndH;
  }

void ScrollWidget::scrollBeforeBeginH(bool s) {
  scBeforeBeginH = s;
  applyLayout();
  }

bool ScrollWidget::hasScrollBeforeBeginH() const {
  return scBeforeBeginH;
  }

void ScrollWidget::scrollAfterEndV(bool s) {
  scAfterEndV = s;
  applyLayout();
  }

bool ScrollWidget::hasScrollAfterEndV() const {
  return scAfterEndV;
  }

void ScrollWidget::scrollBeforeBeginV(bool s) {
  scBeforeBeginV = s;
  applyLayout();
  }

bool ScrollWidget::hasScrollBeforeBeginV() const {
  return scBeforeBeginV;
  }

void ScrollWidget::mouseWheelEvent(Tempest::MouseEvent &e) {
  if(!isEnabled())
    return;

  if( !rect().contains(e.x+x(), e.y+y()) || !sbV.isVisible() ) {
    e.ignore();
    return;
    }

  if(e.delta>0)
    sbV.setValue(sbV.value() - sbV.largeStep()); else
  if(e.delta<0)
    sbV.setValue(sbV.value() + sbV.largeStep());
  }

void ScrollWidget::mouseMoveEvent(Tempest::MouseEvent &e) {
  e.ignore();
  }

void ScrollWidget::scrollH( int v ) {
  sbH.setValue( v );
  cen.setPosition(-sbH.value(), cen.y());
  }

void ScrollWidget::scrollV(int v) {
  sbV.setValue( v );
  cen.setPosition(cen.x(), -sbV.value());
  }

int ScrollWidget::scrollH() const {
  return -cen.x();
  }

int ScrollWidget::scrollV() const {
  return -cen.y();
  }

void ScrollWidget::complexLayout() {
  if(layoutBusy)
    return;

  Orientation orient = cenLay->orientation();

  layoutBusy=true;
  helper.setGeometry(0,0,w(),h());
  wrapContent();
  cenLay->commitLayout();

  static const int tryCound=3;
  for(int i=1;i<=tryCound;++i)
    if(updateScrolls(orient,i==tryCound))
      break;
  layoutBusy=false;
  }

void ScrollWidget::wrapContent() {
  SizePolicy spolicy;
  auto wrap = contentAreaSize();
  spolicy.maxSize=wrap;
  spolicy.minSize=wrap;
  if(cenLay->orientation()==Horizontal) {
    spolicy.typeH  =Fixed;
    spolicy.typeV  =Preferred;
    } else {
    spolicy.typeH  =Preferred;
    spolicy.typeV  =Fixed;
    }

  cen.resize(wrap);
  }

Size ScrollWidget::contentAreaSize() {
  return cenLay->wrapContent(cen,cenLay->orientation(),true);
  }
<|endoftext|>


<commit_before>#include "motiondetector.h"

using namespace cv;

MotionDetector::MotionDetector()
{
	pMOG2 = new BackgroundSubtractorMOG2();
}

MotionDetector::~MotionDetector()
{

}

void MotionDetector::ResetMotionDetection(cv::Mat* frame)
{
	pMOG2->operator()(*frame, fgMaskMOG2, 1);
}

cv::Rect MotionDetector::MotionDetect(cv::Mat* frame)
//Detect motion and create ONE recangle that contains all the detected motion
{
	std::vector<std::vector<cv::Point> > contours;
	std::vector<cv::Vec4i> hierarchy;
	cv::Rect bounding_rect;
	std::vector<cv::Rect> rects;
	cv::Rect largest_rect, rect_temp;

	// Detect motion
	pMOG2->operator()(*frame, fgMaskMOG2, -1);
	//Remove noise
	cv::erode(fgMaskMOG2, fgMaskMOG2, getStructuringElement(cv::MORPH_RECT, cv::Size(6, 6)));
	// Find the contours of motion areas in the image
	findContours(fgMaskMOG2, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
	// Find the bounding rectangles of the areas of motion
	if (contours.size() > 0)
	{
		for (int i = 0; i < contours.size(); i++)
		{
			bounding_rect = boundingRect(contours[i]);
			rects.push_back(bounding_rect);
		}
		// Determine the overall area with motion.
		largest_rect = rects[0];
		for (int i = 1; i < rects.size(); i++)
		{
			rect_temp.x = min(largest_rect.x,rects[i].x);
			rect_temp.y = min(largest_rect.y,rects[i].y);
			rect_temp.width = max(largest_rect.x + largest_rect.width, rects[i].x + rects[i].width)-rect_temp.x;
			rect_temp.height = max(largest_rect.y + largest_rect.height, rects[i].y + rects[i].height) - rect_temp.y;
			largest_rect = rect_temp;
		}
		rectangle(*frame, rect_temp, cv::Scalar(0, 255, 0), 1, 8, 0);
	}
	else
		largest_rect = { 0, 0, 0, 0 };
//	imshow("Motion detect", fgMaskMOG2);
	return largest_rect;
}
<commit_msg>Changed method so that it does not require C++11<commit_after>#include "motiondetector.h"

using namespace cv;

MotionDetector::MotionDetector()
{
	pMOG2 = new BackgroundSubtractorMOG2();
}

MotionDetector::~MotionDetector()
{

}

void MotionDetector::ResetMotionDetection(cv::Mat* frame)
{
	pMOG2->operator()(*frame, fgMaskMOG2, 1);
}

cv::Rect MotionDetector::MotionDetect(cv::Mat* frame)
//Detect motion and create ONE recangle that contains all the detected motion
{
	std::vector<std::vector<cv::Point> > contours;
	std::vector<cv::Vec4i> hierarchy;
	cv::Rect bounding_rect;
	std::vector<cv::Rect> rects;
	cv::Rect largest_rect, rect_temp;

	// Detect motion
	pMOG2->operator()(*frame, fgMaskMOG2, -1);
	//Remove noise
	cv::erode(fgMaskMOG2, fgMaskMOG2, getStructuringElement(cv::MORPH_RECT, cv::Size(6, 6)));
	// Find the contours of motion areas in the image
	findContours(fgMaskMOG2, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
	// Find the bounding rectangles of the areas of motion
	if (contours.size() > 0)
	{
		for (int i = 0; i < contours.size(); i++)
		{
			bounding_rect = boundingRect(contours[i]);
			rects.push_back(bounding_rect);
		}
		// Determine the overall area with motion.
		largest_rect = rects[0];
		for (int i = 1; i < rects.size(); i++)
		{
			rect_temp.x = min(largest_rect.x,rects[i].x);
			rect_temp.y = min(largest_rect.y,rects[i].y);
			rect_temp.width = max(largest_rect.x + largest_rect.width, rects[i].x + rects[i].width)-rect_temp.x;
			rect_temp.height = max(largest_rect.y + largest_rect.height, rects[i].y + rects[i].height) - rect_temp.y;
			largest_rect = rect_temp;
		}
		rectangle(*frame, rect_temp, cv::Scalar(0, 255, 0), 1, 8, 0);
	}
	else
        {
          largest_rect.x = 0;
          largest_rect.y = 0;
          largest_rect.width = 0;
          largest_rect.height = 0;
        }

//	imshow("Motion detect", fgMaskMOG2);
	return largest_rect;
}
<|endoftext|>


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

#include "Timer.hpp"

#if !defined(__i386__) && defined(_M_IX86)
	#define __i386__ 1
#endif

#if !defined(__x86_64__) && (defined(_M_AMD64) || defined (_M_X64))
	#define __x86_64__ 1
#endif

#if defined(_WIN32)
	#ifndef WIN32_LEAN_AND_MEAN
		#define WIN32_LEAN_AND_MEAN
	#endif
	#include <windows.h>
	#include <intrin.h>
#else
	#include <sys/time.h>
	#if defined(__i386__) || defined(__x86_64__)
		#include <x86intrin.h>
	#endif
#endif

namespace sw
{
	Timer::Timer()
	{
	}

	Timer::~Timer()
	{
	}

	double Timer::seconds()
	{
		#if defined(_WIN32)
			return (double)counter() / (double)frequency();
		#else
			timeval t;
			gettimeofday(&t, 0);
			return (double)t.tv_sec + (double)t.tv_usec * 1.0e-6;
		#endif
	}

	int64_t Timer::ticks()
	{
		#if defined(_WIN32)
			#if defined(_M_ARM64)
				return _ReadStatusReg(ARM64_PMCCNTR_EL0);
			#else
				return __rdtsc();
			#endif
		#elif defined(__i386__) || defined(__x86_64__)
			int64_t tsc;
			__asm volatile("rdtsc": "=A" (tsc));
			return tsc;
		#else
			return 0;
		#endif
	}

	int64_t Timer::counter()
	{
		#if defined(_WIN32)
			int64_t counter;
			QueryPerformanceCounter((LARGE_INTEGER*)&counter);
			return counter;
		#else
			timeval t;
			gettimeofday(&t, 0);
			return t.tv_sec * 1000000 + t.tv_usec;
		#endif
	}

	int64_t Timer::frequency()
	{
		#if defined(_WIN32)
			int64_t frequency;
			QueryPerformanceFrequency((LARGE_INTEGER*)&frequency);
			return frequency;
		#else
			return 1000000;   // gettimeofday uses microsecond resolution
		#endif
	}
}
<commit_msg>Fix Timer::ticks() on x86-64.<commit_after>// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "Timer.hpp"

#if !defined(__i386__) && defined(_M_IX86)
	#define __i386__ 1
#endif

#if !defined(__x86_64__) && (defined(_M_AMD64) || defined (_M_X64))
	#define __x86_64__ 1
#endif

#if defined(_WIN32)
	#ifndef WIN32_LEAN_AND_MEAN
		#define WIN32_LEAN_AND_MEAN
	#endif
	#include <windows.h>
	#include <intrin.h>
#else
	#include <sys/time.h>
	#if defined(__i386__) || defined(__x86_64__)
		#include <x86intrin.h>
	#endif
#endif

namespace sw
{
	Timer::Timer()
	{
	}

	Timer::~Timer()
	{
	}

	double Timer::seconds()
	{
		#if defined(_WIN32)
			return (double)counter() / (double)frequency();
		#else
			timeval t;
			gettimeofday(&t, 0);
			return (double)t.tv_sec + (double)t.tv_usec * 1.0e-6;
		#endif
	}

	int64_t Timer::ticks()
	{
		#if defined(_WIN32)
			#if defined(_M_ARM64)
				return _ReadStatusReg(ARM64_PMCCNTR_EL0);
			#else
				return __rdtsc();
			#endif
		#elif defined(__i386__) || defined(__x86_64__)
			return __builtin_ia32_rdtsc();
		#else
			return 0;
		#endif
	}

	int64_t Timer::counter()
	{
		#if defined(_WIN32)
			int64_t counter;
			QueryPerformanceCounter((LARGE_INTEGER*)&counter);
			return counter;
		#else
			timeval t;
			gettimeofday(&t, 0);
			return t.tv_sec * 1000000 + t.tv_usec;
		#endif
	}

	int64_t Timer::frequency()
	{
		#if defined(_WIN32)
			int64_t frequency;
			QueryPerformanceFrequency((LARGE_INTEGER*)&frequency);
			return frequency;
		#else
			return 1000000;   // gettimeofday uses microsecond resolution
		#endif
	}
}
<|endoftext|>


<commit_before>#include <vector>
#include <iostream>

#include <osg/Group>
#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/PositionAttitudeTransform>
#include <osgViewer/Viewer>

#include <Eigen/Dense>

// TODO:
// x Utiliser eigen pour les vecteur donnés aux constructeurs des Objets
// - MSAA
// - Black background
// - Permettre de configurer le refresh rate ou de passer en mode "temps réel"
// - Séparer les modules
// - Ajouter des objets: sphere, cylindre, etc.
// - Objets STL
// - Light
// - Améliorer l'objet "Ground" (tuiles blanches et noires) + fog + LOD
// - Key start/stop recording -> screencast
// - Key take screenshot
// - Key reset
// - Ombres
// - Faire des vidéos et les poster sur jdhp
//
// - Logs (JSON ?)
// - Permettre de lancer une simulation sans interface graphique (sans osg) -> permetter de remplacer le "physicsCallback"
// - Remplacer le makefile par un cmakelist
// - Créer une arborescence et des modules .h/.cpp
//
// - Check units (mm ?, kg ?, ...)
// - Vérifier à la main une simulation simple (calculer à la main l'équation d'un objet qui tombe et comparer avec bullet)
//
// - Singleton OSG / Bullet ? -> bof...
// - Caméra
// - Hinges
// - Commandes d'entrée pour hinge
// - Txt infos (hinge constraints, ...)

// OBJECT.CPP /////////////////////////////////////////////////////////////////

#include <btBulletDynamicsCommon.h>

namespace botsim {

    class Object {
        protected:
            // Bullet
            btRigidBody * rigidBody;

            // OSG
            osg::Group * osgGroup;
            osg::PositionAttitudeTransform * osgPAT;

        public:
            btRigidBody * getRigidBody() {
                return this->rigidBody;
            }

            osg::Node * getOSGGroup() {
                return this->osgGroup;
            }

            osg::PositionAttitudeTransform * getOSGPAT() {
                return this->osgPAT;
            }
    };

    class Box: public botsim::Object {
        protected:
            // Bullet
            btCollisionShape * boxShape; // TODO: rename this
            btDefaultMotionState * boxMotionState; // TODO: rename this

            // Osg
            osg::Box * osgBox;
            osg::ShapeDrawable * osgShapeDrawable;
            osg::Geode * osgGeode;

            // Common
            Eigen::Vector3d initialDimension;         // which unit ? mm ?
            Eigen::Vector3d initialPosition;          // which unit ? mm ?
            Eigen::Vector4d initialAngle;             // which unit ? rad ? deg ?
            Eigen::Vector3d initialInertia;           // which unit ? mm/s ?
            Eigen::Vector3d initialVelocity;          // which unit ? mm/s ?
            Eigen::Vector3d initialAngularVelocity;   // which unit ? mm/s ?
            double mass;                              // which unit ? Kg ?

        public:
            Box(Eigen::Vector3d initial_dimension, Eigen::Vector3d initial_position, Eigen::Vector4d initial_angle, Eigen::Vector3d initial_velocity, Eigen::Vector3d initial_angular_velocity, Eigen::Vector3d initial_inertia, double mass) {

                this->initialDimension = initial_dimension;
                this->initialPosition = initial_position;
                this->initialAngle = initial_angle;
                this->initialInertia = initial_inertia;
                this->initialVelocity = initial_velocity;
                this->initialAngularVelocity = initial_angular_velocity;
                this->mass = mass;

                // BULLET
                btVector3 bt_box_shape(this->initialDimension(0)/2., this->initialDimension(1)/2., this->initialDimension(2)/2.);
                this->boxShape = new btBoxShape(bt_box_shape); // this is half lengths...

                btScalar bt_mass = this->mass;
                btVector3 bt_box_inertia(this->initialInertia(0), this->initialInertia(1), this->initialInertia(2));
                this->boxShape->calculateLocalInertia(bt_mass, bt_box_inertia);

                btQuaternion bt_angle(this->initialAngle(0), this->initialAngle(1), this->initialAngle(2), this->initialAngle(3));
                btVector3 bt_position(this->initialPosition(0), this->initialPosition(1), this->initialPosition(2));
                this->boxMotionState = new btDefaultMotionState(btTransform(bt_angle, bt_position));

                btRigidBody::btRigidBodyConstructionInfo box_rigid_body_ci(mass, this->boxMotionState, this->boxShape, bt_box_inertia);
                this->rigidBody = new btRigidBody(box_rigid_body_ci);

                btVector3 bt_velocity(this->initialVelocity(0), this->initialVelocity(1), this->initialVelocity(2));
                this->rigidBody->setLinearVelocity(bt_velocity);

                btVector3 bt_angular_velocity(this->initialAngularVelocity(0), this->initialAngularVelocity(1), this->initialAngularVelocity(2));
                this->rigidBody->setAngularVelocity(bt_angular_velocity);

                // OSG
                this->osgBox = new osg::Box(osg::Vec3(0, 0, 0), this->initialDimension(0), this->initialDimension(1), this->initialDimension(2));
                this->osgShapeDrawable = new osg::ShapeDrawable(this->osgBox);
                this->osgGeode = new osg::Geode();
                this->osgGeode->addDrawable(osgShapeDrawable);

                this->osgGroup = new osg::Group();
                this->osgGroup->addChild(this->osgGeode);

                this->osgPAT = new osg::PositionAttitudeTransform();
                this->osgPAT->addChild(this->osgGroup);
            }

            ~Box() {
                delete this->rigidBody->getMotionState(); // TODO ?
                delete this->rigidBody; // TODO ?

                delete this->boxShape;
                delete this->boxMotionState;

                //delete this->osgBox;
                //delete this->osgShapeDrawable;
                //delete this->osgGeode;
                //delete this->osgPAT;
            }
    };

    class Ground: public botsim::Object {
        private:
            // Bullet
            btCollisionShape * groundShape;
            btDefaultMotionState * groundMotionState;

            // Osg
            osg::Box * osgBox;
            osg::ShapeDrawable * osgShapeDrawable;
            osg::Geode * osgGeode;

        public:
            Ground() {
                // BULLET
                this->groundShape = new btStaticPlaneShape(btVector3(0, 0, 1), 0);

                this->groundMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1), btVector3(0,0,0)));
                btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI(0, this->groundMotionState, this->groundShape, btVector3(0, 0, 0));
                this->rigidBody = new btRigidBody(groundRigidBodyCI);

                // OSG
                this->osgBox = new osg::Box(osg::Vec3(0, 0, -1), 1.0f);
                this->osgBox->setHalfLengths(osg::Vec3(20, 20, 1));
                this->osgShapeDrawable = new osg::ShapeDrawable(this->osgBox);
                this->osgGeode = new osg::Geode();
                this->osgGeode->addDrawable(osgShapeDrawable);

                this->osgGroup = new osg::Group();
                this->osgGroup->addChild(this->osgGeode);

                this->osgPAT = new osg::PositionAttitudeTransform();
                this->osgPAT->addChild(this->osgGroup);
            }

            ~Ground() {
                delete this->rigidBody->getMotionState(); // TODO ?
                delete this->rigidBody; // TODO ?

                delete this->groundShape;
                delete this->groundMotionState;

                //delete this->osgBox;
                //delete this->osgShapeDrawable;
                //delete this->osgGeode;
                //delete this->osgPAT;
            }
    };
}

// BULLET.CPP /////////////////////////////////////////////////////////////////

class BulletEnvironment {

    // TODO: cette classe devrait être un singleton ?!

    private:
        btDiscreteDynamicsWorld * dynamicsWorld;
        btDbvtBroadphase * broadphase;
        btDefaultCollisionConfiguration * collisionConfiguration;
        btCollisionDispatcher * collisionDispatcher;
        btSequentialImpulseConstraintSolver * constraintSolver;

        std::vector<botsim::Object *> * objectsVec;

        double gravity;

    public:
        BulletEnvironment(std::vector<botsim::Object *> * objects_vec) {
            this->gravity = -10.;

            this->broadphase = new btDbvtBroadphase();

            this->collisionConfiguration = new btDefaultCollisionConfiguration();
            this->collisionDispatcher = new btCollisionDispatcher(this->collisionConfiguration);

            this->constraintSolver = new btSequentialImpulseConstraintSolver();

            this->dynamicsWorld = new btDiscreteDynamicsWorld(this->collisionDispatcher,
                    this->broadphase,
                    this->constraintSolver,
                    this->collisionConfiguration);
            this->dynamicsWorld->setGravity(btVector3(0, 0, this->gravity));

            this->objectsVec = objects_vec;

            // Add rigid bodies
            std::vector<botsim::Object *>::iterator it;
            for(it = this->objectsVec->begin() ; it != this->objectsVec->end() ; it++) {
                this->dynamicsWorld->addRigidBody((*it)->getRigidBody());
            }
        }

        btDiscreteDynamicsWorld * getDynamicsWorld() {
            return this->dynamicsWorld;
        }

        ~BulletEnvironment() {
            std::vector<botsim::Object *>::iterator it;
            for(it = this->objectsVec->begin() ; it != this->objectsVec->end() ; it++) {
                delete (*it);
            }

            delete this->dynamicsWorld;

            delete this->constraintSolver;
            delete this->collisionConfiguration;
            delete this->collisionDispatcher;
            delete this->broadphase;
        }
};

// OSG.CPP ////////////////////////////////////////////////////////////////////

class PhysicsCallback : public osg::NodeCallback {
    // This callback should be applied only to the root osgNode as physics
    // should be updated once per traversal.
    private:
        BulletEnvironment * bulletEnvironment;
        std::vector<botsim::Object *> * objectsVec; //

    public:
        PhysicsCallback(BulletEnvironment * bullet_environment, std::vector<botsim::Object *> * objects_vec) {
            this->bulletEnvironment = bullet_environment;
            this->objectsVec = objects_vec;
        }

        virtual void operator() (osg::Node * node, osg::NodeVisitor * nv) {
            // Update the physics
            this->bulletEnvironment->getDynamicsWorld()->stepSimulation(1 / 60.f, 10);

            // Update the position of each objects
            std::vector<botsim::Object *>::iterator it;
            for(it = this->objectsVec->begin() ; it != this->objectsVec->end() ; it++) {
                // Bullet
                btTransform bulletTransform;
                (*it)->getRigidBody()->getMotionState()->getWorldTransform(bulletTransform);

                // OSG
                (*it)->getOSGPAT()->setPosition(osg::Vec3(bulletTransform.getOrigin().getX(),
                                                          bulletTransform.getOrigin().getY(),
                                                          bulletTransform.getOrigin().getZ()));
                (*it)->getOSGPAT()->setAttitude(osg::Quat(bulletTransform.getRotation().x(),
                                                          bulletTransform.getRotation().y(),
                                                          bulletTransform.getRotation().z(),
                                                          bulletTransform.getRotation().w()));

                // Debug
                //std::cout << bulletTransform.getOrigin().getZ() << std::endl;
            }

            // Continue the traversal
            traverse(node, nv);
        }
};

class OSGEnvironment {

    // TODO: cette classe devrait être un singleton ?!

    private:
        osgViewer::Viewer * viewer;

    public:
        OSGEnvironment(BulletEnvironment * bullet_environment, std::vector<botsim::Object *> * objects_vec) {

            // Make the scene graph
            osg::Group * root = new osg::Group();
            root->setUpdateCallback(new PhysicsCallback(bullet_environment, objects_vec)); // Physics is updated when root is traversed

            // Add objects
            std::vector<botsim::Object *>::iterator it;
            for(it = objects_vec->begin() ; it != objects_vec->end() ; it++) {
                root->addChild((*it)->getOSGPAT());
            }

            // Make the viewer
            this->viewer = new osgViewer::Viewer();
            this->viewer->setSceneData(root);
        }

        void run() {
            this->viewer->run();
        }

        ~OSGEnvironment() {
            delete this->viewer;
        }
};

// MAIN.CPP ///////////////////////////////////////////////////////////////////

int main(int, char **) {

    // Init Bullet //////////////////////////////////////////////////////////////////////

    std::vector<botsim::Object *> * objects_vec = new std::vector<botsim::Object *>;
    objects_vec->push_back(new botsim::Ground());
    objects_vec->push_back(new botsim::Box(Eigen::Vector3d(1., 1., 1.), Eigen::Vector3d(0., 0., 20.), Eigen::Vector4d(0., 0., 0., 1.), Eigen::Vector3d(1., 0., 5.), Eigen::Vector3d(1., 1., 1.), Eigen::Vector3d(0., 0., 0.), 1.));
    objects_vec->push_back(new botsim::Box(Eigen::Vector3d(1., 3., 1.), Eigen::Vector3d(0., 0., 30.), Eigen::Vector4d(0., 0., 0., 1.), Eigen::Vector3d(0., 0., 0.), Eigen::Vector3d(0., 0., 0.), Eigen::Vector3d(0., 0., 0.), 1.));
    objects_vec->push_back(new botsim::Box(Eigen::Vector3d(2., 2., 2.), Eigen::Vector3d(0., 0., 40.), Eigen::Vector4d(0., 0., 0., 1.), Eigen::Vector3d(0., 0., 0.), Eigen::Vector3d(0., 0., 0.), Eigen::Vector3d(0., 0., 0.), 3.));
    objects_vec->push_back(new botsim::Box(Eigen::Vector3d(1., 1., 1.), Eigen::Vector3d(0., 0., 50.), Eigen::Vector4d(0., 0., 0., 1.), Eigen::Vector3d(0., 0., 0.), Eigen::Vector3d(0., 0., 0.), Eigen::Vector3d(0., 0., 0.), 1.));

    BulletEnvironment * bullet_environment = new BulletEnvironment(objects_vec);

    // Init OSG /////////////////////////////////////////////////////////////////////////

    OSGEnvironment * osg_environment = new OSGEnvironment(bullet_environment, objects_vec);

    // Run the simulation ///////////////////////////////////////////////////////////////

    osg_environment->run();

    // Clean Bullet /////////////////////////////////////////////////////////////////////

    delete bullet_environment;
    delete osg_environment;
    // TODO: delete object_vec and its contents

    return 0;
}
<commit_msg>Add antialiasing and a black background.<commit_after>#include <vector>
#include <iostream>

#include <osg/Group>
#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/PositionAttitudeTransform>
#include <osgViewer/Viewer>

#include <Eigen/Dense>

// TODO:
// x Utiliser eigen pour les vecteur donnés aux constructeurs des Objets
// x MSAA
// x Black background
// - Permettre de configurer le refresh rate ou de passer en mode "temps réel"
// - Séparer les modules
// - Ajouter des objets: sphere, cylindre, etc.
// - Objets STL
// - Light
// - Améliorer l'objet "Ground" (tuiles blanches et noires) + fog + LOD
// - Key start/stop recording -> screencast
// - Key take screenshot
// - Key reset
// - Ombres
// - Faire des vidéos et les poster sur jdhp
//
// - Logs (JSON ?)
// - Permettre de lancer une simulation sans interface graphique (sans osg) -> permetter de remplacer le "physicsCallback"
// - Remplacer le makefile par un cmakelist
// - Créer une arborescence et des modules .h/.cpp
//
// - Check units (mm ?, kg ?, ...)
// - Vérifier à la main une simulation simple (calculer à la main l'équation d'un objet qui tombe et comparer avec bullet)
//
// - Singleton OSG / Bullet ? -> bof...
// - Caméra
// - Hinges
// - Commandes d'entrée pour hinge
// - Txt infos (hinge constraints, ...)

// OBJECT.CPP /////////////////////////////////////////////////////////////////

#include <btBulletDynamicsCommon.h>

namespace botsim {

    class Object {
        protected:
            // Bullet
            btRigidBody * rigidBody;

            // OSG
            osg::Group * osgGroup;
            osg::PositionAttitudeTransform * osgPAT;

        public:
            btRigidBody * getRigidBody() {
                return this->rigidBody;
            }

            osg::Node * getOSGGroup() {
                return this->osgGroup;
            }

            osg::PositionAttitudeTransform * getOSGPAT() {
                return this->osgPAT;
            }
    };

    class Box: public botsim::Object {
        protected:
            // Bullet
            btCollisionShape * boxShape; // TODO: rename this
            btDefaultMotionState * boxMotionState; // TODO: rename this

            // Osg
            osg::Box * osgBox;
            osg::ShapeDrawable * osgShapeDrawable;
            osg::Geode * osgGeode;

            // Common
            Eigen::Vector3d initialDimension;         // which unit ? mm ?
            Eigen::Vector3d initialPosition;          // which unit ? mm ?
            Eigen::Vector4d initialAngle;             // which unit ? rad ? deg ?
            Eigen::Vector3d initialInertia;           // which unit ? mm/s ?
            Eigen::Vector3d initialVelocity;          // which unit ? mm/s ?
            Eigen::Vector3d initialAngularVelocity;   // which unit ? mm/s ?
            double mass;                              // which unit ? Kg ?

        public:
            Box(Eigen::Vector3d initial_dimension, Eigen::Vector3d initial_position, Eigen::Vector4d initial_angle, Eigen::Vector3d initial_velocity, Eigen::Vector3d initial_angular_velocity, Eigen::Vector3d initial_inertia, double mass) {

                this->initialDimension = initial_dimension;
                this->initialPosition = initial_position;
                this->initialAngle = initial_angle;
                this->initialInertia = initial_inertia;
                this->initialVelocity = initial_velocity;
                this->initialAngularVelocity = initial_angular_velocity;
                this->mass = mass;

                // BULLET
                btVector3 bt_box_shape(this->initialDimension(0)/2., this->initialDimension(1)/2., this->initialDimension(2)/2.);
                this->boxShape = new btBoxShape(bt_box_shape); // this is half lengths...

                btScalar bt_mass = this->mass;
                btVector3 bt_box_inertia(this->initialInertia(0), this->initialInertia(1), this->initialInertia(2));
                this->boxShape->calculateLocalInertia(bt_mass, bt_box_inertia);

                btQuaternion bt_angle(this->initialAngle(0), this->initialAngle(1), this->initialAngle(2), this->initialAngle(3));
                btVector3 bt_position(this->initialPosition(0), this->initialPosition(1), this->initialPosition(2));
                this->boxMotionState = new btDefaultMotionState(btTransform(bt_angle, bt_position));

                btRigidBody::btRigidBodyConstructionInfo box_rigid_body_ci(mass, this->boxMotionState, this->boxShape, bt_box_inertia);
                this->rigidBody = new btRigidBody(box_rigid_body_ci);

                btVector3 bt_velocity(this->initialVelocity(0), this->initialVelocity(1), this->initialVelocity(2));
                this->rigidBody->setLinearVelocity(bt_velocity);

                btVector3 bt_angular_velocity(this->initialAngularVelocity(0), this->initialAngularVelocity(1), this->initialAngularVelocity(2));
                this->rigidBody->setAngularVelocity(bt_angular_velocity);

                // OSG
                this->osgBox = new osg::Box(osg::Vec3(0, 0, 0), this->initialDimension(0), this->initialDimension(1), this->initialDimension(2));
                this->osgShapeDrawable = new osg::ShapeDrawable(this->osgBox);
                this->osgGeode = new osg::Geode();
                this->osgGeode->addDrawable(osgShapeDrawable);

                this->osgGroup = new osg::Group();
                this->osgGroup->addChild(this->osgGeode);

                this->osgPAT = new osg::PositionAttitudeTransform();
                this->osgPAT->addChild(this->osgGroup);
            }

            ~Box() {
                delete this->rigidBody->getMotionState(); // TODO ?
                delete this->rigidBody; // TODO ?

                delete this->boxShape;
                delete this->boxMotionState;

                //delete this->osgBox;
                //delete this->osgShapeDrawable;
                //delete this->osgGeode;
                //delete this->osgPAT;
            }
    };

    class Ground: public botsim::Object {
        private:
            // Bullet
            btCollisionShape * groundShape;
            btDefaultMotionState * groundMotionState;

            // Osg
            osg::Box * osgBox;
            osg::ShapeDrawable * osgShapeDrawable;
            osg::Geode * osgGeode;

        public:
            Ground() {
                // BULLET
                this->groundShape = new btStaticPlaneShape(btVector3(0, 0, 1), 0);

                this->groundMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1), btVector3(0,0,0)));
                btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI(0, this->groundMotionState, this->groundShape, btVector3(0, 0, 0));
                this->rigidBody = new btRigidBody(groundRigidBodyCI);

                // OSG
                this->osgBox = new osg::Box(osg::Vec3(0, 0, -1), 1.0f);
                this->osgBox->setHalfLengths(osg::Vec3(20, 20, 1));
                this->osgShapeDrawable = new osg::ShapeDrawable(this->osgBox);
                this->osgGeode = new osg::Geode();
                this->osgGeode->addDrawable(osgShapeDrawable);

                this->osgGroup = new osg::Group();
                this->osgGroup->addChild(this->osgGeode);

                this->osgPAT = new osg::PositionAttitudeTransform();
                this->osgPAT->addChild(this->osgGroup);
            }

            ~Ground() {
                delete this->rigidBody->getMotionState(); // TODO ?
                delete this->rigidBody; // TODO ?

                delete this->groundShape;
                delete this->groundMotionState;

                //delete this->osgBox;
                //delete this->osgShapeDrawable;
                //delete this->osgGeode;
                //delete this->osgPAT;
            }
    };
}

// BULLET.CPP /////////////////////////////////////////////////////////////////

class BulletEnvironment {

    // TODO: cette classe devrait être un singleton ?!

    private:
        btDiscreteDynamicsWorld * dynamicsWorld;
        btDbvtBroadphase * broadphase;
        btDefaultCollisionConfiguration * collisionConfiguration;
        btCollisionDispatcher * collisionDispatcher;
        btSequentialImpulseConstraintSolver * constraintSolver;

        std::vector<botsim::Object *> * objectsVec;

        double gravity;

    public:
        BulletEnvironment(std::vector<botsim::Object *> * objects_vec) {
            this->gravity = -10.;

            this->broadphase = new btDbvtBroadphase();

            this->collisionConfiguration = new btDefaultCollisionConfiguration();
            this->collisionDispatcher = new btCollisionDispatcher(this->collisionConfiguration);

            this->constraintSolver = new btSequentialImpulseConstraintSolver();

            this->dynamicsWorld = new btDiscreteDynamicsWorld(this->collisionDispatcher,
                    this->broadphase,
                    this->constraintSolver,
                    this->collisionConfiguration);
            this->dynamicsWorld->setGravity(btVector3(0, 0, this->gravity));

            this->objectsVec = objects_vec;

            // Add rigid bodies
            std::vector<botsim::Object *>::iterator it;
            for(it = this->objectsVec->begin() ; it != this->objectsVec->end() ; it++) {
                this->dynamicsWorld->addRigidBody((*it)->getRigidBody());
            }
        }

        btDiscreteDynamicsWorld * getDynamicsWorld() {
            return this->dynamicsWorld;
        }

        ~BulletEnvironment() {
            std::vector<botsim::Object *>::iterator it;
            for(it = this->objectsVec->begin() ; it != this->objectsVec->end() ; it++) {
                delete (*it);
            }

            delete this->dynamicsWorld;

            delete this->constraintSolver;
            delete this->collisionConfiguration;
            delete this->collisionDispatcher;
            delete this->broadphase;
        }
};

// OSG.CPP ////////////////////////////////////////////////////////////////////

class PhysicsCallback : public osg::NodeCallback {
    // This callback should be applied only to the root osgNode as physics
    // should be updated once per traversal.
    private:
        BulletEnvironment * bulletEnvironment;
        std::vector<botsim::Object *> * objectsVec; //

    public:
        PhysicsCallback(BulletEnvironment * bullet_environment, std::vector<botsim::Object *> * objects_vec) {
            this->bulletEnvironment = bullet_environment;
            this->objectsVec = objects_vec;
        }

        virtual void operator() (osg::Node * node, osg::NodeVisitor * nv) {
            // Update the physics
            this->bulletEnvironment->getDynamicsWorld()->stepSimulation(1 / 60.f, 10);

            // Update the position of each objects
            std::vector<botsim::Object *>::iterator it;
            for(it = this->objectsVec->begin() ; it != this->objectsVec->end() ; it++) {
                // Bullet
                btTransform bulletTransform;
                (*it)->getRigidBody()->getMotionState()->getWorldTransform(bulletTransform);

                // OSG
                (*it)->getOSGPAT()->setPosition(osg::Vec3(bulletTransform.getOrigin().getX(),
                                                          bulletTransform.getOrigin().getY(),
                                                          bulletTransform.getOrigin().getZ()));
                (*it)->getOSGPAT()->setAttitude(osg::Quat(bulletTransform.getRotation().x(),
                                                          bulletTransform.getRotation().y(),
                                                          bulletTransform.getRotation().z(),
                                                          bulletTransform.getRotation().w()));

                // Debug
                //std::cout << bulletTransform.getOrigin().getZ() << std::endl;
            }

            // Continue the traversal
            traverse(node, nv);
        }
};

class OSGEnvironment {

    // TODO: cette classe devrait être un singleton ?!

    private:
        osgViewer::Viewer * viewer;

    public:
        OSGEnvironment(BulletEnvironment * bullet_environment, std::vector<botsim::Object *> * objects_vec) {

            // Make the scene graph
            osg::Group * root = new osg::Group();
            root->setUpdateCallback(new PhysicsCallback(bullet_environment, objects_vec)); // Physics is updated when root is traversed

            // Add objects
            std::vector<botsim::Object *>::iterator it;
            for(it = objects_vec->begin() ; it != objects_vec->end() ; it++) {
                root->addChild((*it)->getOSGPAT());
            }

            // Make the viewer
            this->viewer = new osgViewer::Viewer();
            this->viewer->setSceneData(root);

            // Set the background color (black here -> (0,0,0,0))
            this->viewer->getCamera()->setClearColor(osg::Vec4(0.0f, 0.0f, 0.0f, 0.0f));

            // MSAA: multi-sampled_anti-aliasing
            // See http://gaming.stackexchange.com/questions/31801/what-are-the-differences-between-the-different-anti-aliasing-multisampling-set
            //     http://osghelp.com/?p=179
            osg::DisplaySettings::instance()->setNumMultiSamples(4); // MSAA: multi-sampled_anti-aliasing
        }

        void run() {
            this->viewer->run();
        }

        ~OSGEnvironment() {
            delete this->viewer;
        }
};

// MAIN.CPP ///////////////////////////////////////////////////////////////////

int main(int, char **) {

    // Init Bullet //////////////////////////////////////////////////////////////////////

    std::vector<botsim::Object *> * objects_vec = new std::vector<botsim::Object *>;
    objects_vec->push_back(new botsim::Ground());
    objects_vec->push_back(new botsim::Box(Eigen::Vector3d(1., 1., 1.), Eigen::Vector3d(0., 0., 20.), Eigen::Vector4d(0., 0., 0., 1.), Eigen::Vector3d(1., 0., 5.), Eigen::Vector3d(1., 1., 1.), Eigen::Vector3d(0., 0., 0.), 1.));
    objects_vec->push_back(new botsim::Box(Eigen::Vector3d(1., 3., 1.), Eigen::Vector3d(0., 0., 30.), Eigen::Vector4d(0., 0., 0., 1.), Eigen::Vector3d(0., 0., 0.), Eigen::Vector3d(0., 0., 0.), Eigen::Vector3d(0., 0., 0.), 1.));
    objects_vec->push_back(new botsim::Box(Eigen::Vector3d(2., 2., 2.), Eigen::Vector3d(0., 0., 40.), Eigen::Vector4d(0., 0., 0., 1.), Eigen::Vector3d(0., 0., 0.), Eigen::Vector3d(0., 0., 0.), Eigen::Vector3d(0., 0., 0.), 3.));
    objects_vec->push_back(new botsim::Box(Eigen::Vector3d(1., 1., 1.), Eigen::Vector3d(0., 0., 50.), Eigen::Vector4d(0., 0., 0., 1.), Eigen::Vector3d(0., 0., 0.), Eigen::Vector3d(0., 0., 0.), Eigen::Vector3d(0., 0., 0.), 1.));

    BulletEnvironment * bullet_environment = new BulletEnvironment(objects_vec);

    // Init OSG /////////////////////////////////////////////////////////////////////////

    OSGEnvironment * osg_environment = new OSGEnvironment(bullet_environment, objects_vec);

    // Run the simulation ///////////////////////////////////////////////////////////////

    osg_environment->run();

    // Clean Bullet /////////////////////////////////////////////////////////////////////

    delete bullet_environment;
    delete osg_environment;
    // TODO: delete object_vec and its contents

    return 0;
}
<|endoftext|>


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

#include <tuple>
#include <string>

#include <gtest/gtest.h>

#include "joynr/MutableMessageFactory.h"
#include "joynr/MutableMessage.h"
#include "joynr/ImmutableMessage.h"
#include "joynr/Request.h"
#include "joynr/PrivateCopyAssign.h"
#include "tests/utils/MockObjects.h"
#include "libjoynrclustercontroller/access-control/AccessController.h"
#include "libjoynrclustercontroller/access-control/LocalDomainAccessStore.h"
#include "joynr/types/DiscoveryEntry.h"
#include "joynr/types/Version.h"
#include "joynr/SingleThreadedIOService.h"
#include "joynr/serializer/Serializer.h"

using namespace ::testing;
using namespace joynr;
using namespace joynr::types;
using namespace joynr::infrastructure;
using namespace joynr::infrastructure::DacTypes;

template <typename... Ts>
joynr::Request initOutgoingRequest(std::string methodName, std::vector<std::string> paramDataTypes, Ts... paramValues)
{
    Request outgoingRequest;
    outgoingRequest.setMethodName(methodName);
    outgoingRequest.setParamDatatypes(std::move(paramDataTypes));
    outgoingRequest.setParams(std::move(paramValues)...);
    return outgoingRequest;
}

// Mock objects cannot make callbacks themselves but can make calls to methods
// with the same arguments as the mocked method call.
class ConsumerPermissionCallbackMaker
{
public:
    explicit ConsumerPermissionCallbackMaker(Permission::Enum permission) :
        permission(permission)
    {}

    void consumerPermission(
            const std::string& userId,
            const std::string& domain,
            const std::string& interfaceName,
            TrustLevel::Enum trustLevel,
            std::shared_ptr<LocalDomainAccessController::IGetPermissionCallback> callback
    ) {
        std::ignore = userId;
        std::ignore = domain;
        std::ignore = interfaceName;
        std::ignore = trustLevel;
        callback->permission(permission);
    }

    void operationNeeded(
            const std::string& userId,
            const std::string& domain,
            const std::string& interfaceName,
            TrustLevel::Enum trustLevel,
            std::shared_ptr<LocalDomainAccessController::IGetPermissionCallback> callback
    ) {
        std::ignore = userId;
        std::ignore = domain;
        std::ignore = interfaceName;
        std::ignore = trustLevel;
        callback->operationNeeded();
    }

private:
    Permission::Enum permission;
};

class AccessControllerTest : public ::testing::Test {
public:
    AccessControllerTest() :
        singleThreadedIOService(),
        localDomainAccessControllerMock(std::make_shared<MockLocalDomainAccessController>(std::make_unique<LocalDomainAccessStore>(), false)),
        accessControllerCallback(std::make_shared<MockConsumerPermissionCallback>()),
        settings(),
        messagingSettingsMock(settings),
        localCapabilitiesDirectoryMock(std::make_shared<MockLocalCapabilitiesDirectory>(messagingSettingsMock, settings, singleThreadedIOService.getIOService())),
        accessController(
                localCapabilitiesDirectoryMock,
                localDomainAccessControllerMock
        )
    {
        singleThreadedIOService.start();
    }

    ~AccessControllerTest() = default;

    void invokeOnSuccessCallbackFct (std::string participantId,
                            std::function<void(const joynr::types::DiscoveryEntryWithMetaInfo&)> onSuccess,
                            std::function<void(const joynr::exceptions::ProviderRuntimeException&)> onError) {
        std::ignore = participantId;
        onSuccess(discoveryEntry);
    }

    std::shared_ptr<ImmutableMessage> getImmutableMessage()
    {
        std::shared_ptr<ImmutableMessage> immutableMessage = mutableMessage.getImmutableMessage();
        immutableMessage->setCreator(DUMMY_USERID);
        return immutableMessage;
    }

    void SetUp(){
        messagingQos = MessagingQos(5000);
        const bool isLocalMessage = true;
        mutableMessage = messageFactory.createRequest(fromParticipantId,
                                     toParticipantId,
                                     messagingQos,
                                     initOutgoingRequest(TEST_OPERATION, {}),
                                     isLocalMessage);

        ON_CALL(
                messagingSettingsMock,
                getDiscoveryDirectoriesDomain()
        )
                .WillByDefault(Return("fooDomain"));
        ON_CALL(
                messagingSettingsMock,
                getCapabilitiesDirectoryParticipantId()
        )
                .WillByDefault(Return("fooParticipantId"));

        std::int64_t lastSeenDateMs = 0;
        std::int64_t expiryDateMs = 0;
        joynr::types::Version providerVersion(47, 11);
        discoveryEntry = DiscoveryEntryWithMetaInfo(
                providerVersion,
                TEST_DOMAIN,
                TEST_INTERFACE,
                toParticipantId,
                types::ProviderQos(),
                lastSeenDateMs,
                expiryDateMs,
                TEST_PUBLICKEYID,
                false
        );
    }

    void prepareConsumerTest() {
        EXPECT_CALL(
                *localCapabilitiesDirectoryMock,
                lookup(toParticipantId,
                       A<std::function<void(const joynr::types::DiscoveryEntryWithMetaInfo&)>>(),
                       A<std::function<void(const joynr::exceptions::ProviderRuntimeException&)>>())
        )
                .Times(1)
                .WillOnce(Invoke(this, &AccessControllerTest::invokeOnSuccessCallbackFct));
    }

protected:
    SingleThreadedIOService singleThreadedIOService;
    std::shared_ptr<MockLocalDomainAccessController> localDomainAccessControllerMock;
    std::shared_ptr<MockConsumerPermissionCallback> accessControllerCallback;
    Settings settings;
    MockMessagingSettings messagingSettingsMock;
    std::shared_ptr<MockLocalCapabilitiesDirectory> localCapabilitiesDirectoryMock;
    AccessController accessController;
    MutableMessageFactory messageFactory;
    MutableMessage mutableMessage;
    MessagingQos messagingQos;
    DiscoveryEntryWithMetaInfo discoveryEntry;
    static const std::string fromParticipantId;
    static const std::string toParticipantId;
    static const std::string replyToChannelId;
    static const std::string DUMMY_USERID;
    static const std::string TEST_DOMAIN;
    static const std::string TEST_INTERFACE;
    static const std::string TEST_OPERATION;
    static const std::string TEST_PUBLICKEYID;
private:
    DISALLOW_COPY_AND_ASSIGN(AccessControllerTest);
};

//----- Constants --------------------------------------------------------------
const std::string AccessControllerTest::fromParticipantId("sender");
const std::string AccessControllerTest::toParticipantId("receiver");
const std::string AccessControllerTest::replyToChannelId("replyToId");
const std::string AccessControllerTest::DUMMY_USERID("testUserId");
const std::string AccessControllerTest::TEST_DOMAIN("testDomain");
const std::string AccessControllerTest::TEST_INTERFACE("testInterface");
const std::string AccessControllerTest::TEST_OPERATION("testOperation");
const std::string AccessControllerTest::TEST_PUBLICKEYID("publicKeyId");

//----- Tests ------------------------------------------------------------------

TEST_F(AccessControllerTest, accessWithInterfaceLevelAccessControl) {
    prepareConsumerTest();
    ConsumerPermissionCallbackMaker makeCallback(Permission::YES);
    EXPECT_CALL(
            *localDomainAccessControllerMock,
            getConsumerPermission(DUMMY_USERID, TEST_DOMAIN, TEST_INTERFACE, TrustLevel::HIGH, _)
    )
            .Times(1)
            .WillOnce(Invoke(&makeCallback, &ConsumerPermissionCallbackMaker::consumerPermission));

    EXPECT_CALL(*accessControllerCallback, hasConsumerPermission(true))
            .Times(1);

    accessController.hasConsumerPermission(
            getImmutableMessage(),
            std::dynamic_pointer_cast<IAccessController::IHasConsumerPermissionCallback>(accessControllerCallback)
    );
}

TEST_F(AccessControllerTest, accessWithOperationLevelAccessControl) {
    prepareConsumerTest();
    ConsumerPermissionCallbackMaker makeCallback(Permission::YES);
    EXPECT_CALL(
            *localDomainAccessControllerMock,
            getConsumerPermission(DUMMY_USERID, TEST_DOMAIN, TEST_INTERFACE, TrustLevel::HIGH, _)
    )
            .Times(1)
            .WillOnce(Invoke(&makeCallback, &ConsumerPermissionCallbackMaker::operationNeeded));

    Permission::Enum permissionYes = Permission::YES;
    DefaultValue<Permission::Enum>::Set(permissionYes);
    EXPECT_CALL(
            *localDomainAccessControllerMock,
            getConsumerPermission(
                    DUMMY_USERID,
                    TEST_DOMAIN,
                    TEST_INTERFACE,
                    TEST_OPERATION,
                    TrustLevel::HIGH
            )
    )
            .WillOnce(Return(permissionYes));

    EXPECT_CALL(*accessControllerCallback, hasConsumerPermission(true))
            .Times(1);

    accessController.hasConsumerPermission(
            getImmutableMessage(),
            std::dynamic_pointer_cast<IAccessController::IHasConsumerPermissionCallback>(accessControllerCallback)
    );
}

TEST_F(AccessControllerTest, accessWithOperationLevelAccessControlAndFaultyMessage) {
    prepareConsumerTest();
    ConsumerPermissionCallbackMaker makeCallback(Permission::YES);
    EXPECT_CALL(
            *localDomainAccessControllerMock,
            getConsumerPermission(DUMMY_USERID, TEST_DOMAIN, TEST_INTERFACE, TrustLevel::HIGH, _)
    )
            .Times(1)
            .WillOnce(Invoke(&makeCallback, &ConsumerPermissionCallbackMaker::operationNeeded));

    EXPECT_CALL(*accessControllerCallback, hasConsumerPermission(false))
            .Times(1);

    std::string payload("invalid serialization of Request object");
    mutableMessage.setPayload(payload);

    accessController.hasConsumerPermission(
            getImmutableMessage(),
            std::dynamic_pointer_cast<IAccessController::IHasConsumerPermissionCallback>(accessControllerCallback)
    );
}

TEST_F(AccessControllerTest, hasProviderPermission) {
    Permission::Enum permissionYes = Permission::YES;
    DefaultValue<Permission::Enum>::Set(permissionYes);
    EXPECT_CALL(
            *localDomainAccessControllerMock,
            getProviderPermission(_, _, _, _)
    )
            .Times(1)
            .WillOnce(Return(permissionYes));
    bool retval = accessController.hasProviderPermission(DUMMY_USERID, TrustLevel::HIGH, TEST_DOMAIN, TEST_INTERFACE);
    EXPECT_TRUE(retval);
}

TEST_F(AccessControllerTest, hasNoProviderPermission) {
    Permission::Enum permissionNo = Permission::NO;
    DefaultValue<Permission::Enum>::Set(permissionNo);
    EXPECT_CALL(
            *localDomainAccessControllerMock,
            getProviderPermission(_, _, _, _)
    )
            .Times(1)
            .WillOnce(Return(permissionNo));
    bool retval = accessController.hasProviderPermission(DUMMY_USERID, TrustLevel::HIGH, TEST_DOMAIN, TEST_INTERFACE);
    EXPECT_FALSE(retval);
}
<commit_msg>[C++] Test case for access control check. Consumer has no permission<commit_after>/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2017 BMW Car IT GmbH
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

#include <tuple>
#include <string>

#include <gtest/gtest.h>

#include "joynr/MutableMessageFactory.h"
#include "joynr/MutableMessage.h"
#include "joynr/ImmutableMessage.h"
#include "joynr/Request.h"
#include "joynr/PrivateCopyAssign.h"
#include "tests/utils/MockObjects.h"
#include "libjoynrclustercontroller/access-control/AccessController.h"
#include "libjoynrclustercontroller/access-control/LocalDomainAccessStore.h"
#include "joynr/types/DiscoveryEntry.h"
#include "joynr/types/Version.h"
#include "joynr/SingleThreadedIOService.h"
#include "joynr/serializer/Serializer.h"

using namespace ::testing;
using namespace joynr;
using namespace joynr::types;
using namespace joynr::infrastructure;
using namespace joynr::infrastructure::DacTypes;

template <typename... Ts>
joynr::Request initOutgoingRequest(std::string methodName, std::vector<std::string> paramDataTypes, Ts... paramValues)
{
    Request outgoingRequest;
    outgoingRequest.setMethodName(methodName);
    outgoingRequest.setParamDatatypes(std::move(paramDataTypes));
    outgoingRequest.setParams(std::move(paramValues)...);
    return outgoingRequest;
}

// Mock objects cannot make callbacks themselves but can make calls to methods
// with the same arguments as the mocked method call.
class ConsumerPermissionCallbackMaker
{
public:
    explicit ConsumerPermissionCallbackMaker(Permission::Enum permission) :
        permission(permission)
    {}

    void consumerPermission(
            const std::string& userId,
            const std::string& domain,
            const std::string& interfaceName,
            TrustLevel::Enum trustLevel,
            std::shared_ptr<LocalDomainAccessController::IGetPermissionCallback> callback
    ) {
        std::ignore = userId;
        std::ignore = domain;
        std::ignore = interfaceName;
        std::ignore = trustLevel;
        callback->permission(permission);
    }

    void operationNeeded(
            const std::string& userId,
            const std::string& domain,
            const std::string& interfaceName,
            TrustLevel::Enum trustLevel,
            std::shared_ptr<LocalDomainAccessController::IGetPermissionCallback> callback
    ) {
        std::ignore = userId;
        std::ignore = domain;
        std::ignore = interfaceName;
        std::ignore = trustLevel;
        callback->operationNeeded();
    }

private:
    Permission::Enum permission;
};

class AccessControllerTest : public ::testing::Test {
public:
    AccessControllerTest() :
        singleThreadedIOService(),
        localDomainAccessControllerMock(std::make_shared<MockLocalDomainAccessController>(std::make_unique<LocalDomainAccessStore>(), false)),
        accessControllerCallback(std::make_shared<MockConsumerPermissionCallback>()),
        settings(),
        messagingSettingsMock(settings),
        localCapabilitiesDirectoryMock(std::make_shared<MockLocalCapabilitiesDirectory>(messagingSettingsMock, settings, singleThreadedIOService.getIOService())),
        accessController(
                localCapabilitiesDirectoryMock,
                localDomainAccessControllerMock
        ),
        messagingQos(MessagingQos(5000))
    {
        singleThreadedIOService.start();
    }

    ~AccessControllerTest() = default;

    void invokeOnSuccessCallbackFct (std::string participantId,
                            std::function<void(const joynr::types::DiscoveryEntryWithMetaInfo&)> onSuccess,
                            std::function<void(const joynr::exceptions::ProviderRuntimeException&)> onError) {
        std::ignore = participantId;
        onSuccess(discoveryEntry);
    }

    std::shared_ptr<ImmutableMessage> getImmutableMessage()
    {
        std::shared_ptr<ImmutableMessage> immutableMessage = mutableMessage.getImmutableMessage();
        immutableMessage->setCreator(DUMMY_USERID);
        return immutableMessage;
    }

    void SetUp(){
        mutableMessage = messageFactory.createRequest(fromParticipantId,
                                     toParticipantId,
                                     messagingQos,
                                     initOutgoingRequest(TEST_OPERATION, {}),
                                     isLocalMessage);

        ON_CALL(
                messagingSettingsMock,
                getDiscoveryDirectoriesDomain()
        )
                .WillByDefault(Return("fooDomain"));
        ON_CALL(
                messagingSettingsMock,
                getCapabilitiesDirectoryParticipantId()
        )
                .WillByDefault(Return("fooParticipantId"));

        std::int64_t lastSeenDateMs = 0;
        std::int64_t expiryDateMs = 0;
        joynr::types::Version providerVersion(47, 11);
        discoveryEntry = DiscoveryEntryWithMetaInfo(
                providerVersion,
                TEST_DOMAIN,
                TEST_INTERFACE,
                toParticipantId,
                types::ProviderQos(),
                lastSeenDateMs,
                expiryDateMs,
                TEST_PUBLICKEYID,
                false
        );
    }

    void prepareConsumerTest() {
        EXPECT_CALL(
                *localCapabilitiesDirectoryMock,
                lookup(toParticipantId,
                       A<std::function<void(const joynr::types::DiscoveryEntryWithMetaInfo&)>>(),
                       A<std::function<void(const joynr::exceptions::ProviderRuntimeException&)>>())
        )
                .Times(1)
                .WillOnce(Invoke(this, &AccessControllerTest::invokeOnSuccessCallbackFct));
    }

    void testPermission(Permission::Enum testPermission, bool expectedPermission)
    {
        prepareConsumerTest();
        std::shared_ptr<ImmutableMessage> immutableMessage = mutableMessage.getImmutableMessage();
        immutableMessage->setCreator(DUMMY_USERID);

        ConsumerPermissionCallbackMaker makeCallback(testPermission);
        EXPECT_CALL(
                *localDomainAccessControllerMock,
                getConsumerPermission(DUMMY_USERID, TEST_DOMAIN, TEST_INTERFACE, TrustLevel::HIGH, _)
        )
                .WillOnce(Invoke(&makeCallback, &ConsumerPermissionCallbackMaker::consumerPermission));
        EXPECT_CALL(*accessControllerCallback, hasConsumerPermission(expectedPermission))
                .Times(1);

        // pass the immutable message to hasConsumerPermission
        accessController.hasConsumerPermission(
                immutableMessage,
                std::static_pointer_cast<IAccessController::IHasConsumerPermissionCallback>(accessControllerCallback)
        );
    }

protected:
    SingleThreadedIOService singleThreadedIOService;
    std::shared_ptr<MockLocalDomainAccessController> localDomainAccessControllerMock;
    std::shared_ptr<MockConsumerPermissionCallback> accessControllerCallback;
    Settings settings;
    MockMessagingSettings messagingSettingsMock;
    std::shared_ptr<MockLocalCapabilitiesDirectory> localCapabilitiesDirectoryMock;
    AccessController accessController;
    MutableMessageFactory messageFactory;
    MutableMessage mutableMessage;
    MessagingQos messagingQos;
    const bool isLocalMessage = true;
    DiscoveryEntryWithMetaInfo discoveryEntry;
    static const std::string fromParticipantId;
    static const std::string toParticipantId;
    static const std::string subscriptionId;
    static const std::string replyToChannelId;
    static const std::string DUMMY_USERID;
    static const std::string TEST_DOMAIN;
    static const std::string TEST_INTERFACE;
    static const std::string TEST_OPERATION;
    static const std::string TEST_PUBLICKEYID;
private:
    DISALLOW_COPY_AND_ASSIGN(AccessControllerTest);
};

//----- Constants --------------------------------------------------------------
const std::string AccessControllerTest::fromParticipantId("sender");
const std::string AccessControllerTest::toParticipantId("receiver");
const std::string AccessControllerTest::subscriptionId("testSubscriptionId");
const std::string AccessControllerTest::replyToChannelId("replyToId");
const std::string AccessControllerTest::DUMMY_USERID("testUserId");
const std::string AccessControllerTest::TEST_DOMAIN("testDomain");
const std::string AccessControllerTest::TEST_INTERFACE("testInterface");
const std::string AccessControllerTest::TEST_OPERATION("testOperation");
const std::string AccessControllerTest::TEST_PUBLICKEYID("publicKeyId");

//----- Tests ------------------------------------------------------------------

TEST_F(AccessControllerTest, accessWithInterfaceLevelAccessControl) {
    prepareConsumerTest();
    ConsumerPermissionCallbackMaker makeCallback(Permission::YES);
    EXPECT_CALL(
            *localDomainAccessControllerMock,
            getConsumerPermission(DUMMY_USERID, TEST_DOMAIN, TEST_INTERFACE, TrustLevel::HIGH, _)
    )
            .Times(1)
            .WillOnce(Invoke(&makeCallback, &ConsumerPermissionCallbackMaker::consumerPermission));

    EXPECT_CALL(*accessControllerCallback, hasConsumerPermission(true))
            .Times(1);

    accessController.hasConsumerPermission(
            getImmutableMessage(),
            std::dynamic_pointer_cast<IAccessController::IHasConsumerPermissionCallback>(accessControllerCallback)
    );
}

TEST_F(AccessControllerTest, accessWithOperationLevelAccessControl) {
    prepareConsumerTest();
    ConsumerPermissionCallbackMaker makeCallback(Permission::YES);
    EXPECT_CALL(
            *localDomainAccessControllerMock,
            getConsumerPermission(DUMMY_USERID, TEST_DOMAIN, TEST_INTERFACE, TrustLevel::HIGH, _)
    )
            .Times(1)
            .WillOnce(Invoke(&makeCallback, &ConsumerPermissionCallbackMaker::operationNeeded));

    Permission::Enum permissionYes = Permission::YES;
    DefaultValue<Permission::Enum>::Set(permissionYes);
    EXPECT_CALL(
            *localDomainAccessControllerMock,
            getConsumerPermission(
                    DUMMY_USERID,
                    TEST_DOMAIN,
                    TEST_INTERFACE,
                    TEST_OPERATION,
                    TrustLevel::HIGH
            )
    )
            .WillOnce(Return(permissionYes));

    EXPECT_CALL(*accessControllerCallback, hasConsumerPermission(true))
            .Times(1);

    accessController.hasConsumerPermission(
            getImmutableMessage(),
            std::dynamic_pointer_cast<IAccessController::IHasConsumerPermissionCallback>(accessControllerCallback)
    );
}

TEST_F(AccessControllerTest, accessWithOperationLevelAccessControlAndFaultyMessage) {
    prepareConsumerTest();
    ConsumerPermissionCallbackMaker makeCallback(Permission::YES);
    EXPECT_CALL(
            *localDomainAccessControllerMock,
            getConsumerPermission(DUMMY_USERID, TEST_DOMAIN, TEST_INTERFACE, TrustLevel::HIGH, _)
    )
            .Times(1)
            .WillOnce(Invoke(&makeCallback, &ConsumerPermissionCallbackMaker::operationNeeded));

    EXPECT_CALL(*accessControllerCallback, hasConsumerPermission(false))
            .Times(1);

    std::string payload("invalid serialization of Request object");
    mutableMessage.setPayload(payload);

    accessController.hasConsumerPermission(
            getImmutableMessage(),
            std::dynamic_pointer_cast<IAccessController::IHasConsumerPermissionCallback>(accessControllerCallback)
    );
}

TEST_F(AccessControllerTest, hasProviderPermission) {
    Permission::Enum permissionYes = Permission::YES;
    DefaultValue<Permission::Enum>::Set(permissionYes);
    EXPECT_CALL(
            *localDomainAccessControllerMock,
            getProviderPermission(_, _, _, _)
    )
            .Times(1)
            .WillOnce(Return(permissionYes));
    bool retval = accessController.hasProviderPermission(DUMMY_USERID, TrustLevel::HIGH, TEST_DOMAIN, TEST_INTERFACE);
    EXPECT_TRUE(retval);
}

TEST_F(AccessControllerTest, hasNoProviderPermission) {
    Permission::Enum permissionNo = Permission::NO;
    DefaultValue<Permission::Enum>::Set(permissionNo);
    EXPECT_CALL(
            *localDomainAccessControllerMock,
            getProviderPermission(_, _, _, _)
    )
            .Times(1)
            .WillOnce(Return(permissionNo));
    bool retval = accessController.hasProviderPermission(DUMMY_USERID, TrustLevel::HIGH, TEST_DOMAIN, TEST_INTERFACE);
    EXPECT_FALSE(retval);
}

//----- Test Types --------------------------------------------------------------
typedef ::testing::Types<
        SubscriptionRequest,
        MulticastSubscriptionRequest,
        BroadcastSubscriptionRequest
> SubscriptionTypes;

template <typename T>
class AccessControllerSubscriptionTest : public AccessControllerTest {
public:

    template<typename U = T>
    typename std::enable_if_t<std::is_same<U, SubscriptionRequest>::value>
    createMutableMessage()
    {
        SubscriptionRequest subscriptionRequest;
        subscriptionRequest.setSubscriptionId(subscriptionId);
        mutableMessage = messageFactory.createSubscriptionRequest(fromParticipantId,
                                                                  toParticipantId,
                                                                  messagingQos,
                                                                  subscriptionRequest,
                                                                  isLocalMessage);
    }

    template<typename U = T>
    typename std::enable_if_t<std::is_same<U, MulticastSubscriptionRequest>::value>
    createMutableMessage()
    {
        MulticastSubscriptionRequest subscriptionRequest;
        mutableMessage = messageFactory.createMulticastSubscriptionRequest(fromParticipantId,
                                                                  toParticipantId,
                                                                  messagingQos,
                                                                  subscriptionRequest,
                                                                  isLocalMessage);
    }

    template<typename U = T>
    typename std::enable_if_t<std::is_same<U, BroadcastSubscriptionRequest>::value>
    createMutableMessage()
    {
        BroadcastSubscriptionRequest subscriptionRequest;
        mutableMessage = messageFactory.createBroadcastSubscriptionRequest(fromParticipantId,
                                                                  toParticipantId,
                                                                  messagingQos,
                                                                  subscriptionRequest,
                                                                  isLocalMessage);
    }
};

TYPED_TEST_CASE(AccessControllerSubscriptionTest, SubscriptionTypes);

TYPED_TEST(AccessControllerSubscriptionTest, hasNoConsumerPermission) {
    const Permission::Enum permissionNo = Permission::NO;
    const bool expectedPermissionFalse = false;

    this->createMutableMessage();

    std::shared_ptr<ImmutableMessage> immutableMessage = this->mutableMessage.getImmutableMessage();

    this->testPermission(permissionNo, expectedPermissionFalse);
}

TYPED_TEST(AccessControllerSubscriptionTest, hasConsumerPermission) {
    const Permission::Enum permissionNo = Permission::YES;
    const bool expectedPermissionFalse = true;

    this->createMutableMessage();

    std::shared_ptr<ImmutableMessage> immutableMessage = this->mutableMessage.getImmutableMessage();

    this->testPermission(permissionNo, expectedPermissionFalse);
}
<|endoftext|>