<commit_before>#pragma once

#include <Automaton.h>

class Atm_player : public Machine {
 public:
  enum { IDLE, START, SOUND, QUIET, NEXT, REPEAT, FINISH };                          // STATES
  enum { EVT_START, EVT_STOP, EVT_TOGGLE, EVT_TIMER, EVT_EOPAT, EVT_REPEAT, ELSE };  // EVENTS
  Atm_player( void ) : Machine(){};
  Atm_player& begin( int pin = -1 );
  Atm_player& trace( Stream& stream );
  Atm_player& trigger( int event );
  int state( void );
  Atm_player& play( int* pat, int size );
  Atm_player& play( int freq, int period, int pause = 0 );
  Atm_player& repeat( uint16_t v );
  Atm_player& speed( float v );
  Atm_player& pitch( float v );
  Atm_player& onFinish( Machine& machine, int event = 0 );
  Atm_player& onFinish( atm_cb_push_t callback, int idx = 0 );
  Atm_player& onNote( Machine& machine, int event = 0 );
  Atm_player& onNote( atm_cb_push_t callback, int idx = 0 );
  Atm_player& onNote( int sub, Machine& machine, int event = 0 );
  Atm_player& onNote( int sub, atm_cb_push_t callback, int idx = 0 );

 private:
  int pin;
  int* pattern;
  int patternsize;
  int step;
  uint16_t repeatCount;
  float speedFactor, pitchFactor;
  int stub[3];
  atm_timer_millis timer;
  atm_counter counter_repeat;
  enum { ENT_IDLE, ENT_START, ENT_SOUND, ENT_QUIET, ENT_NEXT, ENT_REPEAT, ENT_FINISH };  // ACTIONS
  enum { ON_FINISH, ON_NOTE, CONN_MAX = 3 }; // CONNECTORS
  atm_connector connectors[CONN_MAX];
  int event( int id );
  void action( int id );
};

/*
Automaton::ATML::begin - State Machine Definition Language

<?xml version="1.0" encoding="UTF-8"?>
<machines>
  <machine name="Atm_player">
    <states>
      <IDLE index="0" sleep="1" on_enter="ENT_IDLE">
        <EVT_START>START</EVT_START>
        <EVT_TOGGLE>START</EVT_TOGGLE>
      </IDLE>
      <START index="1" on_enter="ENT_START">
        <ELSE>SOUND</ELSE>
      </START>
      <SOUND index="2" on_enter="ENT_SOUND">
        <EVT_STOP>IDLE</EVT_STOP>
        <EVT_TOGGLE>IDLE</EVT_TOGGLE>
        <EVT_TIMER>QUIET</EVT_TIMER>
      </SOUND>
      <QUIET index="3" on_enter="ENT_QUIET">
        <EVT_STOP>IDLE</EVT_STOP>
        <EVT_TOGGLE>IDLE</EVT_TOGGLE>
        <EVT_TIMER>NEXT</EVT_TIMER>
      </QUIET>
      <NEXT index="4" on_enter="ENT_NEXT">
        <EVT_STOP>IDLE</EVT_STOP>
        <EVT_TOGGLE>IDLE</EVT_TOGGLE>
        <EVT_EOPAT>REPEAT</EVT_EOPAT>
        <ELSE>SOUND</ELSE>
      </NEXT>
      <REPEAT index="5" on_enter="ENT_REPEAT">
        <EVT_STOP>IDLE</EVT_STOP>
        <EVT_TOGGLE>IDLE</EVT_TOGGLE>
        <EVT_REPEAT>FINISH</EVT_REPEAT>
        <ELSE>START</ELSE>
      </REPEAT>
      <FINISH index="6" on_enter="ENT_FINISH">
        <EVT_REPEAT>IDLE</EVT_REPEAT>
        <ELSE>START</ELSE>
      </FINISH>
    </states>
    <events>
      <EVT_START index="0"/>
      <EVT_STOP index="1"/>
      <EVT_TOGGLE index="2"/>
      <EVT_TIMER index="3"/>
      <EVT_EOPAT index="4"/>
      <EVT_REPEAT index="5"/>
    </events>
    <connectors>
      <FINISH autostore="0" broadcast="0" dir="PUSH" slots="1"/>
      <NOTE autostore="0" broadcast="0" dir="PUSH" slots="2"/>
    </connectors>
    <methods>
    </methods>
  </machine>
</machines>

Automaton::ATML::end
*/
<commit_msg>Comment<commit_after>#pragma once

#include <Automaton.h>

class Atm_player : public Machine {
 public:
  enum { IDLE, START, SOUND, QUIET, NEXT, REPEAT, FINISH };                          // STATES
  enum { EVT_START, EVT_STOP, EVT_TOGGLE, EVT_TIMER, EVT_EOPAT, EVT_REPEAT, ELSE };  // EVENTS
  Atm_player( void ) : Machine(){};
  Atm_player& begin( int pin = -1 );
  Atm_player& trace( Stream& stream );
  Atm_player& trigger( int event );
  int state( void );
  Atm_player& play( int* pat, int size );
  Atm_player& play( int freq, int period, int pause = 0 );
  Atm_player& repeat( uint16_t v );
  Atm_player& speed( float v );
  Atm_player& pitch( float v );
  Atm_player& onFinish( Machine& machine, int event = 0 );
  Atm_player& onFinish( atm_cb_push_t callback, int idx = 0 );
  Atm_player& onNote( Machine& machine, int event = 0 );
  Atm_player& onNote( atm_cb_push_t callback, int idx = 0 );
  Atm_player& onNote( int sub, Machine& machine, int event = 0 );
  Atm_player& onNote( int sub, atm_cb_push_t callback, int idx = 0 );

 private:
  int pin;
  int* pattern;
  int patternsize;
  int step;
  uint16_t repeatCount;
  float speedFactor, pitchFactor;
  int stub[3];
  atm_timer_millis timer;
  atm_counter counter_repeat;
  enum { ENT_IDLE, ENT_START, ENT_SOUND, ENT_QUIET, ENT_NEXT, ENT_REPEAT, ENT_FINISH };  // ACTIONS
  enum { ON_FINISH, ON_NOTE, CONN_MAX = 3 }; // CONNECTORS
  atm_connector connectors[CONN_MAX];
  int event( int id );
  void action( int id );
};

/*
Automaton::ATML::begin - Automaton Markup Language

<?xml version="1.0" encoding="UTF-8"?>
<machines>
  <machine name="Atm_player">
    <states>
      <IDLE index="0" sleep="1" on_enter="ENT_IDLE">
        <EVT_START>START</EVT_START>
        <EVT_TOGGLE>START</EVT_TOGGLE>
      </IDLE>
      <START index="1" on_enter="ENT_START">
        <ELSE>SOUND</ELSE>
      </START>
      <SOUND index="2" on_enter="ENT_SOUND">
        <EVT_STOP>IDLE</EVT_STOP>
        <EVT_TOGGLE>IDLE</EVT_TOGGLE>
        <EVT_TIMER>QUIET</EVT_TIMER>
      </SOUND>
      <QUIET index="3" on_enter="ENT_QUIET">
        <EVT_STOP>IDLE</EVT_STOP>
        <EVT_TOGGLE>IDLE</EVT_TOGGLE>
        <EVT_TIMER>NEXT</EVT_TIMER>
      </QUIET>
      <NEXT index="4" on_enter="ENT_NEXT">
        <EVT_STOP>IDLE</EVT_STOP>
        <EVT_TOGGLE>IDLE</EVT_TOGGLE>
        <EVT_EOPAT>REPEAT</EVT_EOPAT>
        <ELSE>SOUND</ELSE>
      </NEXT>
      <REPEAT index="5" on_enter="ENT_REPEAT">
        <EVT_STOP>IDLE</EVT_STOP>
        <EVT_TOGGLE>IDLE</EVT_TOGGLE>
        <EVT_REPEAT>FINISH</EVT_REPEAT>
        <ELSE>START</ELSE>
      </REPEAT>
      <FINISH index="6" on_enter="ENT_FINISH">
        <EVT_REPEAT>IDLE</EVT_REPEAT>
        <ELSE>START</ELSE>
      </FINISH>
    </states>
    <events>
      <EVT_START index="0"/>
      <EVT_STOP index="1"/>
      <EVT_TOGGLE index="2"/>
      <EVT_TIMER index="3"/>
      <EVT_EOPAT index="4"/>
      <EVT_REPEAT index="5"/>
    </events>
    <connectors>
      <FINISH autostore="0" broadcast="0" dir="PUSH" slots="1"/>
      <NOTE autostore="0" broadcast="0" dir="PUSH" slots="2"/>
    </connectors>
    <methods>
    </methods>
  </machine>
</machines>

Automaton::ATML::end
*/
<|endoftext|>


<commit_before>#include <SCD/CD/CD_Pair.h>
#include <SCD/CD/CD_Simplex.h>
#include <SCD/CD/CD_SimplexEnhanced.h>

#ifdef WITH_OPENGL
# if defined __APPLE__
#  include <GLUT/glut.h>
# else
#  include <GL/glut.h>
# endif // __APPLE__
#endif // WITH_OPENGL

#include <iostream>

//#ifndef NOGLUT
//#define SHOW_LAST_SIMLPEX
//#endif

//#define CD_SAFE_VERSION //use when the scalar has a perfect precision
#define PENETRATION_DEPTH
//#define CD_PAIR_VERBOUS_MODE
//#define CD_ITERATION_LIMIT 20 //use when the real-time constraints are too high fo current performances while keeping the same global precision.
								//no theoretical guarantee on the precision nor the collision-safeness when used - Default value is 20

#define _EPSILON_ 1e-24
#define _PRECISION_ 1e-6

using namespace SCD;

inline Vector3 LinearSystem(Matrix3x3& A, Vector3& y)
{
	Matrix3x3 B;
	A.Inversion(B);
	return (B*y);
}

CD_Pair::CD_Pair(S_Object *obj1, S_Object *obj2):sObj1_(obj1),sObj2_(obj2),lastDirection_(1.0,0.0,0.0),
lastFeature1_(-1),lastFeature2_(-1),distance_(0),stamp1_(sObj1_->checkStamp()),stamp2_(sObj2_->checkStamp()),
precision_(_PRECISION_),epsilon_(_EPSILON_),witPointsAreComputed_(false),s1_(Point3()),s2_(Point3()),s_(Point3()),sp_(Point3()),depthPair(obj1,obj2)
{
	--stamp1_;
	--stamp2_;

	depthPair.setRelativePrecision(_PRECISION_);
	depthPair.setEpsilon(_EPSILON_);

}

CD_Pair::~CD_Pair(void)
{
}

Scalar CD_Pair::getDistance()
{
	if ((stamp1_==sObj1_->checkStamp())&&(stamp2_==sObj2_->checkStamp()))
	{
		return distance_;
	}
	else
	{
		stamp1_=sObj1_->checkStamp();
		stamp2_=sObj2_->checkStamp();
		GJK();
		penetrationDepth();
		return distance_;
	}

}

Scalar CD_Pair::getDistanceWithoutPenetrationDepth()
{
	if ((stamp1_==sObj1_->checkStamp())&&(stamp2_==sObj2_->checkStamp()))
	{
		if (distance_ > 0)
			return distance_;
		return 0;
	}
	else
	{
		GJK();
		if (collision_)
			return 0;
		return distance_;
	}

}

Scalar CD_Pair::reComputeClosestPoints(Point3& p1,Point3& p2)
{
	stamp1_=sObj1_->checkStamp();
	stamp2_=sObj2_->checkStamp();
	GJK();
	penetrationDepth();
	witPoints(p1,p2);
	return distance_;

}

void CD_Pair::setRelativePrecision(Scalar s)
{
	precision_=s*s;
	depthPair.setRelativePrecision(s);
}

void CD_Pair::setEpsilon(Scalar s)
{
	epsilon_=s;
	depthPair.setEpsilon(s);
}

Scalar CD_Pair::getClosestPoints(Point3 &p1, Point3 &p2)
{
	if ((stamp1_==sObj1_->checkStamp())&&(stamp2_==sObj2_->checkStamp()))
	{
		if (!witPointsAreComputed_)
		{
			witPointsAreComputed_=true;
			witPoints(p1,p2);
		}
		p1=p1_;
		p2=p2_;
		return distance_;
	}
	else
	{

		stamp1_=sObj1_->checkStamp();
		stamp2_=sObj2_->checkStamp();
		GJK();
		penetrationDepth();
		witPoints(p1,p2);
		witPointsAreComputed_=true;
		return distance_;

	}

}

Scalar CD_Pair::penetrationDepth()
{
#ifdef PENETRATION_DEPTH
	if (collision_)//Objects are in collision
	{
		distance_=-depthPair.getPenetrationDepth(lastDirection_,p1_,p2_,sp_,s1_,s2_);
		if (distance_<0)
		{
			lastDirection_.Set(0,1,0);
		}

		return distance_;
	}
	else
	{
		return distance_;
	}
#else
	return distance_;
#endif
}

Scalar CD_Pair::GJK()
{
	Vector3& v=lastDirection_;

#ifdef CD_PAIR_VERBOUS_MODE
	std::cout<<"#####GJK START######"<<std::endl;
#endif

	witPointsAreComputed_=false;

	int& lf1=lastFeature1_;
	int& lf2=lastFeature2_;

	Point3 sup1=sObj1_->support(v,lf1);
	Point3 sup2=sObj2_->support(-v,lf2);

#ifdef CD_PAIR_VERBOUS_MODE
	std::cout<<"Last features"<<lf1<<" "<<lf2<<std::endl;
#endif

	Point3 sup(sup1);

	sup-=sup2;

	s1_=sup1;
	s2_=sup2;
	s_=sup;

	sp_=sup;

	CD_SimplexKeptPoints k;

	projectionComputed_=false;

	bool cont=true;

	Point3 proj;

	Vector3 S01;
	Vector3 S02;

	Scalar a1,a2,a3,a4,a5,a6;

#ifdef CD_ITERATION_LIMIT

	int	cnt=0;
#endif

	while (cont)
	{

#ifdef CD_ITERATION_LIMIT

		if (++cnt>CD_ITERATION_LIMIT)
			break;		//the iterations number limit has been reached
#endif

		switch (s_.getType())
		{

		case CD_Triangle:
			{
				S01=s_[1];
				S01-=s_[2];
				S02=s_[0];
				S02-=s_[2];
				a1=S01*s_[0],a2=S01*s_[1],a3=S01*s_[2],a4=S02*s_[0],a5=S02*s_[1],a6=S02*s_[2];

				lambda0_=a2*a6-a3*a5;
				lambda1_=a3*a4-a1*a6;
				lambda2_=a1*a5-a2*a4;
				det_=1/(lambda0_+lambda1_+lambda2_);
				lambda0_*=det_;
				lambda1_*=det_;
				lambda2_*=det_;

				proj=s_[0]*lambda0_+s_[1]*lambda1_+s_[2]*lambda2_;
				v=-proj;
				break;
			}

		case CD_Segment:
			{
				S01=s_[1];
				S01-=s_[0];

				lambda0_=S01*s_[1];
				lambda1_=-(S01*s_[0]);
				det_=1/(lambda0_+lambda1_);
				lambda0_*=det_;
				lambda1_*=det_;

				proj=s_[0]*lambda0_+s_[1]*lambda1_;
				v=-proj;
				break;
			}
		default:
			{
				proj=s_[0];
				v=-proj;
			}

		}
		if ((distance_=v.normsquared())<=sp_.farthestPointDistance()*epsilon_)//v is considered zero
		{
			collision_=true;
			cont=false;
		}
		else
		{
			sup1=sObj1_->support(v,lf1);
			sup2=sObj2_->support(-v,lf2);

#ifdef CD_PAIR_VERBOUS_MODE

			std::cout<<"Last features"<<lf1<<" "<<lf2<<std::endl;
			std::cout<<"supports"<<sup1<<" "<<sup2<<std::endl;
#	ifdef CD_ITERATION_LIMIT
			std::cout<<"Iterations"<<cnt<<std::endl;
#	endif
#endif

			sup=sup1;
			sup-=sup2;

			if ((distance_-proj*sup)<(precision_*distance_))//precision reached
			{
				collision_=false;
				cont=false;
				projectionComputed_=true;
			}
			else
			{
				sp_+=sup;
				sp_.updateVectors();
#ifndef SAFE_VERSION
				if (sp_.isAffinelyDependent())
				{
					cont=false;
					collision_=false;
					projectionComputed_=true;
				}
				else
#endif
				{
					sp_.getClosestSubSimplexGJK(k);
					sp_.filter(k);
					s1_+=sup1;
					s2_+=sup2;

					if (sp_.getType()==CD_Tetrahedron)
					{
						cont=false;
						s1_+=sup1;
						s2_+=sup2;
						collision_=true;
					}
					else
					{
						s_=sp_;
						s1_.filter(k);
						s2_.filter(k);
					}
				}
			}
		}
	}

#ifdef CD_PAIR_VERBOUS_MODE
	std::cout<<"#####GJK END######"<<std::endl;
#endif

	return distance_;

}

void CD_Pair::setVector(const Vector3 &v)
{
	lastDirection_=v;
}

void CD_Pair::witPoints(Point3 &p1, Point3 &p2)
{
	Point3 proj;
	Vector3& v=lastDirection_;

	if (collision_)
	{
		p1=p1_;
		p2=p2_;
		return;

	}

	switch (s_.getType())
	{

	case CD_Triangle:
		{

			{
				if (!projectionComputed_)
				{
					Vector3 S01(s_[1]-s_[2]), S02(s_[0]-s_[2]);

					Scalar a1=S01*s_[0],a2=S01*s_[1],a3=S01*s_[2],a4=S02*s_[0],a5=S02*s_[1],a6=S02*s_[2];

					lambda0_=a2*a6-a3*a5;
					lambda1_=a3*a4-a1*a6;
					lambda2_=a1*a5-a2*a4;
					det_=1/(lambda0_+lambda1_+lambda2_);

					lambda0_*=det_;
					lambda1_*=det_;
					lambda2_*=det_;

					proj=s_[0]*lambda0_+s_[1]*lambda1_+s_[2]*lambda2_;

					v=-proj;

				}

				p1_=p1=s1_[0]*lambda0_+s1_[1]*lambda1_+s1_[2]*lambda2_;
				p2_=p2=s2_[0]*lambda0_+s2_[1]*lambda1_+s2_[2]*lambda2_;

			}

#ifdef SHOW_LAST_SIMLPEX
			glDisable(GL_DEPTH_TEST);
			glColor4d(0,0.5,1,0.5);
			glBegin(GL_TRIANGLES);
			glVertex3d(s1_[0][0],s1_[0][1],s1_[0][2]);
			glVertex3d(s1_[1][0],s1_[1][1],s1_[1][2]);
			glVertex3d(s1_[2][0],s1_[2][1],s1_[2][2]);

			glVertex3d(s2_[0][0],s2_[0][1],s2_[0][2]);
			glVertex3d(s2_[1][0],s2_[1][1],s2_[1][2]);
			glVertex3d(s2_[2][0],s2_[2][1],s2_[2][2]);

			glEnd();

			glEnable(GL_DEPTH_TEST);
#endif

			return;

		}

	case CD_Segment:
		{
			if (!projectionComputed_)
			{

				Vector3 S01(s_[1]-s_[0]);

				lambda1_=-(S01*s_[0]);
				lambda0_=S01*s_[1];

				det_=1/(lambda0_+lambda1_);

				lambda0_*=det_;
				lambda1_*=det_;

				proj=s_[0]*lambda0_+s_[1]*lambda1_;

				v=-proj;

			}

			p1_=p1=s1_[0]*lambda0_+s1_[1]*lambda1_;
			p2_=p2=s2_[0]*lambda0_+s2_[1]*lambda1_;

#ifdef SHOW_LAST_SIMLPEX

			glDisable(GL_DEPTH_TEST);
			glColor4d(0,0.5,1,0.5);
			glBegin(GL_LINES);
			glVertex3d(s1_[0][0],s1_[0][1],s1_[0][2]);
			glVertex3d(s1_[1][0],s1_[1][1],s1_[1][2]);

			glVertex3d(s2_[0][0],s2_[0][1],s2_[0][2]);
			glVertex3d(s2_[1][0],s2_[1][1],s2_[1][2]);

			glEnd();

			glEnable(GL_DEPTH_TEST);

#endif
			return ;
		}
	default:
		{
			p1_=p1=s1_[0];
			p2_=p2=s2_[0];

			return ;
		}

	}
}

bool CD_Pair::isInCollision()
{
	if ((stamp1_==sObj1_->checkStamp())&&(stamp2_==sObj2_->checkStamp()))
	{
		return collision_;
	}
	else
	{
		Scalar prec=precision_;
		precision_=1;
		GJK();
		precision_=prec;
		return collision_;
	}
}

<commit_msg>Set iteration limits to avoid infinite loop.<commit_after>#include <SCD/CD/CD_Pair.h>
#include <SCD/CD/CD_Simplex.h>
#include <SCD/CD/CD_SimplexEnhanced.h>

#ifdef WITH_OPENGL
# if defined __APPLE__
#  include <GLUT/glut.h>
# else
#  include <GL/glut.h>
# endif // __APPLE__
#endif // WITH_OPENGL

#include <iostream>

//#ifndef NOGLUT
//#define SHOW_LAST_SIMLPEX
//#endif

//#define CD_SAFE_VERSION //use when the scalar has a perfect precision
#define PENETRATION_DEPTH
//#define CD_PAIR_VERBOUS_MODE
#define CD_ITERATION_LIMIT 50 //use when the real-time constraints are too high fo current performances while keeping the same global precision.
								//no theoretical guarantee on the precision nor the collision-safeness when used - Default value is 20

#define _EPSILON_ 1e-24
#define _PRECISION_ 1e-6

using namespace SCD;

inline Vector3 LinearSystem(Matrix3x3& A, Vector3& y)
{
	Matrix3x3 B;
	A.Inversion(B);
	return (B*y);
}

CD_Pair::CD_Pair(S_Object *obj1, S_Object *obj2):sObj1_(obj1),sObj2_(obj2),lastDirection_(1.0,0.0,0.0),
lastFeature1_(-1),lastFeature2_(-1),distance_(0),stamp1_(sObj1_->checkStamp()),stamp2_(sObj2_->checkStamp()),
precision_(_PRECISION_),epsilon_(_EPSILON_),witPointsAreComputed_(false),s1_(Point3()),s2_(Point3()),s_(Point3()),sp_(Point3()),depthPair(obj1,obj2)
{
	--stamp1_;
	--stamp2_;

	depthPair.setRelativePrecision(_PRECISION_);
	depthPair.setEpsilon(_EPSILON_);

}

CD_Pair::~CD_Pair(void)
{
}

Scalar CD_Pair::getDistance()
{
	if ((stamp1_==sObj1_->checkStamp())&&(stamp2_==sObj2_->checkStamp()))
	{
		return distance_;
	}
	else
	{
		stamp1_=sObj1_->checkStamp();
		stamp2_=sObj2_->checkStamp();
		GJK();
		penetrationDepth();
		return distance_;
	}

}

Scalar CD_Pair::getDistanceWithoutPenetrationDepth()
{
	if ((stamp1_==sObj1_->checkStamp())&&(stamp2_==sObj2_->checkStamp()))
	{
		if (distance_ > 0)
			return distance_;
		return 0;
	}
	else
	{
		GJK();
		if (collision_)
			return 0;
		return distance_;
	}

}

Scalar CD_Pair::reComputeClosestPoints(Point3& p1,Point3& p2)
{
	stamp1_=sObj1_->checkStamp();
	stamp2_=sObj2_->checkStamp();
	GJK();
	penetrationDepth();
	witPoints(p1,p2);
	return distance_;

}

void CD_Pair::setRelativePrecision(Scalar s)
{
	precision_=s*s;
	depthPair.setRelativePrecision(s);
}

void CD_Pair::setEpsilon(Scalar s)
{
	epsilon_=s;
	depthPair.setEpsilon(s);
}

Scalar CD_Pair::getClosestPoints(Point3 &p1, Point3 &p2)
{
	if ((stamp1_==sObj1_->checkStamp())&&(stamp2_==sObj2_->checkStamp()))
	{
		if (!witPointsAreComputed_)
		{
			witPointsAreComputed_=true;
			witPoints(p1,p2);
		}
		p1=p1_;
		p2=p2_;
		return distance_;
	}
	else
	{

		stamp1_=sObj1_->checkStamp();
		stamp2_=sObj2_->checkStamp();
		GJK();
		penetrationDepth();
		witPoints(p1,p2);
		witPointsAreComputed_=true;
		return distance_;

	}

}

Scalar CD_Pair::penetrationDepth()
{
#ifdef PENETRATION_DEPTH
	if (collision_)//Objects are in collision
	{
		distance_=-depthPair.getPenetrationDepth(lastDirection_,p1_,p2_,sp_,s1_,s2_);
		if (distance_<0)
		{
			lastDirection_.Set(0,1,0);
		}

		return distance_;
	}
	else
	{
		return distance_;
	}
#else
	return distance_;
#endif
}

Scalar CD_Pair::GJK()
{
	Vector3& v=lastDirection_;

#ifdef CD_PAIR_VERBOUS_MODE
	std::cout<<"#####GJK START######"<<std::endl;
#endif

	witPointsAreComputed_=false;

	int& lf1=lastFeature1_;
	int& lf2=lastFeature2_;

	Point3 sup1=sObj1_->support(v,lf1);
	Point3 sup2=sObj2_->support(-v,lf2);

#ifdef CD_PAIR_VERBOUS_MODE
	std::cout<<"Last features"<<lf1<<" "<<lf2<<std::endl;
#endif

	Point3 sup(sup1);

	sup-=sup2;

	s1_=sup1;
	s2_=sup2;
	s_=sup;

	sp_=sup;

	CD_SimplexKeptPoints k;

	projectionComputed_=false;

	bool cont=true;

	Point3 proj;

	Vector3 S01;
	Vector3 S02;

	Scalar a1,a2,a3,a4,a5,a6;

#ifdef CD_ITERATION_LIMIT

	int	cnt=0;
#endif

	while (cont)
	{

#ifdef CD_ITERATION_LIMIT

		if (++cnt>CD_ITERATION_LIMIT)
			break;		//the iterations number limit has been reached
#endif

		switch (s_.getType())
		{

		case CD_Triangle:
			{
				S01=s_[1];
				S01-=s_[2];
				S02=s_[0];
				S02-=s_[2];
				a1=S01*s_[0],a2=S01*s_[1],a3=S01*s_[2],a4=S02*s_[0],a5=S02*s_[1],a6=S02*s_[2];

				lambda0_=a2*a6-a3*a5;
				lambda1_=a3*a4-a1*a6;
				lambda2_=a1*a5-a2*a4;
				det_=1/(lambda0_+lambda1_+lambda2_);
				lambda0_*=det_;
				lambda1_*=det_;
				lambda2_*=det_;

				proj=s_[0]*lambda0_+s_[1]*lambda1_+s_[2]*lambda2_;
				v=-proj;
				break;
			}

		case CD_Segment:
			{
				S01=s_[1];
				S01-=s_[0];

				lambda0_=S01*s_[1];
				lambda1_=-(S01*s_[0]);
				det_=1/(lambda0_+lambda1_);
				lambda0_*=det_;
				lambda1_*=det_;

				proj=s_[0]*lambda0_+s_[1]*lambda1_;
				v=-proj;
				break;
			}
		default:
			{
				proj=s_[0];
				v=-proj;
			}

		}
		if ((distance_=v.normsquared())<=sp_.farthestPointDistance()*epsilon_)//v is considered zero
		{
			collision_=true;
			cont=false;
		}
		else
		{
			sup1=sObj1_->support(v,lf1);
			sup2=sObj2_->support(-v,lf2);

#ifdef CD_PAIR_VERBOUS_MODE

			std::cout<<"Last features"<<lf1<<" "<<lf2<<std::endl;
			std::cout<<"supports"<<sup1<<" "<<sup2<<std::endl;
#	ifdef CD_ITERATION_LIMIT
			std::cout<<"Iterations"<<cnt<<std::endl;
#	endif
#endif

			sup=sup1;
			sup-=sup2;

			if ((distance_-proj*sup)<(precision_*distance_))//precision reached
			{
				collision_=false;
				cont=false;
				projectionComputed_=true;
			}
			else
			{
				sp_+=sup;
				sp_.updateVectors();
#ifndef SAFE_VERSION
				if (sp_.isAffinelyDependent())
				{
					cont=false;
					collision_=false;
					projectionComputed_=true;
				}
				else
#endif
				{
					sp_.getClosestSubSimplexGJK(k);
					sp_.filter(k);
					s1_+=sup1;
					s2_+=sup2;

					if (sp_.getType()==CD_Tetrahedron)
					{
						cont=false;
						s1_+=sup1;
						s2_+=sup2;
						collision_=true;
					}
					else
					{
						s_=sp_;
						s1_.filter(k);
						s2_.filter(k);
					}
				}
			}
		}
	}

#ifdef CD_PAIR_VERBOUS_MODE
	std::cout<<"#####GJK END######"<<std::endl;
#endif

	return distance_;

}

void CD_Pair::setVector(const Vector3 &v)
{
	lastDirection_=v;
}

void CD_Pair::witPoints(Point3 &p1, Point3 &p2)
{
	Point3 proj;
	Vector3& v=lastDirection_;

	if (collision_)
	{
		p1=p1_;
		p2=p2_;
		return;

	}

	switch (s_.getType())
	{

	case CD_Triangle:
		{

			{
				if (!projectionComputed_)
				{
					Vector3 S01(s_[1]-s_[2]), S02(s_[0]-s_[2]);

					Scalar a1=S01*s_[0],a2=S01*s_[1],a3=S01*s_[2],a4=S02*s_[0],a5=S02*s_[1],a6=S02*s_[2];

					lambda0_=a2*a6-a3*a5;
					lambda1_=a3*a4-a1*a6;
					lambda2_=a1*a5-a2*a4;
					det_=1/(lambda0_+lambda1_+lambda2_);

					lambda0_*=det_;
					lambda1_*=det_;
					lambda2_*=det_;

					proj=s_[0]*lambda0_+s_[1]*lambda1_+s_[2]*lambda2_;

					v=-proj;

				}

				p1_=p1=s1_[0]*lambda0_+s1_[1]*lambda1_+s1_[2]*lambda2_;
				p2_=p2=s2_[0]*lambda0_+s2_[1]*lambda1_+s2_[2]*lambda2_;

			}

#ifdef SHOW_LAST_SIMLPEX
			glDisable(GL_DEPTH_TEST);
			glColor4d(0,0.5,1,0.5);
			glBegin(GL_TRIANGLES);
			glVertex3d(s1_[0][0],s1_[0][1],s1_[0][2]);
			glVertex3d(s1_[1][0],s1_[1][1],s1_[1][2]);
			glVertex3d(s1_[2][0],s1_[2][1],s1_[2][2]);

			glVertex3d(s2_[0][0],s2_[0][1],s2_[0][2]);
			glVertex3d(s2_[1][0],s2_[1][1],s2_[1][2]);
			glVertex3d(s2_[2][0],s2_[2][1],s2_[2][2]);

			glEnd();

			glEnable(GL_DEPTH_TEST);
#endif

			return;

		}

	case CD_Segment:
		{
			if (!projectionComputed_)
			{

				Vector3 S01(s_[1]-s_[0]);

				lambda1_=-(S01*s_[0]);
				lambda0_=S01*s_[1];

				det_=1/(lambda0_+lambda1_);

				lambda0_*=det_;
				lambda1_*=det_;

				proj=s_[0]*lambda0_+s_[1]*lambda1_;

				v=-proj;

			}

			p1_=p1=s1_[0]*lambda0_+s1_[1]*lambda1_;
			p2_=p2=s2_[0]*lambda0_+s2_[1]*lambda1_;

#ifdef SHOW_LAST_SIMLPEX

			glDisable(GL_DEPTH_TEST);
			glColor4d(0,0.5,1,0.5);
			glBegin(GL_LINES);
			glVertex3d(s1_[0][0],s1_[0][1],s1_[0][2]);
			glVertex3d(s1_[1][0],s1_[1][1],s1_[1][2]);

			glVertex3d(s2_[0][0],s2_[0][1],s2_[0][2]);
			glVertex3d(s2_[1][0],s2_[1][1],s2_[1][2]);

			glEnd();

			glEnable(GL_DEPTH_TEST);

#endif
			return ;
		}
	default:
		{
			p1_=p1=s1_[0];
			p2_=p2=s2_[0];

			return ;
		}

	}
}

bool CD_Pair::isInCollision()
{
	if ((stamp1_==sObj1_->checkStamp())&&(stamp2_==sObj2_->checkStamp()))
	{
		return collision_;
	}
	else
	{
		Scalar prec=precision_;
		precision_=1;
		GJK();
		precision_=prec;
		return collision_;
	}
}

<|endoftext|>


<commit_before>#ifndef AX_EXPRESSION_H
#define AX_EXPRESSION_H
#include <type_traits>
#include <cstddef>

namespace ax
{
    extern void* enabler; //never defined

    using dimention_type = int;

    struct operator_tag{};
    struct matrix_tag{};
    struct matrix_expression_tag{};
    struct vector_tag{};
    struct vector_expression_tag{};
    struct avx_operation_tag{};

    template <dimention_type I_dim>
    struct is_static_dimention{constexpr static bool value = I_dim >= 0;};
    template <dimention_type I_dim>
    struct is_dynamic_dimention{constexpr static bool value = I_dim < 0;};

    template <typename T>
    struct is_operator_struct : public std::false_type{};
    template <>
    struct is_operator_struct<operator_tag> : public std::true_type{};

    template <typename T>
    struct is_matrix_expression: public std::false_type{};
    template <>
    struct is_matrix_expression<matrix_tag>: public std::true_type{};
    template <>
    struct is_matrix_expression<matrix_expression_tag>: public std::true_type{};

    template <typename T>
    struct is_vector_expression: public std::false_type{};
    template <>
    struct is_vector_expression<vector_tag>: public std::true_type{};
    template <>
    struct is_vector_expression<vector_expression_tag>: public std::true_type{};

    template <dimention_type I_ldim, dimention_type I_rdim>
    struct is_same_dimention: public std::false_type{};
    template <dimention_type I_dim>
    struct is_same_dimention<I_dim, I_dim>: public std::true_type{};

    template <dimention_type I_dim>
    struct is_scalar{constexpr static bool value = (I_dim == 0);};

    template <typename T, typename T_vec>
    struct is_scalar_type
    {
        constexpr static bool value =
            std::is_same<T, typename T_vec::elem_t>::value;
    };

    template <typename T_lhs, typename T_rhs>
    struct is_same_vector
    {
        constexpr static bool value =
            is_vector_expression<typename T_lhs::tag>::value&&
            is_vector_expression<typename T_rhs::tag>::value&&
            is_same_dimention<T_lhs::dim, T_rhs::dim>::value&&
            std::is_same<typename T_lhs::elem_t, typename T_rhs::elem_t>::value;
    };

}
#endif //AX_MATRIX_EXPRESSION_H
<commit_msg>add constant DYNAMIC<commit_after>#ifndef AX_EXPRESSION_H
#define AX_EXPRESSION_H
#include <type_traits>
#include <cstddef>

namespace ax
{
    extern void* enabler; //never defined

    using dimention_type = int;
    constexpr static dimention_type DYNAMIC = -1;

    struct operator_tag{};
    struct matrix_tag{};
    struct matrix_expression_tag{};
    struct vector_tag{};
    struct vector_expression_tag{};
    struct avx_operation_tag{};

    template <dimention_type I_dim>
    struct is_static_dimention{constexpr static bool value = I_dim >= 0;};
    template <dimention_type I_dim>
    struct is_dynamic_dimention{constexpr static bool value = I_dim < 0;};

    template <typename T>
    struct is_operator_struct : public std::false_type{};
    template <>
    struct is_operator_struct<operator_tag> : public std::true_type{};

    template <typename T>
    struct is_matrix_expression: public std::false_type{};
    template <>
    struct is_matrix_expression<matrix_tag>: public std::true_type{};
    template <>
    struct is_matrix_expression<matrix_expression_tag>: public std::true_type{};

    template <typename T>
    struct is_vector_expression: public std::false_type{};
    template <>
    struct is_vector_expression<vector_tag>: public std::true_type{};
    template <>
    struct is_vector_expression<vector_expression_tag>: public std::true_type{};

    template <dimention_type I_ldim, dimention_type I_rdim>
    struct is_same_dimention: public std::false_type{};
    template <dimention_type I_dim>
    struct is_same_dimention<I_dim, I_dim>: public std::true_type{};

    template <dimention_type I_dim>
    struct is_scalar{constexpr static bool value = (I_dim == 0);};

    template <typename T, typename T_vec>
    struct is_scalar_type
    {
        constexpr static bool value =
            std::is_same<T, typename T_vec::elem_t>::value;
    };

    template <typename T_lhs, typename T_rhs>
    struct is_same_vector
    {
        constexpr static bool value =
            is_vector_expression<typename T_lhs::tag>::value&&
            is_vector_expression<typename T_rhs::tag>::value&&
            is_same_dimention<T_lhs::dim, T_rhs::dim>::value&&
            std::is_same<typename T_lhs::elem_t, typename T_rhs::elem_t>::value;
    };

}
#endif //AX_MATRIX_EXPRESSION_H
<|endoftext|>


<commit_before>/*
 * Part of HTTPP.
 *
 * Distributed under the 3-clause BSD licence (See LICENCE.TXT file at the
 * project root).
 *
 * Copyright (c) 2013 Thomas Sanchez.  All rights reserved.
 *
 */

#include "httpp/HttpServer.hpp"

#include <boost/log/trivial.hpp>
#include "httpp/http/Utils.hpp"

namespace HTTPP
{

HttpServer::HttpServer(size_t threads)
: service_(threads)
, pool_(threads, service_)
{
}

HttpServer::~HttpServer()
{
    if (running_)
    {
        stop();
    }
}

void HttpServer::start(ThreadInit fct)
{
    if (running_)
    {
        return;
    }
    running_ = true;
    pool_.start(fct);
}

void HttpServer::stop()
{
    if (!running_)
    {
        return;
    }

    running_ = false;
    for (auto acc : acceptors_)
    {
        boost::system::error_code ec;
        acc->close(ec);
    }

    acceptors_.clear();
    pool_.stop();
}

void HttpServer::bind(const std::string& address, const std::string& port)
{
    auto acc = HttpServer::bind(service_, address, port);
    BOOST_LOG_TRIVIAL(debug) << "Bind address: " << address
                             << " on port: " << port;
    acceptors_.push_back(acc);
    start_accept(acc);
}

void HttpServer::start_accept(AcceptorPtr acceptor)
{
    if (running_)
    {
        auto connection = new HTTP::Connection(*this, service_, pool_);
        //std::make_shared<HTTP::Connection>(*this, service_, pool_);

        acceptor->async_accept(connection->socket_,
                               std::bind(&HttpServer::accept_callback,
                                         this,
                                         std::placeholders::_1,
                                         acceptor,
                                         connection));
    }
}

void HttpServer::accept_callback(const boost::system::error_code& error,
                                 AcceptorPtr acceptor,
                                 ConnectionPtr connection)
{
    if (running_)
    {
        if (error)
        {
            if (error != boost::asio::error::operation_aborted)
            {
                BOOST_LOG_TRIVIAL(error)
                    << "Error during accept: " << error.message();
            }

            delete connection;
        }
        else
        {
            BOOST_LOG_TRIVIAL(debug) << "New connection accepted from: "
                << connection->source();

            connection->start();
        }

        start_accept(acceptor);
    }
    else
    {
        delete connection;
    }
}

HttpServer::AcceptorPtr HttpServer::bind(boost::asio::io_service& service,
                                         const std::string& host,
                                         const std::string& port)
{
    auto acceptor = AcceptorPtr(new Acceptor(service));
    boost::system::error_code error;
    auto addr = boost::asio::ip::address::from_string(host, error);
    boost::asio::ip::tcp::endpoint endpoint;
    if (error)
    {
        boost::asio::ip::tcp::resolver resolver(service);
        boost::asio::ip::tcp::resolver::query query(host, port);
        boost::asio::ip::tcp::resolver::iterator it = resolver.resolve(query),
                                                 end;

        if (it == end)
        {
            BOOST_LOG_TRIVIAL(error)
                << "Error bad address (ip address in dotted format or ipv6 hex format: "
                << host << ", error msg: " << error.message();
            throw error;
        }
        else
        {
            endpoint = *it;
        }
    }
    else
    {
        endpoint = boost::asio::ip::tcp::endpoint(addr, std::stoi(port));
    }

    acceptor->open(endpoint.protocol());
    acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true), error);
    if (error)
    {

        BOOST_LOG_TRIVIAL(warning) << "Cannot set REUSEADDR on " << host
                                   << " on " << port
                                   << ", error msg: " << error.message();
    }

    acceptor->bind(endpoint, error);
    if (error)
    {

        BOOST_LOG_TRIVIAL(error) << "Cannot bind " << host << " on " << port
                                 << " error msg: " << error.message();
        throw error;
    }

    acceptor->listen(boost::asio::socket_base::max_connections, error);
    if (error)
    {
        BOOST_LOG_TRIVIAL(error) << "Cannot listen " << host << " on " << port
                                 << ", error msg: " << error.message();
        throw error;
    }
    return acceptor;
}

void HttpServer::connection_error(ConnectionPtr connection,
                                  const boost::system::error_code& ec)
{
    if (ec != boost::asio::error::eof)
    {
        BOOST_LOG_TRIVIAL(warning)
            << "Got an error from a Connection: " << ec.message();
    }

    pool_.post([connection]
               { HTTP::Connection::disconnect(connection); });
}

void HttpServer::connection_recycle(ConnectionPtr connection)
{
    connection->start();
}

void HttpServer::connection_notify_request(ConnectionPtr connection,
                                           HTTP::Request&& request)
{
    if (sink_)
    {
        sink_(connection, std::forward<HTTP::Request>(request));
    }
    else
    {
        connection->response().setCode(HTTP::HttpCode::NoContent).setBody("");
        HTTP::setShouldConnectionBeClosed(request, connection->response());
        connection->sendResponse();
    }
}

}
<commit_msg>Refactor the accept_callback properly to allow stop/start on HttpServer<commit_after>/*
 * Part of HTTPP.
 *
 * Distributed under the 3-clause BSD licence (See LICENCE.TXT file at the
 * project root).
 *
 * Copyright (c) 2013 Thomas Sanchez.  All rights reserved.
 *
 */

#include "httpp/HttpServer.hpp"

#include <boost/log/trivial.hpp>
#include "httpp/http/Utils.hpp"

namespace HTTPP
{

HttpServer::HttpServer(size_t threads)
: service_(threads)
, pool_(threads, service_)
{
}

HttpServer::~HttpServer()
{
    if (running_)
    {
        stop();
    }
}

void HttpServer::start(ThreadInit fct)
{
    if (running_)
    {
        return;
    }
    running_ = true;
    pool_.start(fct);
}

void HttpServer::stop()
{
    if (!running_)
    {
        return;
    }

    running_ = false;
    for (auto acc : acceptors_)
    {
        boost::system::error_code ec;
        acc->cancel(ec);
        acc->close(ec);
    }

    acceptors_.clear();
    pool_.stop();
}

void HttpServer::bind(const std::string& address, const std::string& port)
{
    auto acc = HttpServer::bind(service_, address, port);
    BOOST_LOG_TRIVIAL(debug) << "Bind address: " << address
                             << " on port: " << port;
    acceptors_.push_back(acc);
    start_accept(acc);
}

void HttpServer::start_accept(AcceptorPtr acceptor)
{
    if (running_)
    {
        auto connection = new HTTP::Connection(*this, service_, pool_);
        //std::make_shared<HTTP::Connection>(*this, service_, pool_);

        acceptor->async_accept(connection->socket_,
                               std::bind(&HttpServer::accept_callback,
                                         this,
                                         std::placeholders::_1,
                                         acceptor,
                                         connection));
    }
}

void HttpServer::accept_callback(const boost::system::error_code& error,
                                 AcceptorPtr acceptor,
                                 ConnectionPtr connection)
{
    if (error)
    {
        if (error != boost::asio::error::operation_aborted)
        {
            BOOST_LOG_TRIVIAL(error)
                << "Error during accept: " << error.message();
        }

        delete connection;
    }

    if (running_)
    {
        BOOST_LOG_TRIVIAL(debug)
            << "New connection accepted from: " << connection->source();

        connection->start();
        start_accept(acceptor);
    }
    else
    {
        HTTP::Connection::disconnect(connection);
    }
}

HttpServer::AcceptorPtr HttpServer::bind(boost::asio::io_service& service,
                                         const std::string& host,
                                         const std::string& port)
{
    auto acceptor = AcceptorPtr(new Acceptor(service));
    boost::system::error_code error;
    auto addr = boost::asio::ip::address::from_string(host, error);
    boost::asio::ip::tcp::endpoint endpoint;
    if (error)
    {
        boost::asio::ip::tcp::resolver resolver(service);
        boost::asio::ip::tcp::resolver::query query(host, port);
        boost::asio::ip::tcp::resolver::iterator it = resolver.resolve(query),
                                                 end;

        if (it == end)
        {
            BOOST_LOG_TRIVIAL(error)
                << "Error bad address (ip address in dotted format or ipv6 hex format: "
                << host << ", error msg: " << error.message();
            throw error;
        }
        else
        {
            endpoint = *it;
        }
    }
    else
    {
        endpoint = boost::asio::ip::tcp::endpoint(addr, std::stoi(port));
    }

    acceptor->open(endpoint.protocol());
    acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true), error);
    if (error)
    {

        BOOST_LOG_TRIVIAL(warning) << "Cannot set REUSEADDR on " << host
                                   << " on " << port
                                   << ", error msg: " << error.message();
    }

    acceptor->bind(endpoint, error);
    if (error)
    {

        BOOST_LOG_TRIVIAL(error) << "Cannot bind " << host << " on " << port
                                 << " error msg: " << error.message();
        throw error;
    }

    acceptor->listen(boost::asio::socket_base::max_connections, error);
    if (error)
    {
        BOOST_LOG_TRIVIAL(error) << "Cannot listen " << host << " on " << port
                                 << ", error msg: " << error.message();
        throw error;
    }
    return acceptor;
}

void HttpServer::connection_error(ConnectionPtr connection,
                                  const boost::system::error_code& ec)
{
    if (ec != boost::asio::error::eof)
    {
        BOOST_LOG_TRIVIAL(warning)
            << "Got an error from a Connection: " << ec.message();
    }

    pool_.post([connection]
               { HTTP::Connection::disconnect(connection); });
}

void HttpServer::connection_recycle(ConnectionPtr connection)
{
    connection->start();
}

void HttpServer::connection_notify_request(ConnectionPtr connection,
                                           HTTP::Request&& request)
{
    if (sink_)
    {
        sink_(connection, std::forward<HTTP::Request>(request));
    }
    else
    {
        connection->response().setCode(HTTP::HttpCode::NoContent).setBody("");
        HTTP::setShouldConnectionBeClosed(request, connection->response());
        connection->sendResponse();
    }
}

}
<|endoftext|>


<commit_before>
/* IntroScene.cpp
 *
 * Copyright (C) 2013 Michael Imamura
 *
 * 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 "StdAfx.h"

#include "PagedTextDecor.h"
#include "Player.h"
#include "PlayerDecor.h"
#include "ResStr.h"
#include "SpriteMap.h"

#include "IntroScene.h"

namespace AISDL {

IntroScene::IntroScene(Director &director, Display &display) :
	SUPER(director, display, "Introduction")
{
}

IntroScene::~IntroScene()
{
}

void IntroScene::OnAction()
{
	if (!introTxt->NextPage(true)) {
		director.RequestNextScene();
	}
}

void IntroScene::Preload()
{
	const std::string dir = display.res.resDir + "/text/intro/";
	introTxt.reset(new PagedTextDecor(display, display.res.pixelFont,
		ResStr::Load(dir + "intro.txt"), 472, true));
}

void IntroScene::Reset()
{
	introTxt->FirstPage(true);

	auto player = director.GetMainPlayer();
	player->SetPos(40, 300);
	playerDecor.reset(new PlayerDecor(display, player,
		display.res.playerSprite));
}

void IntroScene::Advance(Uint32 tick)
{
	introTxt->Advance(tick);
}

void IntroScene::RenderContent()
{
	SDL_SetRenderDrawColor(display.renderer, 0x00, 0x00, 0x00, 0xff);
	SDL_RenderClear(display.renderer);
	display.SetLowRes();

	introTxt->Render(40, 40);

	playerDecor->Render();
	/*
	display.res.playerSprite->Render(40, 300, 0);
	display.res.playerSprite->Render(80, 300, 12);
	*/
}

}  // namespace AISDL

<commit_msg>Add a background to the text.<commit_after>
/* IntroScene.cpp
 *
 * Copyright (C) 2013 Michael Imamura
 *
 * 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 "StdAfx.h"

#include "PagedTextDecor.h"
#include "Player.h"
#include "PlayerDecor.h"
#include "ResStr.h"
#include "SpriteMap.h"

#include "IntroScene.h"

namespace AISDL {

IntroScene::IntroScene(Director &director, Display &display) :
	SUPER(director, display, "Introduction")
{
}

IntroScene::~IntroScene()
{
}

void IntroScene::OnAction()
{
	if (!introTxt->NextPage(true)) {
		director.RequestNextScene();
	}
}

void IntroScene::Preload()
{
	const std::string dir = display.res.resDir + "/text/intro/";
	introTxt.reset(new PagedTextDecor(display, display.res.pixelFont,
		ResStr::Load(dir + "intro.txt"), 432, true));
}

void IntroScene::Reset()
{
	introTxt->FirstPage(true);

	auto player = director.GetMainPlayer();
	player->SetPos(40, 300);
	playerDecor.reset(new PlayerDecor(display, player,
		display.res.playerSprite));
}

void IntroScene::Advance(Uint32 tick)
{
	introTxt->Advance(tick);
}

void IntroScene::RenderContent()
{
	SDL_SetRenderDrawColor(display.renderer, 0x00, 0x00, 0x00, 0xff);
	SDL_RenderClear(display.renderer);
	display.SetLowRes();

	// Draw the background behind the text.
	SDL_SetRenderDrawColor(display.renderer, 0x00, 0x1f, 0x00, 0xff);
	SDL_Rect textBg = {
		35, 35,
		432 + 10, introTxt->MeasureHeight() + 10
	};
	SDL_RenderFillRect(display.renderer, &textBg);

	introTxt->Render(40, 40);

	playerDecor->Render();
	/*
	display.res.playerSprite->Render(40, 300, 0);
	display.res.playerSprite->Render(80, 300, 12);
	*/
}

}  // namespace AISDL

<|endoftext|>


<commit_before>#include <LoadConfig.h>
#include <string.h>

#define MAXLINE  200
#include "defines.h"

//Equivale from sdt import *
using namespace std;

LoadConfig::LoadConfig(const string &pathFileName)

   //cast string to *char
   :fileConf(pathFileName.c_str())
{
	file2Map();
}

LoadConfig::~LoadConfig(){
   fileConf.close();
}

void LoadConfig::file2Map(){
  char *l;
  l = Malloc(char, MAXLINE);
  strcpy(l, "\0");
  while (fileConf.eof() == false){
#ifdef _WIN32
       fileConf.getline(l,MAXLINE, '\n');
#endif
#ifdef linux
 	  fileConf.getline(l,MAXLINE);
#endif
	   //printf("%s\n", l);
       string s(l);
       int ind_token = s.find("=");
       if (ind_token != string::npos){
           string key = trim(s.substr(0,ind_token-1));
           string value = trim( s.substr(ind_token+2,s.length()) );
           dicParameters[key] = value;
       }
	}
  free(l);
}

std::string LoadConfig::getParameter(const std::string &Parameter){
	return dicParameters[Parameter];
}

std::string LoadConfig::trim(std::string s){
    char l[MAXLINE] = "";
    char l2[MAXLINE]= "";
    strcpy(l,s.c_str());
    int i = 0;
    int j = 0;
    while (l[i] != '\0'){
        if (l[i] != ' '){
        	l2[j++] = l[i];
        };
        i++;
    }
    l2[j] = '\0';
	return string(l2);
}

char* LoadConfig::getParameterChar(const std::string &Parameter){
#ifdef _WIN32
	char * c = strdup(getParameter(Parameter).c_str());
	return c;
#endif

#ifdef linux
	return const_cast< char* > ( getParameter(Parameter).c_str() );
#endif

}
<commit_msg>Removing residual files<commit_after><|endoftext|>


<commit_before>/*
 *
 * Error Codes
 * 1.x - Sql Errors
 * 2.x - Launcher Errors
 * 3.x - Editor Errors
 * 4.x - Builder Errors
 * 5.x - Save Errors
 * 6.x - Edit Idea Name Errors
 *
 */

#include "MPLauncher.h"

MPLauncher::MPLauncher(void)
	:	BWindow(BRect(100, 100, 650, 400), "MasterPiece Launcher", B_TITLED_WINDOW,  B_NOT_H_RESIZABLE | B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS, B_CURRENT_WORKSPACE)
{
	// mplauncher is the main window of the application

	// gui control initialization
	mainGroup = new BGroupLayout(B_HORIZONTAL, 0.0);
	newThoughtButton = new BButton(BRect(10, 10, 90, 35), NULL, "Create a New...", new BMessage(CREATE_NEW_THT), B_FOLLOW_NONE, B_WILL_DRAW);
	newMasterpieceButton = new BButton(BRect(10, 10, 90, 35), NULL, "Create a New...", new BMessage(CREATE_NEW_MP), B_FOLLOW_NONE, B_WILL_DRAW);
	delThoughtButton = new BButton(BRect(10, 10, 90, 35), NULL, "Delete Selected...", new BMessage(DELETE_THT), B_FOLLOW_NONE, B_WILL_DRAW);
	delMasterpieceButton = new BButton(BRect(10, 10, 90, 35), NULL, "Delete Selected...", new BMessage(DELETE_MP), B_FOLLOW_NONE, B_WILL_DRAW);
	thoughtStringView = new BStringView(BRect(10, 10, 200, 30), NULL, "Work on a Thought");
	masterpieceStringView = new BStringView(BRect(10, 10, 200, 30), NULL, "Work on a Masterpiece");
	openMasterpieceStringView = new BStringView(BRect(10, 10, 200, 30), NULL, "Open an Existing...");
	openThoughtStringView = new BStringView(BRect(10, 10, 200, 30), NULL, "Open an Existing...");
	openThoughtListView = new BListView(BRect(10, 10, 100, 30), NULL, B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL, B_WILL_DRAW);
	openMasterpieceListView = new BListView(BRect(10, 10, 100, 30), NULL, B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL, B_WILL_DRAW);
	backView = new BView(Bounds(), "backview", B_FOLLOW_ALL, B_WILL_DRAW);
	backView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
	AddChild(backView);
	// layout builder code
	backView->SetLayout(mainGroup);
	backView->AddChild(BGridLayoutBuilder()
		.Add(masterpieceStringView, 0, 0)
		.Add(BSpaceLayoutItem::CreateGlue(), 1, 0)
		.Add(thoughtStringView, 2, 0)
		.Add(BSpaceLayoutItem::CreateGlue(), 3, 0)
		.Add(newMasterpieceButton, 0, 1)
		.Add(delMasterpieceButton, 1, 1)
		.Add(BSpaceLayoutItem::CreateGlue(), 1, 0)
		.Add(newThoughtButton, 2, 1)
		.Add(delThoughtButton, 3, 1)
		.Add(openMasterpieceStringView, 0, 2)
		.Add(BSpaceLayoutItem::CreateGlue(), 1, 2)
		.Add(openThoughtStringView, 2, 2)
		.Add(BSpaceLayoutItem::CreateGlue(), 3, 2)
		.Add(new BScrollView("scroll_masterpiecelist", openMasterpieceListView,  B_FOLLOW_ALL_SIDES, 0, false, true, B_FANCY_BORDER), 0, 3, 2, 3)
		.Add(new BScrollView("scroll_thoughtlist", openThoughtListView,  B_FOLLOW_ALL_SIDES, 0, false, true, B_FANCY_BORDER), 2, 3, 2, 3)
		.SetInsets(5, 5, 5, 2)
	);
	PopulateLauncherListViews(); // populate listview's here
	openMasterpieceListView->SetInvocationMessage(new BMessage(OPEN_EXISTING_MP)); // double click action
	openThoughtListView->SetInvocationMessage(new BMessage(OPEN_EXISTING_THT)); // double click action
}
void MPLauncher::MessageReceived(BMessage* msg)
{
	switch(msg->what)
	{
		case CREATE_NEW_MP: // create new mp by opening mp builder
			mpBuilder = new MPBuilder(BMessage(SHOW_LAUNCHER), BMessenger(this), "MasterPiece Builder - untitled", -1);
			mpBuilder->Show();
			this->Hide();
			break;
		case CREATE_NEW_THT: // create new thought by opening thought editor
			mpEditor = new MPEditor(BMessage(SHOW_LAUNCHER), BMessenger(this), "MasterPiece Editor - untitled", -1);
			mpEditor->Show();
			this->Hide();
			break;
		case OPEN_EXISTING_MP: // open existing mp by selecting from listview
			selected = openMasterpieceListView->CurrentSelection(); // list item value
			if(selected < 0) // if selected nothing, open empty builder window
			{
				mpBuilder = new MPBuilder(BMessage(SHOW_LAUNCHER), BMessenger(this), "MasterPiece Builder - untitled", -1);
				mpBuilder->Show();
				this->Hide();
			}
			else // you selected an actual existing mp from listview
			{
				IdeaStringItem* item;
				item = dynamic_cast<IdeaStringItem*>(openMasterpieceListView->ItemAt(selected));
				BString tmpText;
				tmpText = "MasterPiece Builder - ";
				tmpText += item->Text();
				mpBuilder = new MPBuilder(BMessage(SHOW_LAUNCHER), BMessenger(this), tmpText, item->ReturnID());
				mpBuilder->Show();
				this->Hide();
			}
			break;
		case OPEN_EXISTING_THT: // open existing thought by selecting from listview
			selected = openThoughtListView->CurrentSelection(); // list item value
			if(selected < 0) // if selected nothing, open empty builder window
			{
				mpEditor = new MPEditor(BMessage(SHOW_LAUNCHER), BMessenger(this), "MasterPiece Editor - untitled", -1);
				mpEditor->Show();
				this->Hide();
			}
			else // you selected an actual existing thought from listview
			{
				IdeaStringItem* item;
				item = dynamic_cast<IdeaStringItem*>(openThoughtListView->ItemAt(selected));
				BString tmpText;
				tmpText = "MasterPiece Editor - ";
				tmpText += item->Text();
				mpEditor = new MPEditor(BMessage(SHOW_LAUNCHER), BMessenger(this), tmpText, item->ReturnID());
				mpEditor->Show();
				this->Hide();
			}
			break;
		case SHOW_LAUNCHER:  // once finished with editor or builder, call to show this launcher
			if(msg->FindInt64("showLauncher", &showLauncher) == B_OK) // message was found
			{
				if(showLauncher == 1)
				{
					PopulateLauncherListViews(); // rerun the sql and repopulate the 2 listviews with any updated values
					if(this->IsHidden())
					{
						this->Show();
					}
				}
				else if(showLauncher == 0)
				{
					this->Hide();
				}
				else
				{
					eAlert = new ErrorAlert("2.1 Launcher Error: Illegal Value was returned.");
					eAlert->Launch();
					// big error must display
				}
			}
			else // message not found
			{
				eAlert = new ErrorAlert("2.2 Launcher Error: Message Variable was not found.");
				eAlert->Launch();
			}
			break;
		default:
		{
			BWindow::MessageReceived(msg);
			break;
		}
	}
}
bool MPLauncher::QuitRequested(void)
{
	be_app->PostMessage(B_QUIT_REQUESTED); // exit application
	return true;
}
void MPLauncher::PopulateLauncherListViews(void)
{
	openMasterpieceListView->MakeEmpty();
	openThoughtListView->MakeEmpty();
	sqlObject = new SqlObject(ideaStatement, "5"); // open sqldb
	sqlObject->PrepareSql("select ideaname, ideaid from ideatable where ismp = 1"); // prepare sql
	while(sqlObject->StepSql() == SQLITE_ROW) // step through the sql
	{
		openMasterpieceListView->AddItem(new IdeaStringItem(sqlObject->ReturnText(0), sqlObject->ReturnInt(1))); // populate listview
	}
	sqlObject->FinalizeSql(); // finalize sql
	sqlObject->CloseSql(); // close sql

	sqlObject = new SqlObject(ideaStatement, "6"); // open sqldb
	sqlObject->PrepareSql("select ideaname, ideaid from ideatable where ismp = 0"); // prepare sql
	while(sqlObject->StepSql() == SQLITE_ROW) // step through the sql
	{
		openThoughtListView->AddItem(new IdeaStringItem(sqlObject->ReturnText(0), sqlObject->ReturnInt(1))); // populate listview
	}
	sqlObject->FinalizeSql(); // finalize sql
	sqlObject->CloseSql(); // close sql
}
<commit_msg>working on gui corrections<commit_after>/*
 *
 * Error Codes
 * 1.x - Sql Errors
 * 2.x - Launcher Errors
 * 3.x - Editor Errors
 * 4.x - Builder Errors
 * 5.x - Save Errors
 * 6.x - Edit Idea Name Errors
 *
 */

#include "MPLauncher.h"

MPLauncher::MPLauncher(void)
	:	BWindow(BRect(100, 100, 650, 400), "MasterPiece Launcher", B_TITLED_WINDOW,  B_NOT_H_RESIZABLE | B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS, B_CURRENT_WORKSPACE)
{
	// mplauncher is the main window of the application

	// gui control initialization
	mainGroup = new BGroupLayout(B_HORIZONTAL, 0.0);
	newThoughtButton = new BButton(BRect(10, 10, 90, 35), NULL, "Create a New...", new BMessage(CREATE_NEW_THT), B_FOLLOW_NONE, B_WILL_DRAW);
	newMasterpieceButton = new BButton(BRect(10, 10, 90, 35), NULL, "Create a New...", new BMessage(CREATE_NEW_MP), B_FOLLOW_NONE, B_WILL_DRAW);
	delThoughtButton = new BButton(BRect(10, 10, 90, 35), NULL, "Delete Selected...", new BMessage(DELETE_THT), B_FOLLOW_NONE, B_WILL_DRAW);
	delMasterpieceButton = new BButton(BRect(10, 10, 90, 35), NULL, "Delete Selected...", new BMessage(DELETE_MP), B_FOLLOW_NONE, B_WILL_DRAW);
	thoughtStringView = new BStringView(BRect(10, 10, 200, 30), NULL, "Work on a Thought");
	masterpieceStringView = new BStringView(BRect(10, 10, 200, 30), NULL, "Work on a Masterpiece");
	openMasterpieceStringView = new BStringView(BRect(10, 10, 200, 30), NULL, "Open an Existing...");
	openThoughtStringView = new BStringView(BRect(10, 10, 200, 30), NULL, "Open an Existing...");
	openThoughtListView = new BListView(BRect(10, 10, 100, 30), NULL, B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL, B_WILL_DRAW);
	openMasterpieceListView = new BListView(BRect(10, 10, 100, 30), NULL, B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL, B_WILL_DRAW);
	backView = new BView(Bounds(), "backview", B_FOLLOW_ALL, B_WILL_DRAW);
	backView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
	AddChild(backView);
	// layout builder code
	backView->SetLayout(mainGroup);
	backView->AddChild(BGridLayoutBuilder()
		.Add(masterpieceStringView, 0, 0)
		.Add(BSpaceLayoutItem::CreateGlue(), 1, 0)
		.Add(thoughtStringView, 2, 0)
		.Add(BSpaceLayoutItem::CreateGlue(), 3, 0)
		.Add(BSpaceLayoutItem::CreateGlue(), 4, 0)
		.Add(newMasterpieceButton, 0, 1)
		.Add(delMasterpieceButton, 1, 1)
		.Add(BSpaceLayoutItem::CreateGlue(), 1, 0)
		.Add(newThoughtButton, 2, 1)
		.Add(delThoughtButton, 3, 1)
		.Add(openMasterpieceStringView, 0, 2)
		.Add(BSpaceLayoutItem::CreateGlue(), 1, 2)
		.Add(openThoughtStringView, 2, 2)
		.Add(BSpaceLayoutItem::CreateGlue(), 3, 2)
		.Add(new BScrollView("scroll_masterpiecelist", openMasterpieceListView,  B_FOLLOW_ALL_SIDES, 0, false, true, B_FANCY_BORDER), 0, 3, 2, 3)
		.Add(new BScrollView("scroll_thoughtlist", openThoughtListView,  B_FOLLOW_ALL_SIDES, 0, false, true, B_FANCY_BORDER), 2, 3, 2, 3)
		.SetInsets(5, 5, 5, 2)
	);
	PopulateLauncherListViews(); // populate listview's here
	openMasterpieceListView->SetInvocationMessage(new BMessage(OPEN_EXISTING_MP)); // double click action
	openThoughtListView->SetInvocationMessage(new BMessage(OPEN_EXISTING_THT)); // double click action
}
void MPLauncher::MessageReceived(BMessage* msg)
{
	switch(msg->what)
	{
		case CREATE_NEW_MP: // create new mp by opening mp builder
			mpBuilder = new MPBuilder(BMessage(SHOW_LAUNCHER), BMessenger(this), "MasterPiece Builder - untitled", -1);
			mpBuilder->Show();
			this->Hide();
			break;
		case CREATE_NEW_THT: // create new thought by opening thought editor
			mpEditor = new MPEditor(BMessage(SHOW_LAUNCHER), BMessenger(this), "MasterPiece Editor - untitled", -1);
			mpEditor->Show();
			this->Hide();
			break;
		case OPEN_EXISTING_MP: // open existing mp by selecting from listview
			selected = openMasterpieceListView->CurrentSelection(); // list item value
			if(selected < 0) // if selected nothing, open empty builder window
			{
				mpBuilder = new MPBuilder(BMessage(SHOW_LAUNCHER), BMessenger(this), "MasterPiece Builder - untitled", -1);
				mpBuilder->Show();
				this->Hide();
			}
			else // you selected an actual existing mp from listview
			{
				IdeaStringItem* item;
				item = dynamic_cast<IdeaStringItem*>(openMasterpieceListView->ItemAt(selected));
				BString tmpText;
				tmpText = "MasterPiece Builder - ";
				tmpText += item->Text();
				mpBuilder = new MPBuilder(BMessage(SHOW_LAUNCHER), BMessenger(this), tmpText, item->ReturnID());
				mpBuilder->Show();
				this->Hide();
			}
			break;
		case OPEN_EXISTING_THT: // open existing thought by selecting from listview
			selected = openThoughtListView->CurrentSelection(); // list item value
			if(selected < 0) // if selected nothing, open empty builder window
			{
				mpEditor = new MPEditor(BMessage(SHOW_LAUNCHER), BMessenger(this), "MasterPiece Editor - untitled", -1);
				mpEditor->Show();
				this->Hide();
			}
			else // you selected an actual existing thought from listview
			{
				IdeaStringItem* item;
				item = dynamic_cast<IdeaStringItem*>(openThoughtListView->ItemAt(selected));
				BString tmpText;
				tmpText = "MasterPiece Editor - ";
				tmpText += item->Text();
				mpEditor = new MPEditor(BMessage(SHOW_LAUNCHER), BMessenger(this), tmpText, item->ReturnID());
				mpEditor->Show();
				this->Hide();
			}
			break;
		case SHOW_LAUNCHER:  // once finished with editor or builder, call to show this launcher
			if(msg->FindInt64("showLauncher", &showLauncher) == B_OK) // message was found
			{
				if(showLauncher == 1)
				{
					PopulateLauncherListViews(); // rerun the sql and repopulate the 2 listviews with any updated values
					if(this->IsHidden())
					{
						this->Show();
					}
				}
				else if(showLauncher == 0)
				{
					this->Hide();
				}
				else
				{
					eAlert = new ErrorAlert("2.1 Launcher Error: Illegal Value was returned.");
					eAlert->Launch();
					// big error must display
				}
			}
			else // message not found
			{
				eAlert = new ErrorAlert("2.2 Launcher Error: Message Variable was not found.");
				eAlert->Launch();
			}
			break;
		default:
		{
			BWindow::MessageReceived(msg);
			break;
		}
	}
}
bool MPLauncher::QuitRequested(void)
{
	be_app->PostMessage(B_QUIT_REQUESTED); // exit application
	return true;
}
void MPLauncher::PopulateLauncherListViews(void)
{
	openMasterpieceListView->MakeEmpty();
	openThoughtListView->MakeEmpty();
	sqlObject = new SqlObject(ideaStatement, "5"); // open sqldb
	sqlObject->PrepareSql("select ideaname, ideaid from ideatable where ismp = 1"); // prepare sql
	while(sqlObject->StepSql() == SQLITE_ROW) // step through the sql
	{
		openMasterpieceListView->AddItem(new IdeaStringItem(sqlObject->ReturnText(0), sqlObject->ReturnInt(1))); // populate listview
	}
	sqlObject->FinalizeSql(); // finalize sql
	sqlObject->CloseSql(); // close sql

	sqlObject = new SqlObject(ideaStatement, "6"); // open sqldb
	sqlObject->PrepareSql("select ideaname, ideaid from ideatable where ismp = 0"); // prepare sql
	while(sqlObject->StepSql() == SQLITE_ROW) // step through the sql
	{
		openThoughtListView->AddItem(new IdeaStringItem(sqlObject->ReturnText(0), sqlObject->ReturnInt(1))); // populate listview
	}
	sqlObject->FinalizeSql(); // finalize sql
	sqlObject->CloseSql(); // close sql
}
<|endoftext|>


<commit_before>#include "MQTTClient.h"

void messageArrived(MQTT::MessageData& messageData) {
  MQTT::Message &message = messageData.message;
  int len = messageData.topicName.lenstring.len;
  char topic[len+1];
  memcpy(topic, messageData.topicName.lenstring.data, len);
  topic[len] = '\0';
  messageReceived(String(topic), (char*)message.payload, message.payloadlen);
}

MQTTClient::MQTTClient(const char * _hostname, int _port, Client& _client) {
  this->client = new MQTT::Client<Network, Timer, MQTT_BUFFER_SIZE>(this->network);
  this->network.setClient(&_client);
  this->hostname = _hostname;
  this->port = _port;
}

boolean MQTTClient::connect(const char * clientId) {
  return this->connect(clientId, "", "");
}

boolean MQTTClient::connect(const char * clientId, const char * username, const char * password) {
  if(!this->network.connect((char*)this->hostname, this->port)) {
    return false;
  }

  MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
  data.clientID.cstring = (char*)clientId;
  if(username && password) {
    data.username.cstring = (char*)username;
    data.password.cstring = (char*)password;
  }

  return this->client->connect(data) == 0;
}

boolean MQTTClient::publish(String topic, String payload) {
  return this->publish(topic.c_str(), payload.c_str());
}

boolean MQTTClient::publish(const char * topic, String payload) {
  return this->publish(topic, payload.c_str());
}

boolean MQTTClient::publish(const char * topic, const char * payload) {
  MQTT::Message message;
  message.qos = MQTT::QOS0;
  message.retained = false;
  message.dup = false;
  message.payload = (char*)payload;
  message.payloadlen = strlen(payload);
  return client->publish(topic, message) == 0;
}

boolean MQTTClient::subscribe(String topic) {
  return this->subscribe(topic.c_str());
}

boolean MQTTClient::subscribe(const char * topic) {
  return client->subscribe(topic, MQTT::QOS0, messageArrived) == 0;
}

boolean MQTTClient::unsubscribe(String topic) {
  return this->unsubscribe(topic.c_str());
}

boolean MQTTClient::unsubscribe(const char * topic) {
  return client->unsubscribe(topic) == 0;
}

boolean MQTTClient::loop() {
  this->client->yield(100);
}

boolean MQTTClient::connected() {
  return this->client->isConnected();
}

void MQTTClient::disconnect() {
  this->client->disconnect();
}
<commit_msg>set timeout to 10 for ok speed<commit_after>#include "MQTTClient.h"

void messageArrived(MQTT::MessageData& messageData) {
  MQTT::Message &message = messageData.message;
  int len = messageData.topicName.lenstring.len;
  char topic[len+1];
  memcpy(topic, messageData.topicName.lenstring.data, len);
  topic[len] = '\0';
  messageReceived(String(topic), (char*)message.payload, message.payloadlen);
}

MQTTClient::MQTTClient(const char * _hostname, int _port, Client& _client) {
  this->client = new MQTT::Client<Network, Timer, MQTT_BUFFER_SIZE>(this->network);
  this->network.setClient(&_client);
  this->hostname = _hostname;
  this->port = _port;
}

boolean MQTTClient::connect(const char * clientId) {
  return this->connect(clientId, "", "");
}

boolean MQTTClient::connect(const char * clientId, const char * username, const char * password) {
  if(!this->network.connect((char*)this->hostname, this->port)) {
    return false;
  }

  MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
  data.clientID.cstring = (char*)clientId;
  if(username && password) {
    data.username.cstring = (char*)username;
    data.password.cstring = (char*)password;
  }

  return this->client->connect(data) == 0;
}

boolean MQTTClient::publish(String topic, String payload) {
  return this->publish(topic.c_str(), payload.c_str());
}

boolean MQTTClient::publish(const char * topic, String payload) {
  return this->publish(topic, payload.c_str());
}

boolean MQTTClient::publish(const char * topic, const char * payload) {
  MQTT::Message message;
  message.qos = MQTT::QOS0;
  message.retained = false;
  message.dup = false;
  message.payload = (char*)payload;
  message.payloadlen = strlen(payload);
  return client->publish(topic, message) == 0;
}

boolean MQTTClient::subscribe(String topic) {
  return this->subscribe(topic.c_str());
}

boolean MQTTClient::subscribe(const char * topic) {
  return client->subscribe(topic, MQTT::QOS0, messageArrived) == 0;
}

boolean MQTTClient::unsubscribe(String topic) {
  return this->unsubscribe(topic.c_str());
}

boolean MQTTClient::unsubscribe(const char * topic) {
  return client->unsubscribe(topic) == 0;
}

boolean MQTTClient::loop() {
  this->client->yield(10);
}

boolean MQTTClient::connected() {
  return this->client->isConnected();
}

void MQTTClient::disconnect() {
  this->client->disconnect();
}
<|endoftext|>


<commit_before>#include "MainWindow.h"
#include "TcxHandler.h"
#include "TrackLAyer.h"

#include <QFileDialog>
#include <QGridLayout>
#include <QMenu>
#include <QMessageBox>
#include <QWidget>
#include <QXmlInputSource>
#include <QXmlSimpleReader>

MainWindow::MainWindow(GLWidget *glWidget,
                       QWidget * parent,
                       Qt::WindowFlags flags) :
    QMainWindow::QMainWindow(parent, flags),
    _menuBar(new QMenuBar(0)),
    _glWidget(glWidget)
{
    QWidget *ctr = new QWidget(this);
    setCentralWidget(ctr);
    _rewindButton = new QPushButton("<<", ctr);
    _backButton = new QPushButton("<", ctr);
    _pauseButton = new QPushButton("x",ctr);
    _forwardButton = new QPushButton(">", ctr);
    _playSpeedCombo = new QComboBox(ctr);
    _playSpeedCombo->addItem("1x");
    _playSpeedCombo->addItem("2x");
    _playSpeedCombo->addItem("4x");
    _playSpeedCombo->addItem("8x");
    _playSpeedCombo->addItem("16x");
    _playSpeedCombo->addItem("32x");
    _playSpeedCombo->addItem("64x");
    _slider = new QSlider(Qt::Horizontal, ctr);
    _currentTimeLineEdit = new QLineEdit(ctr);
    _currentTimeLineEdit->setReadOnly(true);
    _currentTimeLineEdit->setText("0");
    _currentTimeLineEdit->setAlignment(Qt::AlignRight);
    _layout(ctr);
    QMenu *_fileMenu = _menuBar->addMenu("File");
    _openLayerAction = new QAction("Open Layer. . .", this);
    _forwardAction = new QAction("Play", this);
    _backAction = new QAction("Reverse", this);
    _rewindAction = new QAction("Rewind", this);
    _pauseAction = new QAction("Pause", this);
    _fileMenu->addAction(_openLayerAction);
    connect(_openLayerAction, SIGNAL(triggered(bool)),
            this, SLOT(slotLoadFile()));
    connect(_forwardButton, SIGNAL(clicked(bool)),
            _forwardAction, SLOT(trigger()));
    connect(_backButton, SIGNAL(clicked(bool)),
            _backAction, SLOT(trigger()));
    connect(_pauseButton, SIGNAL(clicked(bool)),
            _pauseAction, SLOT(trigger()));
    connect(_rewindButton, SIGNAL(clicked(bool)),
            _rewindAction, SLOT(trigger()));
    connect(_playSpeedCombo, SIGNAL(activated(const QString&)),
            this, SLOT(slotPlaybackRateChanged(const QString&)));

    connect(_forwardAction, SIGNAL(triggered()),
            _glWidget, SLOT(slotPlay()));
    connect(_backAction, SIGNAL(triggered()),
            _glWidget, SLOT(slotReverse()));
    connect(_pauseAction, SIGNAL(triggered()),
            _glWidget, SLOT(slotPause()));
    connect(_rewindAction, SIGNAL(triggered()),
            _glWidget, SLOT(slotRewind()));

    connect(_glWidget, SIGNAL(signalTimeChanged(double)),
            this, SLOT(slotTimeChanged(double)));
    connect(_glWidget->getMap(), SIGNAL(signalLayerAdded()),
            this, SLOT(slotLayerAdded()));

    // DEBUG
    loadTcxFile(new QFile("/Users/dal/Dropbox/tmp/10-8-13 6-29-18 PM.tcx"));
}

MainWindow::~MainWindow()
{
    // empty
}

void
MainWindow::_layout(QWidget *ctr)
{
    QGridLayout *_layout = new QGridLayout(ctr);
    _layout->addWidget(_rewindButton, 0, 0);
    _layout->addWidget(_backButton, 0, 1);
    _layout->addWidget(_pauseButton, 0, 2);
    _layout->addWidget(_forwardButton, 0, 3);
    _layout->addWidget(_playSpeedCombo, 0, 4);
    _layout->addWidget(_slider, 1, 0, 1, 4);
    _layout->addWidget(_currentTimeLineEdit, 1, 4);
}

void
MainWindow::loadTcxFile(QFile *tcxFile)
{
    QList<Track*> tracks;
    TcxHandler *handler = new TcxHandler(&tracks);
    QXmlSimpleReader *reader = new QXmlSimpleReader();
    reader->setContentHandler(handler);
    reader->setErrorHandler(handler);

    QString msg = QString("File '%1' does not exist").arg(tcxFile->fileName());

    if (!tcxFile->exists()) {
        QMessageBox::critical(this, msg, msg);
    }

    QXmlInputSource *source = new QXmlInputSource(tcxFile);

    reader->parse(source, true /*incremental*/);
    while (reader->parseContinue()) { };
    Track *thisTrack;
    foreach(thisTrack, tracks) {
        TrackLayer *thisLayer = new TrackLayer(thisTrack);
        _glWidget->getMap()->addLayer(thisLayer);
    }
}

void
MainWindow::slotLoadFile()
{
    QString path = QFileDialog::getOpenFileName(this, "Select tcx file");
    if (!path.isEmpty()) {
        QFile *tcxFile = new QFile(path);
        loadTcxFile(tcxFile);
    }
}

void
MainWindow::slotPlaybackRateChanged(const QString &newRate)
{
    QString rate(newRate);
    if (rate.endsWith("x"))
        rate.chop(1);
    bool ok = false;
    double theRate = rate.toDouble(&ok);
    if (ok)
        _glWidget->setPlaybackRate(theRate);
}

void
MainWindow::slotTimeChanged(double mapSeconds)
{
    int hours = mapSeconds / 3600;
    int modhrs = int(mapSeconds) % 3600;
    int mins = modhrs / 60;
    int secs = modhrs % 60;
    QChar zero('0');
    QString time = QString("%1hr%2m%3s").arg(hours)
                                        .arg(mins, 2, 10, zero)
                                        .arg(secs, 2, 10, zero);
    _currentTimeLineEdit->setText(time);
    _slider->setSliderPosition(int(mapSeconds));
}

void
MainWindow::slotLayerAdded()
{
    int dur = _glWidget->getMap()->getDuration();
    _slider->setMaximum(dur);
}
<commit_msg>Stretchy slider.<commit_after>#include "MainWindow.h"
#include "TcxHandler.h"
#include "TrackLAyer.h"

#include <QFileDialog>
#include <QGridLayout>
#include <QMenu>
#include <QMessageBox>
#include <QWidget>
#include <QXmlInputSource>
#include <QXmlSimpleReader>

MainWindow::MainWindow(GLWidget *glWidget,
                       QWidget * parent,
                       Qt::WindowFlags flags) :
    QMainWindow::QMainWindow(parent, flags),
    _menuBar(new QMenuBar(0)),
    _glWidget(glWidget)
{
    QWidget *ctr = new QWidget(this);
    setCentralWidget(ctr);
    _rewindButton = new QPushButton("<<", ctr);
    _backButton = new QPushButton("<", ctr);
    _pauseButton = new QPushButton("x",ctr);
    _forwardButton = new QPushButton(">", ctr);
    _playSpeedCombo = new QComboBox(ctr);
    _playSpeedCombo->addItem("1x");
    _playSpeedCombo->addItem("2x");
    _playSpeedCombo->addItem("4x");
    _playSpeedCombo->addItem("8x");
    _playSpeedCombo->addItem("16x");
    _playSpeedCombo->addItem("32x");
    _playSpeedCombo->addItem("64x");
    _slider = new QSlider(Qt::Horizontal, ctr);
    _currentTimeLineEdit = new QLineEdit(ctr);
    _currentTimeLineEdit->setReadOnly(true);
    _currentTimeLineEdit->setText("0");
    _currentTimeLineEdit->setAlignment(Qt::AlignRight);
    _layout(ctr);
    QMenu *_fileMenu = _menuBar->addMenu("File");
    _openLayerAction = new QAction("Open Layer. . .", this);
    _forwardAction = new QAction("Play", this);
    _backAction = new QAction("Reverse", this);
    _rewindAction = new QAction("Rewind", this);
    _pauseAction = new QAction("Pause", this);
    _fileMenu->addAction(_openLayerAction);
    connect(_openLayerAction, SIGNAL(triggered(bool)),
            this, SLOT(slotLoadFile()));
    connect(_forwardButton, SIGNAL(clicked(bool)),
            _forwardAction, SLOT(trigger()));
    connect(_backButton, SIGNAL(clicked(bool)),
            _backAction, SLOT(trigger()));
    connect(_pauseButton, SIGNAL(clicked(bool)),
            _pauseAction, SLOT(trigger()));
    connect(_rewindButton, SIGNAL(clicked(bool)),
            _rewindAction, SLOT(trigger()));
    connect(_playSpeedCombo, SIGNAL(activated(const QString&)),
            this, SLOT(slotPlaybackRateChanged(const QString&)));

    connect(_forwardAction, SIGNAL(triggered()),
            _glWidget, SLOT(slotPlay()));
    connect(_backAction, SIGNAL(triggered()),
            _glWidget, SLOT(slotReverse()));
    connect(_pauseAction, SIGNAL(triggered()),
            _glWidget, SLOT(slotPause()));
    connect(_rewindAction, SIGNAL(triggered()),
            _glWidget, SLOT(slotRewind()));

    connect(_glWidget, SIGNAL(signalTimeChanged(double)),
            this, SLOT(slotTimeChanged(double)));
    connect(_glWidget->getMap(), SIGNAL(signalLayerAdded()),
            this, SLOT(slotLayerAdded()));

    slotTimeChanged(0);
    // DEBUG
    loadTcxFile(new QFile("/Users/dal/Dropbox/tmp/10-8-13 6-29-18 PM.tcx"));
}

MainWindow::~MainWindow()
{
    // empty
}

void
MainWindow::_layout(QWidget *ctr)
{
    QGridLayout *_layout = new QGridLayout(ctr);
    _layout->addWidget(_rewindButton, 0, 0);
    _layout->addWidget(_backButton, 0, 1);
    _layout->addWidget(_pauseButton, 0, 2);
    _layout->addWidget(_forwardButton, 0, 3);
    _layout->addWidget(_playSpeedCombo, 0, 4);
    _layout->addWidget(_slider, 1, 0, 1, 4);
    _layout->addWidget(_currentTimeLineEdit, 1, 4);
    for (int i=0; i < _layout->columnCount(); i++)
        _layout->setColumnStretch(i, 1);
}

void
MainWindow::loadTcxFile(QFile *tcxFile)
{
    QList<Track*> tracks;
    TcxHandler *handler = new TcxHandler(&tracks);
    QXmlSimpleReader *reader = new QXmlSimpleReader();
    reader->setContentHandler(handler);
    reader->setErrorHandler(handler);

    QString msg = QString("File '%1' does not exist").arg(tcxFile->fileName());

    if (!tcxFile->exists()) {
        QMessageBox::critical(this, msg, msg);
    }

    QXmlInputSource *source = new QXmlInputSource(tcxFile);

    reader->parse(source, true /*incremental*/);
    while (reader->parseContinue()) { };
    Track *thisTrack;
    foreach(thisTrack, tracks) {
        TrackLayer *thisLayer = new TrackLayer(thisTrack);
        _glWidget->getMap()->addLayer(thisLayer);
    }
}

void
MainWindow::slotLoadFile()
{
    QString path = QFileDialog::getOpenFileName(this, "Select tcx file");
    if (!path.isEmpty()) {
        QFile *tcxFile = new QFile(path);
        loadTcxFile(tcxFile);
    }
}

void
MainWindow::slotPlaybackRateChanged(const QString &newRate)
{
    QString rate(newRate);
    if (rate.endsWith("x"))
        rate.chop(1);
    bool ok = false;
    double theRate = rate.toDouble(&ok);
    if (ok)
        _glWidget->setPlaybackRate(theRate);
}

void
MainWindow::slotTimeChanged(double mapSeconds)
{
    int hours = mapSeconds / 3600;
    int modhrs = int(mapSeconds) % 3600;
    int mins = modhrs / 60;
    int secs = modhrs % 60;
    QChar zero('0');
    QString time = QString("%1hr%2m%3s").arg(hours)
                                        .arg(mins, 2, 10, zero)
                                        .arg(secs, 2, 10, zero);
    _currentTimeLineEdit->setText(time);
    _slider->setSliderPosition(int(mapSeconds));
}

void
MainWindow::slotLayerAdded()
{
    int dur = _glWidget->getMap()->getDuration();
    _slider->setMaximum(dur);
}
<|endoftext|>


<commit_before>// Local
#include "MainWindow.h"
#include "ui_MainWindow.h"

#include "ShadowSettings.h"

#include "GraphicsRoundedRectItem.h"

// Qt
#include <QGraphicsRectItem>
#include <QFileDialog>
#include <QMessageBox>
#include <QSettings>
#include <QMenu>
#include <QInputDialog>
#include <QDebug>

MainWindow::MainWindow(QWidget* parent)
  : QMainWindow(parent)
  , ui(new Ui::MainWindow)
  , m_settings(new QSettings)
  , m_width(40)
  , m_height(40)
  , m_radius(0)
  , m_scale(1)
{
  ui->setupUi(this);

  m_scene = new QGraphicsScene(this);

  m_baseItem = new GraphicsRoundedRectItem();
  m_baseItem->setBrush(QBrush(Qt::white));
  m_baseItem->setPen(QPen(Qt::NoBrush, 0, Qt::NoPen));
  m_baseItem->setZValue(1000);

  m_scene->addItem(m_baseItem);
  ui->graphicsView->setScene(m_scene);
  addShadow();

  connect(ui->scaleSlider, SIGNAL(valueChanged(int)), SLOT(userScaleChanged(int)));

  connect(ui->widthBox, SIGNAL(valueChanged(int)), SLOT(userSourceChanged()));
  connect(ui->heightBox, SIGNAL(valueChanged(int)), SLOT(userSourceChanged()));
  connect(ui->radiusBox, SIGNAL(valueChanged(int)), SLOT(userSourceChanged()));

  connect(ui->addShadowButton, SIGNAL(clicked()), SLOT(addShadow()));

  connect(this, SIGNAL(sourceOptionsChanged(int,int,int)), SLOT(updateSource()));
  connect(this, SIGNAL(scaleChanged(qreal)), SLOT(updateSource()));

  // Hack: position view to the center of layout
  //
  // This is the only way I've found to ensure the item will be placed in the center of view: we simply make the view
  // rectangle definitely larger than the view itself, turn off the scroll bars display (in the UI file) and forcing
  // positioning on the center of the base item. If the scene rect is smaller than the view itself, QGraphicsView
  // control simply ignores QGraphicsView::centerOn calls
  ui->graphicsView->setSceneRect(-1000, -1000, 2000, 2000);

  updateSource();
  updatePresets();
}

MainWindow::~MainWindow()
{
  delete ui;
}

void MainWindow::on_saveButton_clicked()
{
  // File name
  QString fileName = QFileDialog::getSaveFileName(this, tr("Save rendered image as..."), QString(),
                                                  "PNG image (*.png)");
  if (fileName.isEmpty())
    return;
  if (!fileName.endsWith(".png", Qt::CaseInsensitive))
    fileName.append(".png");

  // Source scene rect to render
  // We must use the aligned rectangle to not mess with the non-integer items coordinates
  QRectF sourceRect = QRectF(m_scene->itemsBoundingRect().toAlignedRect());

  QImage target(sourceRect.width(), sourceRect.height(), QImage::Format_ARGB32_Premultiplied);
  target.fill(Qt::transparent);

  QPainter p(&target);
  p.setRenderHint(QPainter::Antialiasing);
  p.setRenderHint(QPainter::SmoothPixmapTransform);

  // Don't draw the base item if it's not requested
  if (!ui->renderSourceRadio->isChecked())
    m_baseItem->setVisible(false);

  m_scene->render(&p, target.rect(), sourceRect);

  QRect filled = filledRect(target, 5);

  // Clear source region if needed
  if (ui->transparentSourceRadio->isChecked())
  {
    p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
    p.setBrush(QBrush(Qt::white));
    p.setPen(Qt::NoPen);
    p.drawRoundedRect(m_baseItem->boundingRect().translated(-sourceRect.topLeft()), m_radius * m_scale, m_radius * m_scale);
  }

  m_baseItem->setVisible(true);
  p.end();

  // Determine the image rectangle filled by shadow and crop borders
  target = target.copy(filled);

  QLabel* l = new QLabel;
  l->setAttribute(Qt::WA_DeleteOnClose);
  l->setStyleSheet(ui->graphicsView->styleSheet());
  l->setPixmap(QPixmap::fromImage(target));
  l->show();

  // Save file
  bool saveResult = target.save(fileName);
  if (!saveResult)
  {
    QMessageBox::critical(this, tr("Error saving file"), tr("Could not save file %1").arg(fileName));
    return;
  }

  // Generate QML
  if (ui->generateQmlCheckBox->isChecked())
  {
    QRectF baseItemRect = m_baseItem->boundingRect().translated(-sourceRect.topLeft()).translated(-filled.topLeft());

    QFileInfo fileInfo(fileName);
    QFile qmlFile(fileInfo.absolutePath() + "/" + fileInfo.completeBaseName() + ".qml");
    if (!qmlFile.open(QIODevice::WriteOnly | QIODevice::Text))
    {
      QMessageBox::critical(this, tr("Error saving file"), tr("Could not save file %1").arg(qmlFile.fileName()));
      return;
    }

    QTextStream stream(&qmlFile);

    stream << "import QtQuick 2.0" << endl;
    stream << endl;
    stream << "Item {" << endl;

    stream << "  BorderImage {" << endl;
    stream << "    source: \"" << fileInfo.fileName() << "\"" << endl;
    stream << endl;
    stream << "    anchors {" << endl;
    stream << "      fill: parent" << endl;
    stream << "      leftMargin: -border.left; topMargin: -border.top" << endl;
    stream << "      rightMargin: -border.right; bottomMargin: -border.bottom" << endl;
    stream << "    }" << endl;
    stream << endl;
    stream << "    border.left: " << baseItemRect.left() << "; border.top: " << baseItemRect.top() << endl;
    stream << "    border.right: " << target.width() - baseItemRect.right()
           <<   "; border.bottom: " << target.height() - baseItemRect.bottom() << endl;
    stream << "  }" << endl;

    stream << "}" << endl;

    qmlFile.close();
  }
}

void MainWindow::updateSource()
{
  m_baseItem->setRect(0, 0, m_width * m_scale, m_height * m_scale);
  m_baseItem->setRadiusX(m_radius * m_scale);
  m_baseItem->setRadiusY(m_radius * m_scale);

  ui->graphicsView->centerOn(m_baseItem);
}

void MainWindow::addShadow(int xOffset, int yOffset, int opacity, double blur)
{
  QBoxLayout* shadowLayout = static_cast<QBoxLayout*>(ui->shadowsBox->layout());

  ShadowSettings* settings = new ShadowSettings(m_scene);
  settings->setSourceOptions(m_width, m_height, m_radius);
  settings->setScale(m_scale);

  connect(this, SIGNAL(sourceOptionsChanged(int,int,int)), settings, SLOT(setSourceOptions(int,int,int)));
  connect(this, SIGNAL(scaleChanged(qreal)), settings, SLOT(setScale(qreal)));
  connect(settings, &QObject::destroyed, [this](QObject* obj) {
            this->m_shadows.removeOne(static_cast<ShadowSettings*>(obj));
          });

  settings->setXOffset(xOffset);
  settings->setYOffset(yOffset);
  settings->setOpacity(opacity);
  settings->setBlur(blur);

  shadowLayout->insertWidget(shadowLayout->count() - 1, settings);

  m_shadows.append(settings);
  ui->graphicsView->centerOn(m_baseItem);
}

void MainWindow::userSourceChanged()
{
  m_width = ui->widthBox->value();
  m_height = ui->heightBox->value();
  m_radius = ui->radiusBox->value();

  ui->radiusBox->setMaximum(qMin(m_width, m_height) / 2);

  emit sourceOptionsChanged(m_width, m_height, m_radius);
}

void MainWindow::userScaleChanged(int value)
{
  // Calculate and display scale value
  m_scale = qreal(value) * 0.25;
  ui->scaleValueLabel->setText(tr("%1%").arg(m_scale * 100));

  emit scaleChanged(m_scale);
}

void MainWindow::loadShadowPreset()
{
  QAction* a = qobject_cast<QAction*>(sender());
  if (!a)
  {
    qWarning("Unknown action source");
    return;
  }

  QVariantList o = a->data().toList();
  if (o.size() % 4)
  {
    qWarning() << "Incorrect preset data for preset" << a->text();
    return;
  }

  qDeleteAll(m_shadows);
  m_shadows.clear();

  for (int i = 0; i < o.size() / 4; ++i)
    addShadow(o.at(i * 4).toInt(), o.at(i * 4 + 1).toInt(), o.at(i * 4 + 2).toInt(), o.at(i * 4 + 3).toDouble());
}

QRect MainWindow::filledRect(const QImage& image, int threshold)
{
  QRect result = image.rect();

  // Left border
  while (result.left() < result.right())
  {
    bool hasFilledPixel = false;
    for (int y = result.top(); y <= result.bottom(); y++)
    {
      if (qAlpha(image.pixel(result.left(), y)) > threshold)
      {
        hasFilledPixel = true;
        break;
      }
    }

    if (hasFilledPixel)
      break;

    result.adjust(1, 0, 0, 0);
  }

  // Right border
  while (result.right() > result.left())
  {
    bool hasFilledPixel = false;
    for (int y = result.top(); y <= result.bottom(); y++)
    {
      if (qAlpha(image.pixel(result.right(), y)) > threshold)
      {
        hasFilledPixel = true;
        break;
      }
    }

    if (hasFilledPixel)
      break;

    result.adjust(0, 0, -1, 0);
  }

  // Top border
  while (result.top() < result.bottom())
  {
    bool hasFilledPixel = false;
    for (int x = result.left(); x <= result.right(); x++)
    {
      if (qAlpha(image.pixel(x, result.top())) > threshold)
      {
        hasFilledPixel = true;
        break;
      }
    }

    if (hasFilledPixel)
      break;

    result.adjust(0, 1, 0, 0);
  }

  // Top border
  while (result.bottom() > result.top())
  {
    bool hasFilledPixel = false;
    for (int x = result.left(); x <= result.right(); x++)
    {
      if (qAlpha(image.pixel(x, result.bottom())) > threshold)
      {
        hasFilledPixel = true;
        break;
      }
    }

    if (hasFilledPixel)
      break;

    result.adjust(0, 0, 0, -1);
  }

  return result;
}

void MainWindow::updatePresets()
{
  if (!ui->loadPresetButton->menu())
    ui->loadPresetButton->setMenu(new QMenu);

  QMenu* menu = ui->loadPresetButton->menu();
  menu->clear();

  // Default presets
  QVariantList presets;
  if (!m_settings->contains("ShadowPresets"))
  {
    QVariantMap d1;
    d1[QStringLiteral("name")] = tr("Material design Z=1");
    d1[QStringLiteral("options")] = QVariantList() << 0 << 1 << 12 << 1.5
                                                   << 0 << 1 << 24 << 1.;

    QVariantMap d2;
    d2[QStringLiteral("name")] = tr("Material design Z=2");
    d2[QStringLiteral("options")] = QVariantList() << 0 << 3 << 16 << 3.
                                                   << 0 << 3 << 23 << 3.;

    QVariantMap d3;
    d3[QStringLiteral("name")] = tr("Material design Z=3");
    d3[QStringLiteral("options")] = QVariantList() << 0 << 10 << 19 << 10.
                                                   << 0 << 6  << 23 << 3.;

    QVariantMap d4;
    d4[QStringLiteral("name")] = tr("Material design Z=4");
    d4[QStringLiteral("options")] = QVariantList() << 0 << 14 << 25 << 14.
                                                   << 0 << 10 << 22 << 5.;

    QVariantMap d5;
    d5[QStringLiteral("name")] = tr("Material design Z=5");
    d5[QStringLiteral("options")] = QVariantList() << 0 << 19 << 30 << 19.
                                                   << 0 << 15 << 22 << 6.;

    presets << d1 << d2 << d3 << d4 << d5;
    m_settings->setValue(QStringLiteral("ShadowPresets"), presets);
  }
  else
  {
    presets = m_settings->value(QStringLiteral("ShadowPresets")).toList();
  }

  // Fill in the menu
  for (auto p : presets)
  {
    if (!p.isValid())
    {
      qWarning() << "Failed to load preset";
      continue;
    }

    QVariantMap preset = p.toMap();
    auto action = menu->addAction(preset[QStringLiteral("name")].toString(), this, SLOT(loadShadowPreset()));
    action->setData(preset[QStringLiteral("options")]);
  }
}

void MainWindow::on_addPresetButton_clicked()
{
  QString name = QInputDialog::getText(this, tr("Choose preset name"), tr("Preset name:"));
  if (!name.isEmpty())
  {
    QVariantMap preset;
    preset[QStringLiteral("name")] = name;
    QVariantList options;
    for (auto s : m_shadows)
      options << s->xOffset() << s->yOffset() << s->opacity() << s->blur();

    preset[QStringLiteral("options")] = options;

    auto presets = m_settings->value(QStringLiteral("ShadowPresets")).toList();
    presets.append(preset);
    m_settings->setValue(QStringLiteral("ShadowPresets"), presets);
    updatePresets();
  }
}
<commit_msg>Removed shadow border optimization causing artifacts<commit_after>// Local
#include "MainWindow.h"
#include "ui_MainWindow.h"

#include "ShadowSettings.h"

#include "GraphicsRoundedRectItem.h"

// Qt
#include <QGraphicsRectItem>
#include <QFileDialog>
#include <QMessageBox>
#include <QSettings>
#include <QMenu>
#include <QInputDialog>
#include <QDebug>

MainWindow::MainWindow(QWidget* parent)
  : QMainWindow(parent)
  , ui(new Ui::MainWindow)
  , m_settings(new QSettings)
  , m_width(40)
  , m_height(40)
  , m_radius(0)
  , m_scale(1)
{
  ui->setupUi(this);

  m_scene = new QGraphicsScene(this);

  m_baseItem = new GraphicsRoundedRectItem();
  m_baseItem->setBrush(QBrush(Qt::white));
  m_baseItem->setPen(QPen(Qt::NoBrush, 0, Qt::NoPen));
  m_baseItem->setZValue(1000);

  m_scene->addItem(m_baseItem);
  ui->graphicsView->setScene(m_scene);
  addShadow();

  connect(ui->scaleSlider, SIGNAL(valueChanged(int)), SLOT(userScaleChanged(int)));

  connect(ui->widthBox, SIGNAL(valueChanged(int)), SLOT(userSourceChanged()));
  connect(ui->heightBox, SIGNAL(valueChanged(int)), SLOT(userSourceChanged()));
  connect(ui->radiusBox, SIGNAL(valueChanged(int)), SLOT(userSourceChanged()));

  connect(ui->addShadowButton, SIGNAL(clicked()), SLOT(addShadow()));

  connect(this, SIGNAL(sourceOptionsChanged(int,int,int)), SLOT(updateSource()));
  connect(this, SIGNAL(scaleChanged(qreal)), SLOT(updateSource()));

  // Hack: position view to the center of layout
  //
  // This is the only way I've found to ensure the item will be placed in the center of view: we simply make the view
  // rectangle definitely larger than the view itself, turn off the scroll bars display (in the UI file) and forcing
  // positioning on the center of the base item. If the scene rect is smaller than the view itself, QGraphicsView
  // control simply ignores QGraphicsView::centerOn calls
  ui->graphicsView->setSceneRect(-1000, -1000, 2000, 2000);

  updateSource();
  updatePresets();
}

MainWindow::~MainWindow()
{
  delete ui;
}

void MainWindow::on_saveButton_clicked()
{
  // File name
  QString fileName = QFileDialog::getSaveFileName(this, tr("Save rendered image as..."), QString(),
                                                  "PNG image (*.png)");
  if (fileName.isEmpty())
    return;
  if (!fileName.endsWith(".png", Qt::CaseInsensitive))
    fileName.append(".png");

  // Source scene rect to render
  // We must use the aligned rectangle to not mess with the non-integer items coordinates
  QRectF sourceRect = QRectF(m_scene->itemsBoundingRect().toAlignedRect());

  QImage target(sourceRect.width(), sourceRect.height(), QImage::Format_ARGB32_Premultiplied);
  target.fill(Qt::transparent);

  QPainter p(&target);
  p.setRenderHint(QPainter::Antialiasing);
  p.setRenderHint(QPainter::SmoothPixmapTransform);

  // Don't draw the base item if it's not requested
  if (!ui->renderSourceRadio->isChecked())
    m_baseItem->setVisible(false);

  m_scene->render(&p, target.rect(), sourceRect);

  QRect filled = filledRect(target);

  // Clear source region if needed
  if (ui->transparentSourceRadio->isChecked())
  {
    p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
    p.setBrush(QBrush(Qt::white));
    p.setPen(Qt::NoPen);
    p.drawRoundedRect(m_baseItem->boundingRect().translated(-sourceRect.topLeft()), m_radius * m_scale, m_radius * m_scale);
  }

  m_baseItem->setVisible(true);
  p.end();

  // Determine the image rectangle filled by shadow and crop borders
  target = target.copy(filled);

  QLabel* l = new QLabel;
  l->setAttribute(Qt::WA_DeleteOnClose);
  l->setStyleSheet(ui->graphicsView->styleSheet());
  l->setPixmap(QPixmap::fromImage(target));
  l->show();

  // Save file
  bool saveResult = target.save(fileName);
  if (!saveResult)
  {
    QMessageBox::critical(this, tr("Error saving file"), tr("Could not save file %1").arg(fileName));
    return;
  }

  // Generate QML
  if (ui->generateQmlCheckBox->isChecked())
  {
    QRectF baseItemRect = m_baseItem->boundingRect().translated(-sourceRect.topLeft()).translated(-filled.topLeft());

    QFileInfo fileInfo(fileName);
    QFile qmlFile(fileInfo.absolutePath() + "/" + fileInfo.completeBaseName() + ".qml");
    if (!qmlFile.open(QIODevice::WriteOnly | QIODevice::Text))
    {
      QMessageBox::critical(this, tr("Error saving file"), tr("Could not save file %1").arg(qmlFile.fileName()));
      return;
    }

    QTextStream stream(&qmlFile);

    stream << "import QtQuick 2.0" << endl;
    stream << endl;
    stream << "Item {" << endl;

    stream << "  BorderImage {" << endl;
    stream << "    source: \"" << fileInfo.fileName() << "\"" << endl;
    stream << endl;
    stream << "    anchors {" << endl;
    stream << "      fill: parent" << endl;
    stream << "      leftMargin: -border.left; topMargin: -border.top" << endl;
    stream << "      rightMargin: -border.right; bottomMargin: -border.bottom" << endl;
    stream << "    }" << endl;
    stream << endl;
    stream << "    border.left: " << baseItemRect.left() << "; border.top: " << baseItemRect.top() << endl;
    stream << "    border.right: " << target.width() - baseItemRect.right()
           <<   "; border.bottom: " << target.height() - baseItemRect.bottom() << endl;
    stream << "  }" << endl;

    stream << "}" << endl;

    qmlFile.close();
  }
}

void MainWindow::updateSource()
{
  m_baseItem->setRect(0, 0, m_width * m_scale, m_height * m_scale);
  m_baseItem->setRadiusX(m_radius * m_scale);
  m_baseItem->setRadiusY(m_radius * m_scale);

  ui->graphicsView->centerOn(m_baseItem);
}

void MainWindow::addShadow(int xOffset, int yOffset, int opacity, double blur)
{
  QBoxLayout* shadowLayout = static_cast<QBoxLayout*>(ui->shadowsBox->layout());

  ShadowSettings* settings = new ShadowSettings(m_scene);
  settings->setSourceOptions(m_width, m_height, m_radius);
  settings->setScale(m_scale);

  connect(this, SIGNAL(sourceOptionsChanged(int,int,int)), settings, SLOT(setSourceOptions(int,int,int)));
  connect(this, SIGNAL(scaleChanged(qreal)), settings, SLOT(setScale(qreal)));
  connect(settings, &QObject::destroyed, [this](QObject* obj) {
            this->m_shadows.removeOne(static_cast<ShadowSettings*>(obj));
          });

  settings->setXOffset(xOffset);
  settings->setYOffset(yOffset);
  settings->setOpacity(opacity);
  settings->setBlur(blur);

  shadowLayout->insertWidget(shadowLayout->count() - 1, settings);

  m_shadows.append(settings);
  ui->graphicsView->centerOn(m_baseItem);
}

void MainWindow::userSourceChanged()
{
  m_width = ui->widthBox->value();
  m_height = ui->heightBox->value();
  m_radius = ui->radiusBox->value();

  ui->radiusBox->setMaximum(qMin(m_width, m_height) / 2);

  emit sourceOptionsChanged(m_width, m_height, m_radius);
}

void MainWindow::userScaleChanged(int value)
{
  // Calculate and display scale value
  m_scale = qreal(value) * 0.25;
  ui->scaleValueLabel->setText(tr("%1%").arg(m_scale * 100));

  emit scaleChanged(m_scale);
}

void MainWindow::loadShadowPreset()
{
  QAction* a = qobject_cast<QAction*>(sender());
  if (!a)
  {
    qWarning("Unknown action source");
    return;
  }

  QVariantList o = a->data().toList();
  if (o.size() % 4)
  {
    qWarning() << "Incorrect preset data for preset" << a->text();
    return;
  }

  qDeleteAll(m_shadows);
  m_shadows.clear();

  for (int i = 0; i < o.size() / 4; ++i)
    addShadow(o.at(i * 4).toInt(), o.at(i * 4 + 1).toInt(), o.at(i * 4 + 2).toInt(), o.at(i * 4 + 3).toDouble());
}

QRect MainWindow::filledRect(const QImage& image, int threshold)
{
  QRect result = image.rect();

  // Left border
  while (result.left() < result.right())
  {
    bool hasFilledPixel = false;
    for (int y = result.top(); y <= result.bottom(); y++)
    {
      if (qAlpha(image.pixel(result.left(), y)) > threshold)
      {
        hasFilledPixel = true;
        break;
      }
    }

    if (hasFilledPixel)
      break;

    result.adjust(1, 0, 0, 0);
  }

  // Right border
  while (result.right() > result.left())
  {
    bool hasFilledPixel = false;
    for (int y = result.top(); y <= result.bottom(); y++)
    {
      if (qAlpha(image.pixel(result.right(), y)) > threshold)
      {
        hasFilledPixel = true;
        break;
      }
    }

    if (hasFilledPixel)
      break;

    result.adjust(0, 0, -1, 0);
  }

  // Top border
  while (result.top() < result.bottom())
  {
    bool hasFilledPixel = false;
    for (int x = result.left(); x <= result.right(); x++)
    {
      if (qAlpha(image.pixel(x, result.top())) > threshold)
      {
        hasFilledPixel = true;
        break;
      }
    }

    if (hasFilledPixel)
      break;

    result.adjust(0, 1, 0, 0);
  }

  // Top border
  while (result.bottom() > result.top())
  {
    bool hasFilledPixel = false;
    for (int x = result.left(); x <= result.right(); x++)
    {
      if (qAlpha(image.pixel(x, result.bottom())) > threshold)
      {
        hasFilledPixel = true;
        break;
      }
    }

    if (hasFilledPixel)
      break;

    result.adjust(0, 0, 0, -1);
  }

  return result;
}

void MainWindow::updatePresets()
{
  if (!ui->loadPresetButton->menu())
    ui->loadPresetButton->setMenu(new QMenu);

  QMenu* menu = ui->loadPresetButton->menu();
  menu->clear();

  // Default presets
  QVariantList presets;
  if (!m_settings->contains("ShadowPresets"))
  {
    QVariantMap d1;
    d1[QStringLiteral("name")] = tr("Material design Z=1");
    d1[QStringLiteral("options")] = QVariantList() << 0 << 1 << 12 << 1.5
                                                   << 0 << 1 << 24 << 1.;

    QVariantMap d2;
    d2[QStringLiteral("name")] = tr("Material design Z=2");
    d2[QStringLiteral("options")] = QVariantList() << 0 << 3 << 16 << 3.
                                                   << 0 << 3 << 23 << 3.;

    QVariantMap d3;
    d3[QStringLiteral("name")] = tr("Material design Z=3");
    d3[QStringLiteral("options")] = QVariantList() << 0 << 10 << 19 << 10.
                                                   << 0 << 6  << 23 << 3.;

    QVariantMap d4;
    d4[QStringLiteral("name")] = tr("Material design Z=4");
    d4[QStringLiteral("options")] = QVariantList() << 0 << 14 << 25 << 14.
                                                   << 0 << 10 << 22 << 5.;

    QVariantMap d5;
    d5[QStringLiteral("name")] = tr("Material design Z=5");
    d5[QStringLiteral("options")] = QVariantList() << 0 << 19 << 30 << 19.
                                                   << 0 << 15 << 22 << 6.;

    presets << d1 << d2 << d3 << d4 << d5;
    m_settings->setValue(QStringLiteral("ShadowPresets"), presets);
  }
  else
  {
    presets = m_settings->value(QStringLiteral("ShadowPresets")).toList();
  }

  // Fill in the menu
  for (auto p : presets)
  {
    if (!p.isValid())
    {
      qWarning() << "Failed to load preset";
      continue;
    }

    QVariantMap preset = p.toMap();
    auto action = menu->addAction(preset[QStringLiteral("name")].toString(), this, SLOT(loadShadowPreset()));
    action->setData(preset[QStringLiteral("options")]);
  }
}

void MainWindow::on_addPresetButton_clicked()
{
  QString name = QInputDialog::getText(this, tr("Choose preset name"), tr("Preset name:"));
  if (!name.isEmpty())
  {
    QVariantMap preset;
    preset[QStringLiteral("name")] = name;
    QVariantList options;
    for (auto s : m_shadows)
      options << s->xOffset() << s->yOffset() << s->opacity() << s->blur();

    preset[QStringLiteral("options")] = options;

    auto presets = m_settings->value(QStringLiteral("ShadowPresets")).toList();
    presets.append(preset);
    m_settings->setValue(QStringLiteral("ShadowPresets"), presets);
    updatePresets();
  }
}
<|endoftext|>