<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/*
$Log$
Revision 1.3  2000/06/30 12:08:36  morsch
In member data: char* replaced by TString, Init takes care of resizing the strings to
8 characters required by Hijing.

Revision 1.2  2000/06/15 14:15:05  morsch
Add possibility for heavy flavor selection: charm and beauty.

Revision 1.1  2000/06/09 20:47:27  morsch
AliGenerator interface class to HIJING using THijing (test version)

*/

#include "AliGenHijing.h"
#include "AliGenHijingEventHeader.h"
#include "AliRun.h"

#include <TArrayI.h>
#include <TParticle.h>
#include <THijing.h>

 ClassImp(AliGenHijing)

AliGenHijing::AliGenHijing()
                 :AliGenerator()
{
// Constructor
}

AliGenHijing::AliGenHijing(Int_t npart)
                 :AliGenerator(npart)
{
// Default PbPb collisions at 5. 5 TeV
//
    SetEnergyCMS();
    SetImpactParameterRange();
    SetTarget();
    SetProjectile();
    fKeep=0;
    fQuench=1;
    fShadowing=1;
    fTrigger=0;
    fDecaysOff=1;
    fEvaluate=0;
    fSelectAll=0;
    fFlavor=0;
}

AliGenHijing::AliGenHijing(const AliGenHijing & Hijing)
{
// copy constructor
}

AliGenHijing::~AliGenHijing()
{
// Destructor
}

void AliGenHijing::Init()
{
// Initialisation
    fFrame.Resize(8);
    fTarget.Resize(8);
    fProjectile.Resize(8);

    SetMC(new THijing(fEnergyCMS, fFrame, fProjectile, fTarget,
		      fAProjectile, fZProjectile, fATarget, fZTarget,
		      fMinImpactParam, fMaxImpactParam));

    fHijing=(THijing*) fgMCEvGen;
    fHijing->Initialize();
    fHijing->SetIHPR2(3,  fTrigger);
    fHijing->SetIHPR2(4,  fQuench);
    fHijing->SetIHPR2(6,  fShadowing);
    fHijing->SetIHPR2(12, fDecaysOff);
    fHijing->SetIHPR2(21, fKeep);
//
    if (fEvaluate) EvaluateCrossSections();
}

void AliGenHijing::Generate()
{
// Generate one event

    Float_t polar[3] =   {0,0,0};
    Float_t origin[3]=   {0,0,0};
    Float_t origin0[3]=  {0,0,0};
    Float_t p[3], random[6];
    Float_t tof;

    static TClonesArray *particles;
//  converts from mm/c to s
    const Float_t kconv=0.001/2.999792458e8;
//
    Int_t nt=0;
    Int_t jev=0;
    Int_t j, kf, ks, imo;
    kf=0;

    if(!particles) particles=new TClonesArray("TParticle",10000);

    fTrials=0;
    for (j=0;j<3;j++) origin0[j]=fOrigin[j];
    if(fVertexSmear==kPerEvent) {
	gMC->Rndm(random,6);
	for (j=0;j<3;j++) {
	    origin0[j]+=fOsigma[j]*TMath::Cos(2*random[2*j]*TMath::Pi())*
		TMath::Sqrt(-2*TMath::Log(random[2*j+1]));
//	    fHijing->SetMSTP(151,0);
	}
    } else if (fVertexSmear==kPerTrack) {
//	fHijing->SetMSTP(151,0);
	for (j=0;j<3;j++) {
//	    fHijing->SetPARP(151+j, fOsigma[j]*10.);
	}
    }
    while(1)
    {

	fHijing->GenerateEvent();
	fTrials++;
	fHijing->ImportParticles(particles,"All");
	Int_t np = particles->GetEntriesFast();
	printf("\n **************************************************%d\n",np);
	Int_t nc=0;
	if (np == 0 ) continue;
	Int_t i;
	Int_t * newPos = new Int_t[np];
	for (i = 0; i<np; i++) *(newPos+i)=i;

	for (i = 0; i<np; i++) {
	    TParticle *  iparticle       = (TParticle *) particles->At(i);

	    Bool_t  hasMother            =  (iparticle->GetFirstMother()   >=0);
	    Bool_t  hasDaughter          =  (iparticle->GetFirstDaughter() >=0);
	    Bool_t  selected             =  kTRUE;
	    Bool_t  hasSelectedDaughters =  kFALSE;

	    kf        = iparticle->GetPdgCode();
	    if (!fSelectAll) selected = KinematicSelection(iparticle)&&SelectFlavor(kf);
	    if (hasDaughter && !selected) hasSelectedDaughters = DaughtersSelection(iparticle, particles);
//
// Put particle on the stack if it is either selected or it is the mother of at least one seleted particle
//

	    if (selected || hasSelectedDaughters) {
		nc++;
		ks        = iparticle->GetStatusCode();
		p[0]=iparticle->Px();
		p[1]=iparticle->Py();
		p[2]=iparticle->Pz();
		origin[0]=origin0[0]+iparticle->Vx()/10;
		origin[1]=origin0[1]+iparticle->Vy()/10;
		origin[2]=origin0[2]+iparticle->Vz()/10;
		tof=kconv*iparticle->T();
		imo=-1;
		if (hasMother) {
		    imo=iparticle->GetFirstMother();
		    imo=*(newPos+imo);
		}

//		printf("\n selected iparent %d %d %d \n",i, kf, imo);
		if (hasDaughter) {
		    gAlice->SetTrack(0,imo,kf,p,origin,polar,
				     tof,"Primary",nt);
		} else {
		    gAlice->SetTrack(fTrackIt,imo,kf,p,origin,polar,
				     tof,"Secondary",nt);
		}
		*(newPos+i)=nt;
	    } // selected
	} // particle loop
	delete newPos;
	printf("\n I've put %i particles on the stack \n",nc);
	if (nc > 0) {
	    jev+=nc;
	    if (jev >= fNpart || fNpart == -1) {
		fKineBias=Float_t(fNpart)/Float_t(fTrials);
		printf("\n Trials: %i %i %i\n",fTrials, fNpart, jev);
		break;
	    }
	}
    } // event loop
}

Bool_t AliGenHijing::KinematicSelection(TParticle *particle)
{
// Perform kinematic selection
    Float_t px=particle->Px();
    Float_t py=particle->Py();
    Float_t pz=particle->Pz();
    Float_t  e=particle->Energy();

//
//  transverse momentum cut
    Float_t pt=TMath::Sqrt(px*px+py*py);
    if (pt > fPtMax || pt < fPtMin)
    {
//	printf("\n failed pt cut %f %f %f \n",pt,fPtMin,fPtMax);
	return kFALSE;
    }
//
// momentum cut
    Float_t p=TMath::Sqrt(px*px+py*py+pz*pz);
    if (p > fPMax || p < fPMin)
    {
//	printf("\n failed p cut %f %f %f \n",p,fPMin,fPMax);
	return kFALSE;
    }

//
// theta cut
    Float_t  theta = Float_t(TMath::ATan2(Double_t(pt),Double_t(pz)));
    if (theta > fThetaMax || theta < fThetaMin)
    {

//    	printf("\n failed theta cut %f %f %f \n",theta,fThetaMin,fThetaMax);
	return kFALSE;
    }

//
// rapidity cut
    Float_t y = 0.5*TMath::Log((e+pz)/(e-pz));
    if (y > fYMax || y < fYMin)
    {
//	printf("\n failed y cut %f %f %f \n",y,fYMin,fYMax);
	return kFALSE;
    }

//
// phi cut
    Float_t phi=Float_t(TMath::ATan2(Double_t(py),Double_t(px)));
    if (phi > fPhiMax || phi < fPhiMin)
    {
//	printf("\n failed phi cut %f %f %f \n",phi,fPhiMin,fPhiMax);
	return kFALSE;
    }

    return kTRUE;
}

void AliGenHijing::KeepFullEvent()
{
    fKeep=1;
}

void AliGenHijing::EvaluateCrossSections()
{
//     Glauber Calculation of geometrical x-section
//
    Float_t xTot=0.;          // barn
    Float_t xTotHard=0.;      // barn
    Float_t xPart=0.;         // barn
    Float_t xPartHard=0.;     // barn
    Float_t sigmaHard=0.1;    // mbarn
    Float_t bMin=0.;
    Float_t bMax=fHijing->GetHIPR1(34)+fHijing->GetHIPR1(35);
    const Float_t kdib=0.2;
    Int_t   kMax=Int_t((bMax-bMin)/kdib)+1;

    printf("\n Projectile Radius (fm): %f \n",fHijing->GetHIPR1(34));
    printf("\n Target     Radius (fm): %f \n",fHijing->GetHIPR1(35));
    Int_t i;
    Float_t oldvalue=0.;

    for (i=0; i<kMax; i++)
    {
	Float_t xb=bMin+i*kdib;
	Float_t ov;
	ov=fHijing->Profile(xb);
	Float_t gb =  2.*0.01*fHijing->GetHIPR1(40)*kdib*xb*(1.-TMath::Exp(-fHijing->GetHINT1(12)*ov));
	Float_t gbh = 2.*0.01*fHijing->GetHIPR1(40)*kdib*xb*sigmaHard*ov;
	xTot+=gb;
	xTotHard+=gbh;
	if (xb > fMinImpactParam && xb < fMaxImpactParam)
	{
	    xPart+=gb;
	    xPartHard+=gbh;
	}

	if ((xTot-oldvalue)/oldvalue<0.0001) break;
	oldvalue=xTot;
	printf("\n Total cross section (barn): %d %f %f \n",i, xb, xTot);
	printf("\n Hard  cross section (barn): %d %f %f \n\n",i, xb, xTotHard);
    }
    printf("\n Total cross section (barn): %f \n",xTot);
    printf("\n Hard  cross section (barn): %f \n \n",xTotHard);
    printf("\n Partial       cross section (barn): %f %f \n",xPart, xPart/xTot*100.);
    printf("\n Partial  hard cross section (barn): %f %f \n",xPartHard, xPartHard/xTotHard*100.);
}

Bool_t AliGenHijing::DaughtersSelection(TParticle* iparticle, TClonesArray* particles)
{
//
// Looks recursively if one of the daughters has been selected
//
//    printf("\n Consider daughters %d:",iparticle->GetPdgCode());
    Int_t imin=-1;
    Int_t imax=-1;
    Int_t i;
    Bool_t hasDaughters= (iparticle->GetFirstDaughter() >=0);
    Bool_t selected=kFALSE;
    if (hasDaughters) {
	imin=iparticle->GetFirstDaughter();
	imax=iparticle->GetLastDaughter();
	for (i=imin; i<= imax; i++){
	    TParticle *  jparticle       = (TParticle *) particles->At(i);
	    Int_t ip=jparticle->GetPdgCode();
	    if (KinematicSelection(jparticle)&&SelectFlavor(ip)) {selected=kTRUE; break;}
	    if (DaughtersSelection(jparticle, particles)) {selected=kTRUE; break; }
	}
    } else {
	return kFALSE;
    }

    return selected;
}

Bool_t AliGenHijing::SelectFlavor(Int_t pid)
{
// Select flavor of particle
// 0: all
// 4: charm and beauty
// 5: beauty
    if (fFlavor == 0) return kTRUE;

    Int_t ifl=TMath::Abs(pid/100);
    if (ifl > 10) ifl/=10;
    return ((fFlavor==4 && (ifl==4 || ifl==5))  ||
	    (fFlavor==5 &&  ifl==5));

}

void AliGenHijing::MakeHeader()
{
// Builds the event header, to be called after each event
    AliGenHijingEventHeader* header = new AliGenHijingEventHeader("Hijing");
//    header->SetDate(date);
//    header->SetRunNumber(run);
//    header->SetEventNumber(event);
    header->SetNProduced(fHijing->GetNATT());
    header->SetImpactParameter(fHijing->GetHINT1(19));
    header->SetTotalEnergy(fHijing->GetEATT());
    header->SetHardScatters(fHijing->GetJATT());
    header->SetParticipants(fHijing->GetNP(), fHijing->GetNT());
    header->SetCollisions(fHijing->GetN0(),
			  fHijing->GetN01(),
			  fHijing->GetN10(),
			  fHijing->GetN11());
}

AliGenHijing& AliGenHijing::operator=(const  AliGenHijing& rhs)
{
// Assignment operator
    return *this;
}
<commit_msg>fHijing->Initialize(); after change of parameters. (Dmitri Yurevitch Peressounko)<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/*
$Log$
Revision 1.4  2000/07/11 18:24:56  fca
Coding convention corrections + few minor bug fixes

Revision 1.3  2000/06/30 12:08:36  morsch
In member data: char* replaced by TString, Init takes care of resizing the strings to
8 characters required by Hijing.

Revision 1.2  2000/06/15 14:15:05  morsch
Add possibility for heavy flavor selection: charm and beauty.

Revision 1.1  2000/06/09 20:47:27  morsch
AliGenerator interface class to HIJING using THijing (test version)

*/

#include "AliGenHijing.h"
#include "AliGenHijingEventHeader.h"
#include "AliRun.h"

#include <TArrayI.h>
#include <TParticle.h>
#include <THijing.h>

 ClassImp(AliGenHijing)

AliGenHijing::AliGenHijing()
                 :AliGenerator()
{
// Constructor
}

AliGenHijing::AliGenHijing(Int_t npart)
                 :AliGenerator(npart)
{
// Default PbPb collisions at 5. 5 TeV
//
    SetEnergyCMS();
    SetImpactParameterRange();
    SetTarget();
    SetProjectile();
    fKeep=0;
    fQuench=1;
    fShadowing=1;
    fTrigger=0;
    fDecaysOff=1;
    fEvaluate=0;
    fSelectAll=0;
    fFlavor=0;
}

AliGenHijing::AliGenHijing(const AliGenHijing & Hijing)
{
// copy constructor
}

AliGenHijing::~AliGenHijing()
{
// Destructor
}

void AliGenHijing::Init()
{
// Initialisation
    fFrame.Resize(8);
    fTarget.Resize(8);
    fProjectile.Resize(8);

    SetMC(new THijing(fEnergyCMS, fFrame, fProjectile, fTarget,
		      fAProjectile, fZProjectile, fATarget, fZTarget,
		      fMinImpactParam, fMaxImpactParam));

    fHijing=(THijing*) fgMCEvGen;

    fHijing->SetIHPR2(3,  fTrigger);
    fHijing->SetIHPR2(4,  fQuench);
    fHijing->SetIHPR2(6,  fShadowing);
    fHijing->SetIHPR2(12, fDecaysOff);
    fHijing->SetIHPR2(21, fKeep);
    fHijing->Initialize();
//
    if (fEvaluate) EvaluateCrossSections();
}

void AliGenHijing::Generate()
{
// Generate one event

    Float_t polar[3] =   {0,0,0};
    Float_t origin[3]=   {0,0,0};
    Float_t origin0[3]=  {0,0,0};
    Float_t p[3], random[6];
    Float_t tof;

    static TClonesArray *particles;
//  converts from mm/c to s
    const Float_t kconv=0.001/2.999792458e8;
//
    Int_t nt=0;
    Int_t jev=0;
    Int_t j, kf, ks, imo;
    kf=0;

    if(!particles) particles=new TClonesArray("TParticle",10000);

    fTrials=0;
    for (j=0;j<3;j++) origin0[j]=fOrigin[j];
    if(fVertexSmear==kPerEvent) {
	gMC->Rndm(random,6);
	for (j=0;j<3;j++) {
	    origin0[j]+=fOsigma[j]*TMath::Cos(2*random[2*j]*TMath::Pi())*
		TMath::Sqrt(-2*TMath::Log(random[2*j+1]));
//	    fHijing->SetMSTP(151,0);
	}
    } else if (fVertexSmear==kPerTrack) {
//	fHijing->SetMSTP(151,0);
	for (j=0;j<3;j++) {
//	    fHijing->SetPARP(151+j, fOsigma[j]*10.);
	}
    }
    while(1)
    {

	fHijing->GenerateEvent();
	fTrials++;
	fHijing->ImportParticles(particles,"All");
	Int_t np = particles->GetEntriesFast();
	printf("\n **************************************************%d\n",np);
	Int_t nc=0;
	if (np == 0 ) continue;
	Int_t i;
	Int_t * newPos = new Int_t[np];
	for (i = 0; i<np; i++) *(newPos+i)=i;

	for (i = 0; i<np; i++) {
	    TParticle *  iparticle       = (TParticle *) particles->At(i);

	    Bool_t  hasMother            =  (iparticle->GetFirstMother()   >=0);
	    Bool_t  hasDaughter          =  (iparticle->GetFirstDaughter() >=0);
	    Bool_t  selected             =  kTRUE;
	    Bool_t  hasSelectedDaughters =  kFALSE;

	    kf        = iparticle->GetPdgCode();
	    if (!fSelectAll) selected = KinematicSelection(iparticle)&&SelectFlavor(kf);
	    if (hasDaughter && !selected) hasSelectedDaughters = DaughtersSelection(iparticle, particles);
//
// Put particle on the stack if it is either selected or it is the mother of at least one seleted particle
//

	    if (selected || hasSelectedDaughters) {
		nc++;
		ks        = iparticle->GetStatusCode();
		p[0]=iparticle->Px();
		p[1]=iparticle->Py();
		p[2]=iparticle->Pz();
		origin[0]=origin0[0]+iparticle->Vx()/10;
		origin[1]=origin0[1]+iparticle->Vy()/10;
		origin[2]=origin0[2]+iparticle->Vz()/10;
		tof=kconv*iparticle->T();
		imo=-1;
		if (hasMother) {
		    imo=iparticle->GetFirstMother();
		    imo=*(newPos+imo);
		}

//		printf("\n selected iparent %d %d %d \n",i, kf, imo);
		if (hasDaughter) {
		    gAlice->SetTrack(0,imo,kf,p,origin,polar,
				     tof,"Primary",nt);
		} else {
		    gAlice->SetTrack(fTrackIt,imo,kf,p,origin,polar,
				     tof,"Secondary",nt);
		}
		*(newPos+i)=nt;
	    } // selected
	} // particle loop
	delete newPos;
	printf("\n I've put %i particles on the stack \n",nc);
	if (nc > 0) {
	    jev+=nc;
	    if (jev >= fNpart || fNpart == -1) {
		fKineBias=Float_t(fNpart)/Float_t(fTrials);
		printf("\n Trials: %i %i %i\n",fTrials, fNpart, jev);
		break;
	    }
	}
    } // event loop
}

Bool_t AliGenHijing::KinematicSelection(TParticle *particle)
{
// Perform kinematic selection
    Float_t px=particle->Px();
    Float_t py=particle->Py();
    Float_t pz=particle->Pz();
    Float_t  e=particle->Energy();

//
//  transverse momentum cut
    Float_t pt=TMath::Sqrt(px*px+py*py);
    if (pt > fPtMax || pt < fPtMin)
    {
//	printf("\n failed pt cut %f %f %f \n",pt,fPtMin,fPtMax);
	return kFALSE;
    }
//
// momentum cut
    Float_t p=TMath::Sqrt(px*px+py*py+pz*pz);
    if (p > fPMax || p < fPMin)
    {
//	printf("\n failed p cut %f %f %f \n",p,fPMin,fPMax);
	return kFALSE;
    }

//
// theta cut
    Float_t  theta = Float_t(TMath::ATan2(Double_t(pt),Double_t(pz)));
    if (theta > fThetaMax || theta < fThetaMin)
    {

//    	printf("\n failed theta cut %f %f %f \n",theta,fThetaMin,fThetaMax);
	return kFALSE;
    }

//
// rapidity cut
    Float_t y = 0.5*TMath::Log((e+pz)/(e-pz));
    if (y > fYMax || y < fYMin)
    {
//	printf("\n failed y cut %f %f %f \n",y,fYMin,fYMax);
	return kFALSE;
    }

//
// phi cut
    Float_t phi=Float_t(TMath::ATan2(Double_t(py),Double_t(px)));
    if (phi > fPhiMax || phi < fPhiMin)
    {
//	printf("\n failed phi cut %f %f %f \n",phi,fPhiMin,fPhiMax);
	return kFALSE;
    }

    return kTRUE;
}

void AliGenHijing::KeepFullEvent()
{
    fKeep=1;
}

void AliGenHijing::EvaluateCrossSections()
{
//     Glauber Calculation of geometrical x-section
//
    Float_t xTot=0.;          // barn
    Float_t xTotHard=0.;      // barn
    Float_t xPart=0.;         // barn
    Float_t xPartHard=0.;     // barn
    Float_t sigmaHard=0.1;    // mbarn
    Float_t bMin=0.;
    Float_t bMax=fHijing->GetHIPR1(34)+fHijing->GetHIPR1(35);
    const Float_t kdib=0.2;
    Int_t   kMax=Int_t((bMax-bMin)/kdib)+1;

    printf("\n Projectile Radius (fm): %f \n",fHijing->GetHIPR1(34));
    printf("\n Target     Radius (fm): %f \n",fHijing->GetHIPR1(35));
    Int_t i;
    Float_t oldvalue=0.;

    for (i=0; i<kMax; i++)
    {
	Float_t xb=bMin+i*kdib;
	Float_t ov;
	ov=fHijing->Profile(xb);
	Float_t gb =  2.*0.01*fHijing->GetHIPR1(40)*kdib*xb*(1.-TMath::Exp(-fHijing->GetHINT1(12)*ov));
	Float_t gbh = 2.*0.01*fHijing->GetHIPR1(40)*kdib*xb*sigmaHard*ov;
	xTot+=gb;
	xTotHard+=gbh;
	if (xb > fMinImpactParam && xb < fMaxImpactParam)
	{
	    xPart+=gb;
	    xPartHard+=gbh;
	}

	if ((xTot-oldvalue)/oldvalue<0.0001) break;
	oldvalue=xTot;
	printf("\n Total cross section (barn): %d %f %f \n",i, xb, xTot);
	printf("\n Hard  cross section (barn): %d %f %f \n\n",i, xb, xTotHard);
    }
    printf("\n Total cross section (barn): %f \n",xTot);
    printf("\n Hard  cross section (barn): %f \n \n",xTotHard);
    printf("\n Partial       cross section (barn): %f %f \n",xPart, xPart/xTot*100.);
    printf("\n Partial  hard cross section (barn): %f %f \n",xPartHard, xPartHard/xTotHard*100.);
}

Bool_t AliGenHijing::DaughtersSelection(TParticle* iparticle, TClonesArray* particles)
{
//
// Looks recursively if one of the daughters has been selected
//
//    printf("\n Consider daughters %d:",iparticle->GetPdgCode());
    Int_t imin=-1;
    Int_t imax=-1;
    Int_t i;
    Bool_t hasDaughters= (iparticle->GetFirstDaughter() >=0);
    Bool_t selected=kFALSE;
    if (hasDaughters) {
	imin=iparticle->GetFirstDaughter();
	imax=iparticle->GetLastDaughter();
	for (i=imin; i<= imax; i++){
	    TParticle *  jparticle       = (TParticle *) particles->At(i);
	    Int_t ip=jparticle->GetPdgCode();
	    if (KinematicSelection(jparticle)&&SelectFlavor(ip)) {selected=kTRUE; break;}
	    if (DaughtersSelection(jparticle, particles)) {selected=kTRUE; break; }
	}
    } else {
	return kFALSE;
    }

    return selected;
}

Bool_t AliGenHijing::SelectFlavor(Int_t pid)
{
// Select flavor of particle
// 0: all
// 4: charm and beauty
// 5: beauty
    if (fFlavor == 0) return kTRUE;

    Int_t ifl=TMath::Abs(pid/100);
    if (ifl > 10) ifl/=10;
    return ((fFlavor==4 && (ifl==4 || ifl==5))  ||
	    (fFlavor==5 &&  ifl==5));

}

void AliGenHijing::MakeHeader()
{
// Builds the event header, to be called after each event
    AliGenHijingEventHeader* header = new AliGenHijingEventHeader("Hijing");
//    header->SetDate(date);
//    header->SetRunNumber(run);
//    header->SetEventNumber(event);
    header->SetNProduced(fHijing->GetNATT());
    header->SetImpactParameter(fHijing->GetHINT1(19));
    header->SetTotalEnergy(fHijing->GetEATT());
    header->SetHardScatters(fHijing->GetJATT());
    header->SetParticipants(fHijing->GetNP(), fHijing->GetNT());
    header->SetCollisions(fHijing->GetN0(),
			  fHijing->GetN01(),
			  fHijing->GetN10(),
			  fHijing->GetN11());
}

AliGenHijing& AliGenHijing::operator=(const  AliGenHijing& rhs)
{
// Assignment operator
    return *this;
}
<|endoftext|>


<commit_before><commit_msg>update editor weather presets<commit_after><|endoftext|>


<commit_before>#include "GLMMDModelDrawer.h"

#include "GLMMDModelDrawContext.h"

#include <Saba/Base/Log.h>
#include <Saba/GL/GLShaderUtil.h>
#include <Saba/GL/GLTextureUtil.h>

#include <imgui.h>

namespace saba
{
	GLMMDModelDrawer::GLMMDModelDrawer(GLMMDModelDrawContext * ctxt, std::shared_ptr<GLMMDModel> mmdModel)
		: m_drawContext(ctxt)
		, m_mmdModel(mmdModel)
		, m_playMode(PlayMode::None)
		, m_clipElapsed(true)
	{
		SABA_ASSERT(ctxt != nullptr);
		SABA_ASSERT(mmdModel != nullptr);
	}

	GLMMDModelDrawer::~GLMMDModelDrawer()
	{
		Destroy();
	}

	bool GLMMDModelDrawer::Create()
	{
		int matIdx = 0;
		for (const auto& mat : m_mmdModel->GetMaterials())
		{
			GLSLDefine define;

			MaterialShader matShader;
			matShader.m_objMaterialIndex = matIdx;
			matShader.m_objShaderIndex = m_drawContext->GetShaderIndex(define);
			if (matShader.m_objShaderIndex == -1)
			{
				SABA_ERROR("Obj Material Shader not found.");
				return false;
			}
			if (!matShader.m_vao.Create())
			{
				SABA_ERROR("Vertex Array Object Create fail.");
				return false;
			}

			auto shader = m_drawContext->GetShader(matShader.m_objShaderIndex);

			glBindVertexArray(matShader.m_vao);

			m_mmdModel->GetPositionBinder().Bind(shader->m_inPos, m_mmdModel->GetPositionVBO());
			glEnableVertexAttribArray(shader->m_inPos);

			m_mmdModel->GetNormalBinder().Bind(shader->m_inNor, m_mmdModel->GetNormalVBO());
			glEnableVertexAttribArray(shader->m_inNor);

			if (shader->m_inUV != -1)
			{
				m_mmdModel->GetUVBinder().Bind(shader->m_inUV, m_mmdModel->GetUVVBO());
				glEnableVertexAttribArray(shader->m_inUV);
			}

			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_mmdModel->GetIBO());

			glBindVertexArray(0);

			m_materialShaders.emplace_back(std::move(matShader));

			matIdx++;
		}
		m_playMode = PlayMode::Stop;
		return true;
	}

	void GLMMDModelDrawer::Destroy()
	{
		m_materialShaders.clear();
	}

	void GLMMDModelDrawer::DrawUI(ViewerContext * ctxt)
	{
		ImGui::Begin("MMDDrawCtrl");
		if (ImGui::CollapsingHeader("Animation"))
		{
			ImGui::Checkbox("Clip Elapsed", &m_clipElapsed);
			float animFrame = (float)(m_mmdModel->GetAnimationTime() * 30.0);
			if (ImGui::InputFloat("Frame", &animFrame))
			{
				m_mmdModel->SetAnimationTime(animFrame / 30.0);
				m_playMode = PlayMode::Update;
			}

			if (m_playMode == PlayMode::Play)
			{
				if (ImGui::Button("Stop"))
				{
					m_playMode = PlayMode::Stop;
				}
			}
			else
			{
				if (ImGui::Button("Play"))
				{
					m_playMode = PlayMode::Play;
				}
			}
			if (ImGui::Button("Step FF"))
			{
				m_playMode = PlayMode::StepFF;
			}
			if (ImGui::Button("Step FR"))
			{
				m_playMode = PlayMode::StepFR;
			}
		}
		if (ImGui::CollapsingHeader("Morph"))
		{
			auto model = m_mmdModel->GetMMDModel();
			auto morphMan = model->GetMorphManager();
			size_t morphCount = morphMan->GetMorphCount();
			for (size_t morphIdx = 0; morphIdx < morphCount; morphIdx++)
			{
				auto morph = morphMan->GetMorph(morphIdx);
				float weight = morph->GetWeight();
				if (ImGui::SliderFloat(morph->GetName().c_str(), &weight, 0.0f, 1.0f))
				{
					morph->SetWeight(weight);
					m_playMode = PlayMode::Update;
				}
			}
		}
		ImGui::End();
	}

	void GLMMDModelDrawer::Update(ViewerContext * ctxt)
	{
		double elapsed = ctxt->GetElapsed();
		float animFrame = (float)(m_mmdModel->GetAnimationTime() * 30.0);
		if (m_clipElapsed)
		{
			if (elapsed > 1.0f / 30.0f)
			{
				elapsed = 1.0f / 30.0f;
			}
		}

		switch (m_playMode)
		{
		case PlayMode::None:
			break;
		case PlayMode::Play:
			m_mmdModel->UpdateAnimation(elapsed);
			m_mmdModel->Update(elapsed);
			break;
		case PlayMode::Stop:
			m_mmdModel->Update(elapsed);
			break;
		case PlayMode::Update:
			m_mmdModel->UpdateAnimation(0.0f);
			m_mmdModel->Update(elapsed);
			m_playMode = PlayMode::Stop;
			break;
		case PlayMode::StepFF:
			m_mmdModel->UpdateAnimation(1.0f / 30.0f);
			m_mmdModel->Update(elapsed);
			m_playMode = PlayMode::Stop;
			break;
		case PlayMode::StepFR:
			m_mmdModel->UpdateAnimation(-1.0f / 30.0f);
			m_mmdModel->Update(elapsed);
			m_playMode = PlayMode::Stop;
			break;
		default:
			break;
		}
	}

	void GLMMDModelDrawer::Draw(ViewerContext * ctxt)
	{
		const auto& view = ctxt->GetCamera()->GetViewMatrix();
		const auto& proj = ctxt->GetCamera()->GetProjectionMatrix();

		auto wv = view * m_world;
		auto wvp = proj * view * m_world;
		auto wvit = glm::mat3(view * m_world);
		wvit = glm::inverse(wvit);
		wvit = glm::transpose(wvit);
		for (const auto& subMesh : m_mmdModel->GetSubMeshes())
		{
			int matID = subMesh.m_materialID;
			const auto& matShader = m_materialShaders[matID];
			const auto& mmdMat = m_mmdModel->GetMaterials()[matID];
			auto shader = m_drawContext->GetShader(matShader.m_objShaderIndex);

			if (mmdMat.m_alpha == 0.0f)
			{
				continue;
			}

			glUseProgram(shader->m_prog);
			glBindVertexArray(matShader.m_vao);

			SetUniform(shader->m_uWV, wv);
			SetUniform(shader->m_uWVP, wvp);

			bool alphaBlend = true;

			SetUniform(shader->m_uAmbinet, mmdMat.m_ambient);
			SetUniform(shader->m_uDiffuse, mmdMat.m_diffuse);
			SetUniform(shader->m_uSpecular, mmdMat.m_specular);
			SetUniform(shader->m_uSpecularPower, mmdMat.m_specularPower);
			SetUniform(shader->m_uAlpha, mmdMat.m_alpha);

			glActiveTexture(GL_TEXTURE0 + 0);
			SetUniform(shader->m_uTex, (GLint)0);
			if (mmdMat.m_texture != 0)
			{
				if (!IsAlphaTexture(mmdMat.m_texture))
				{
					// Use Material Alpha
					SetUniform(shader->m_uTexMode, (GLint)1);
				}
				else
				{
					// Use Material Alpha * Texture Alpha
					SetUniform(shader->m_uTexMode, (GLint)2);
				}
				SetUniform(shader->m_uTexMulFactor, mmdMat.m_textureMulFactor);
				SetUniform(shader->m_uTexAddFactor, mmdMat.m_textureAddFactor);
				glBindTexture(GL_TEXTURE_2D, mmdMat.m_texture);
			}
			else
			{
				SetUniform(shader->m_uTexMode, (GLint)0);
				glBindTexture(GL_TEXTURE_2D, 0);
			}

			glActiveTexture(GL_TEXTURE0 + 1);
			SetUniform(shader->m_uSphereTex, (GLint)1);
			if (mmdMat.m_spTexture != 0)
			{
				if (mmdMat.m_spTextureMode == MMDMaterial::SphereTextureMode::Mul)
				{
					SetUniform(shader->m_uSphereTexMode, (GLint)1);
				}
				else if (mmdMat.m_spTextureMode == MMDMaterial::SphereTextureMode::Add)
				{
					SetUniform(shader->m_uSphereTexMode, (GLint)2);
				}
				SetUniform(shader->m_uSphereTexMulFactor, mmdMat.m_spTextureMulFactor);
				SetUniform(shader->m_uSphereTexAddFactor, mmdMat.m_spTextureAddFactor);
				glBindTexture(GL_TEXTURE_2D, mmdMat.m_spTexture);
			}
			else
			{
				SetUniform(shader->m_uSphereTexMode, (GLint)0);
				glBindTexture(GL_TEXTURE_2D, 0);
			}

			glActiveTexture(GL_TEXTURE0 + 2);
			SetUniform(shader->m_uToonTex, 2);
			if (mmdMat.m_toonTexture != 0)
			{
				SetUniform(shader->m_uToonTexMulFactor, mmdMat.m_toonTextureMulFactor);
				SetUniform(shader->m_uToonTexAddFactor, mmdMat.m_toonTextureAddFactor);
				SetUniform(shader->m_uToonTexMode, (GLint)1);
				glBindTexture(GL_TEXTURE_2D, mmdMat.m_toonTexture);
				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
			}
			else
			{
				SetUniform(shader->m_uToonTexMode, (GLint)0);
				glBindTexture(GL_TEXTURE_2D, 0);
			}

			glm::vec3 lightColor = glm::vec3(0.6f);
			glm::vec3 lightDir = glm::vec3(0.5f, 1.0f, 0.5f);
			glm::mat3 viewMat = glm::mat3(ctxt->GetCamera()->GetViewMatrix());
			lightDir = viewMat * lightDir;
			SetUniform(shader->m_uLightDir, lightDir);
			SetUniform(shader->m_uLightColor, lightColor);

			if (mmdMat.m_bothFace)
			{
				glDisable(GL_CULL_FACE);
			}
			else
			{
				glEnable(GL_CULL_FACE);
				glCullFace(GL_BACK);
			}

			if (alphaBlend)
			{
				glEnable(GL_BLEND);
				glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
			}
			else
			{
				glDisable(GL_BLEND);
			}

			size_t offset = subMesh.m_beginIndex * m_mmdModel->GetIndexTypeSize();
			glDrawElements(
				GL_TRIANGLES,
				subMesh.m_vertexCount,
				m_mmdModel->GetIndexType(),
				(GLvoid*)offset
			);

			glActiveTexture(GL_TEXTURE0 + 2);
			glBindTexture(GL_TEXTURE_2D, 0);
			glActiveTexture(GL_TEXTURE0 + 1);
			glBindTexture(GL_TEXTURE_2D, 0);
			glActiveTexture(GL_TEXTURE0 + 0);
			glBindTexture(GL_TEXTURE_2D, 0);

			glBindVertexArray(0);
			glUseProgram(0);
		}

		glBindVertexArray(0);
		glUseProgram(0);

		glDisable(GL_BLEND);
		glDisable(GL_CULL_FACE);
	}
}

<commit_msg>ライトの方向を修正<commit_after>#include "GLMMDModelDrawer.h"

#include "GLMMDModelDrawContext.h"

#include <Saba/Base/Log.h>
#include <Saba/GL/GLShaderUtil.h>
#include <Saba/GL/GLTextureUtil.h>

#include <imgui.h>

namespace saba
{
	GLMMDModelDrawer::GLMMDModelDrawer(GLMMDModelDrawContext * ctxt, std::shared_ptr<GLMMDModel> mmdModel)
		: m_drawContext(ctxt)
		, m_mmdModel(mmdModel)
		, m_playMode(PlayMode::None)
		, m_clipElapsed(true)
	{
		SABA_ASSERT(ctxt != nullptr);
		SABA_ASSERT(mmdModel != nullptr);
	}

	GLMMDModelDrawer::~GLMMDModelDrawer()
	{
		Destroy();
	}

	bool GLMMDModelDrawer::Create()
	{
		int matIdx = 0;
		for (const auto& mat : m_mmdModel->GetMaterials())
		{
			GLSLDefine define;

			MaterialShader matShader;
			matShader.m_objMaterialIndex = matIdx;
			matShader.m_objShaderIndex = m_drawContext->GetShaderIndex(define);
			if (matShader.m_objShaderIndex == -1)
			{
				SABA_ERROR("Obj Material Shader not found.");
				return false;
			}
			if (!matShader.m_vao.Create())
			{
				SABA_ERROR("Vertex Array Object Create fail.");
				return false;
			}

			auto shader = m_drawContext->GetShader(matShader.m_objShaderIndex);

			glBindVertexArray(matShader.m_vao);

			m_mmdModel->GetPositionBinder().Bind(shader->m_inPos, m_mmdModel->GetPositionVBO());
			glEnableVertexAttribArray(shader->m_inPos);

			m_mmdModel->GetNormalBinder().Bind(shader->m_inNor, m_mmdModel->GetNormalVBO());
			glEnableVertexAttribArray(shader->m_inNor);

			if (shader->m_inUV != -1)
			{
				m_mmdModel->GetUVBinder().Bind(shader->m_inUV, m_mmdModel->GetUVVBO());
				glEnableVertexAttribArray(shader->m_inUV);
			}

			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_mmdModel->GetIBO());

			glBindVertexArray(0);

			m_materialShaders.emplace_back(std::move(matShader));

			matIdx++;
		}
		m_playMode = PlayMode::Stop;
		return true;
	}

	void GLMMDModelDrawer::Destroy()
	{
		m_materialShaders.clear();
	}

	void GLMMDModelDrawer::DrawUI(ViewerContext * ctxt)
	{
		ImGui::Begin("MMDDrawCtrl");
		if (ImGui::CollapsingHeader("Animation"))
		{
			ImGui::Checkbox("Clip Elapsed", &m_clipElapsed);
			float animFrame = (float)(m_mmdModel->GetAnimationTime() * 30.0);
			if (ImGui::InputFloat("Frame", &animFrame))
			{
				m_mmdModel->SetAnimationTime(animFrame / 30.0);
				m_playMode = PlayMode::Update;
			}

			if (m_playMode == PlayMode::Play)
			{
				if (ImGui::Button("Stop"))
				{
					m_playMode = PlayMode::Stop;
				}
			}
			else
			{
				if (ImGui::Button("Play"))
				{
					m_playMode = PlayMode::Play;
				}
			}
			if (ImGui::Button("Step FF"))
			{
				m_playMode = PlayMode::StepFF;
			}
			if (ImGui::Button("Step FR"))
			{
				m_playMode = PlayMode::StepFR;
			}
		}
		if (ImGui::CollapsingHeader("Morph"))
		{
			auto model = m_mmdModel->GetMMDModel();
			auto morphMan = model->GetMorphManager();
			size_t morphCount = morphMan->GetMorphCount();
			for (size_t morphIdx = 0; morphIdx < morphCount; morphIdx++)
			{
				auto morph = morphMan->GetMorph(morphIdx);
				float weight = morph->GetWeight();
				if (ImGui::SliderFloat(morph->GetName().c_str(), &weight, 0.0f, 1.0f))
				{
					morph->SetWeight(weight);
					m_playMode = PlayMode::Update;
				}
			}
		}
		ImGui::End();
	}

	void GLMMDModelDrawer::Update(ViewerContext * ctxt)
	{
		double elapsed = ctxt->GetElapsed();
		float animFrame = (float)(m_mmdModel->GetAnimationTime() * 30.0);
		if (m_clipElapsed)
		{
			if (elapsed > 1.0f / 30.0f)
			{
				elapsed = 1.0f / 30.0f;
			}
		}

		switch (m_playMode)
		{
		case PlayMode::None:
			break;
		case PlayMode::Play:
			m_mmdModel->UpdateAnimation(elapsed);
			m_mmdModel->Update(elapsed);
			break;
		case PlayMode::Stop:
			m_mmdModel->Update(elapsed);
			break;
		case PlayMode::Update:
			m_mmdModel->UpdateAnimation(0.0f);
			m_mmdModel->Update(elapsed);
			m_playMode = PlayMode::Stop;
			break;
		case PlayMode::StepFF:
			m_mmdModel->UpdateAnimation(1.0f / 30.0f);
			m_mmdModel->Update(elapsed);
			m_playMode = PlayMode::Stop;
			break;
		case PlayMode::StepFR:
			m_mmdModel->UpdateAnimation(-1.0f / 30.0f);
			m_mmdModel->Update(elapsed);
			m_playMode = PlayMode::Stop;
			break;
		default:
			break;
		}
	}

	void GLMMDModelDrawer::Draw(ViewerContext * ctxt)
	{
		const auto& view = ctxt->GetCamera()->GetViewMatrix();
		const auto& proj = ctxt->GetCamera()->GetProjectionMatrix();

		auto wv = view * m_world;
		auto wvp = proj * view * m_world;
		auto wvit = glm::mat3(view * m_world);
		wvit = glm::inverse(wvit);
		wvit = glm::transpose(wvit);
		for (const auto& subMesh : m_mmdModel->GetSubMeshes())
		{
			int matID = subMesh.m_materialID;
			const auto& matShader = m_materialShaders[matID];
			const auto& mmdMat = m_mmdModel->GetMaterials()[matID];
			auto shader = m_drawContext->GetShader(matShader.m_objShaderIndex);

			if (mmdMat.m_alpha == 0.0f)
			{
				continue;
			}

			glUseProgram(shader->m_prog);
			glBindVertexArray(matShader.m_vao);

			SetUniform(shader->m_uWV, wv);
			SetUniform(shader->m_uWVP, wvp);

			bool alphaBlend = true;

			SetUniform(shader->m_uAmbinet, mmdMat.m_ambient);
			SetUniform(shader->m_uDiffuse, mmdMat.m_diffuse);
			SetUniform(shader->m_uSpecular, mmdMat.m_specular);
			SetUniform(shader->m_uSpecularPower, mmdMat.m_specularPower);
			SetUniform(shader->m_uAlpha, mmdMat.m_alpha);

			glActiveTexture(GL_TEXTURE0 + 0);
			SetUniform(shader->m_uTex, (GLint)0);
			if (mmdMat.m_texture != 0)
			{
				if (!IsAlphaTexture(mmdMat.m_texture))
				{
					// Use Material Alpha
					SetUniform(shader->m_uTexMode, (GLint)1);
				}
				else
				{
					// Use Material Alpha * Texture Alpha
					SetUniform(shader->m_uTexMode, (GLint)2);
				}
				SetUniform(shader->m_uTexMulFactor, mmdMat.m_textureMulFactor);
				SetUniform(shader->m_uTexAddFactor, mmdMat.m_textureAddFactor);
				glBindTexture(GL_TEXTURE_2D, mmdMat.m_texture);
			}
			else
			{
				SetUniform(shader->m_uTexMode, (GLint)0);
				glBindTexture(GL_TEXTURE_2D, 0);
			}

			glActiveTexture(GL_TEXTURE0 + 1);
			SetUniform(shader->m_uSphereTex, (GLint)1);
			if (mmdMat.m_spTexture != 0)
			{
				if (mmdMat.m_spTextureMode == MMDMaterial::SphereTextureMode::Mul)
				{
					SetUniform(shader->m_uSphereTexMode, (GLint)1);
				}
				else if (mmdMat.m_spTextureMode == MMDMaterial::SphereTextureMode::Add)
				{
					SetUniform(shader->m_uSphereTexMode, (GLint)2);
				}
				SetUniform(shader->m_uSphereTexMulFactor, mmdMat.m_spTextureMulFactor);
				SetUniform(shader->m_uSphereTexAddFactor, mmdMat.m_spTextureAddFactor);
				glBindTexture(GL_TEXTURE_2D, mmdMat.m_spTexture);
			}
			else
			{
				SetUniform(shader->m_uSphereTexMode, (GLint)0);
				glBindTexture(GL_TEXTURE_2D, 0);
			}

			glActiveTexture(GL_TEXTURE0 + 2);
			SetUniform(shader->m_uToonTex, 2);
			if (mmdMat.m_toonTexture != 0)
			{
				SetUniform(shader->m_uToonTexMulFactor, mmdMat.m_toonTextureMulFactor);
				SetUniform(shader->m_uToonTexAddFactor, mmdMat.m_toonTextureAddFactor);
				SetUniform(shader->m_uToonTexMode, (GLint)1);
				glBindTexture(GL_TEXTURE_2D, mmdMat.m_toonTexture);
				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
			}
			else
			{
				SetUniform(shader->m_uToonTexMode, (GLint)0);
				glBindTexture(GL_TEXTURE_2D, 0);
			}

			glm::vec3 lightColor = glm::vec3(0.6f);
			glm::vec3 lightDir = glm::normalize(glm::vec3(0.5f, -1.0f, 0.5f));
			glm::mat3 viewMat = glm::mat3(ctxt->GetCamera()->GetViewMatrix());
			lightDir = viewMat * lightDir;
			SetUniform(shader->m_uLightDir, lightDir);
			SetUniform(shader->m_uLightColor, lightColor);

			if (mmdMat.m_bothFace)
			{
				glDisable(GL_CULL_FACE);
			}
			else
			{
				glEnable(GL_CULL_FACE);
				glCullFace(GL_BACK);
			}

			if (alphaBlend)
			{
				glEnable(GL_BLEND);
				glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
			}
			else
			{
				glDisable(GL_BLEND);
			}

			size_t offset = subMesh.m_beginIndex * m_mmdModel->GetIndexTypeSize();
			glDrawElements(
				GL_TRIANGLES,
				subMesh.m_vertexCount,
				m_mmdModel->GetIndexType(),
				(GLvoid*)offset
			);

			glActiveTexture(GL_TEXTURE0 + 2);
			glBindTexture(GL_TEXTURE_2D, 0);
			glActiveTexture(GL_TEXTURE0 + 1);
			glBindTexture(GL_TEXTURE_2D, 0);
			glActiveTexture(GL_TEXTURE0 + 0);
			glBindTexture(GL_TEXTURE_2D, 0);

			glBindVertexArray(0);
			glUseProgram(0);
		}

		glBindVertexArray(0);
		glUseProgram(0);

		glDisable(GL_BLEND);
		glDisable(GL_CULL_FACE);
	}
}

<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "views/controls/native/native_view_host_win.h"

#include "base/logging.h"
#include "gfx/canvas.h"
#include "views/controls/native/native_view_host.h"
#include "views/focus/focus_manager.h"
#include "views/widget/root_view.h"
#include "views/widget/widget.h"

namespace views {

////////////////////////////////////////////////////////////////////////////////
// NativeViewHostWin, public:

NativeViewHostWin::NativeViewHostWin(NativeViewHost* host)
    : host_(host),
      installed_clip_(false) {
}

NativeViewHostWin::~NativeViewHostWin() {
}

////////////////////////////////////////////////////////////////////////////////
// NativeViewHostWin, NativeViewHostWrapper implementation:
void NativeViewHostWin::NativeViewAttached() {
  DCHECK(host_->native_view())
      << "Impossible detatched tab case; See crbug.com/6316";

  // First hide the new window. We don't want anything to draw (like sub-hwnd
  // borders), when we change the parent below.
  ShowWindow(host_->native_view(), SW_HIDE);

  // Need to set the HWND's parent before changing its size to avoid flashing.
  SetParent(host_->native_view(), host_->GetWidget()->GetNativeView());
  host_->Layout();
  // Notify children that parent changed, so they could adjust the focus
  std::vector<RootView*> root_views;
  Widget::FindAllRootViews(host_->native_view(), &root_views);
  for (std::vector<RootView*>::iterator it = root_views.begin();
       it < root_views.end();
       ++it) {
    (*it)->NotifyNativeViewHierarchyChanged(true,
        host_->GetWidget()->GetNativeView());
  }
}

void NativeViewHostWin::NativeViewDetaching(bool destroyed) {
  installed_clip_ = false;
  // Notify children that parent is removed
  std::vector<RootView*> root_views;
  Widget::FindAllRootViews(host_->native_view(), &root_views);
  for (std::vector<RootView*>::iterator it = root_views.begin();
       it < root_views.end();
       ++it) {
    (*it)->NotifyNativeViewHierarchyChanged(false,
        host_->GetWidget()->GetNativeView());
  }
}

void NativeViewHostWin::AddedToWidget() {
  if (!IsWindow(host_->native_view()))
    return;
  HWND parent_hwnd = GetParent(host_->native_view());
  HWND widget_hwnd = host_->GetWidget()->GetNativeView();
  if (parent_hwnd != widget_hwnd)
    SetParent(host_->native_view(), widget_hwnd);
  if (host_->IsVisibleInRootView())
    ShowWindow(host_->native_view(), SW_SHOW);
  else
    ShowWindow(host_->native_view(), SW_HIDE);
  host_->Layout();
}

void NativeViewHostWin::RemovedFromWidget() {
  if (!IsWindow(host_->native_view()))
    return;
  ShowWindow(host_->native_view(), SW_HIDE);
  SetParent(host_->native_view(), NULL);
}

void NativeViewHostWin::InstallClip(int x, int y, int w, int h) {
  HRGN clip_region = CreateRectRgn(x, y, x + w, y + h);
  // NOTE: SetWindowRgn owns the region (as well as the deleting the
  // current region), as such we don't delete the old region.
  SetWindowRgn(host_->native_view(), clip_region, TRUE);
  installed_clip_ = true;
}

bool NativeViewHostWin::HasInstalledClip() {
  return installed_clip_;
}

void NativeViewHostWin::UninstallClip() {
  SetWindowRgn(host_->native_view(), 0, TRUE);
  installed_clip_ = false;
}

void NativeViewHostWin::ShowWidget(int x, int y, int w, int h) {
  UINT swp_flags = SWP_DEFERERASE |
                   SWP_NOACTIVATE |
                   SWP_NOCOPYBITS |
                   SWP_NOOWNERZORDER |
                   SWP_NOZORDER;
  // Only send the SHOWWINDOW flag if we're invisible, to avoid flashing.
  if (!IsWindowVisible(host_->native_view()))
    swp_flags = (swp_flags | SWP_SHOWWINDOW) & ~SWP_NOREDRAW;

  if (host_->fast_resize()) {
    // In a fast resize, we move the window and clip it with SetWindowRgn.
    RECT win_rect;
    GetWindowRect(host_->native_view(), &win_rect);
    gfx::Rect rect(win_rect);
    SetWindowPos(host_->native_view(), 0, x, y, rect.width(), rect.height(),
                 swp_flags);

    InstallClip(0, 0, w, h);
  } else {
    SetWindowPos(host_->native_view(), 0, x, y, w, h, swp_flags);
  }
}

void NativeViewHostWin::HideWidget() {
  if (!IsWindowVisible(host_->native_view()))
    return;  // Currently not visible, nothing to do.

  // The window is currently visible, but its clipped by another view. Hide
  // it.
  SetWindowPos(host_->native_view(), 0, 0, 0, 0, 0,
               SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER |
               SWP_NOREDRAW | SWP_NOOWNERZORDER);
}

void NativeViewHostWin::SetFocus() {
  ::SetFocus(host_->native_view());
}

////////////////////////////////////////////////////////////////////////////////
// NativeViewHostWrapper, public:

// static
NativeViewHostWrapper* NativeViewHostWrapper::CreateWrapper(
    NativeViewHost* host) {
  return new NativeViewHostWin(host);
}

}  // namespace views
<commit_msg>Fixes another gray rect. This problem occurred because NativeViewHost was not correctly resetting state when the child was switched. In particular it wouldn't remove the clip when switching, which meant that if we switched back to an hwnd we had installed a clip we wouldn't reset the clip when we should have.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "views/controls/native/native_view_host_win.h"

#include "base/logging.h"
#include "gfx/canvas.h"
#include "views/controls/native/native_view_host.h"
#include "views/focus/focus_manager.h"
#include "views/widget/root_view.h"
#include "views/widget/widget.h"

namespace views {

////////////////////////////////////////////////////////////////////////////////
// NativeViewHostWin, public:

NativeViewHostWin::NativeViewHostWin(NativeViewHost* host)
    : host_(host),
      installed_clip_(false) {
}

NativeViewHostWin::~NativeViewHostWin() {
}

////////////////////////////////////////////////////////////////////////////////
// NativeViewHostWin, NativeViewHostWrapper implementation:
void NativeViewHostWin::NativeViewAttached() {
  DCHECK(host_->native_view())
      << "Impossible detatched tab case; See crbug.com/6316";

  // First hide the new window. We don't want anything to draw (like sub-hwnd
  // borders), when we change the parent below.
  ShowWindow(host_->native_view(), SW_HIDE);

  // Need to set the HWND's parent before changing its size to avoid flashing.
  SetParent(host_->native_view(), host_->GetWidget()->GetNativeView());
  host_->Layout();
  // Notify children that parent changed, so they could adjust the focus
  std::vector<RootView*> root_views;
  Widget::FindAllRootViews(host_->native_view(), &root_views);
  for (std::vector<RootView*>::iterator it = root_views.begin();
       it < root_views.end();
       ++it) {
    (*it)->NotifyNativeViewHierarchyChanged(true,
        host_->GetWidget()->GetNativeView());
  }
}

void NativeViewHostWin::NativeViewDetaching(bool destroyed) {
  if (!destroyed && installed_clip_)
    UninstallClip();
  installed_clip_ = false;
  // Notify children that parent is removed
  std::vector<RootView*> root_views;
  Widget::FindAllRootViews(host_->native_view(), &root_views);
  for (std::vector<RootView*>::iterator it = root_views.begin();
       it < root_views.end();
       ++it) {
    (*it)->NotifyNativeViewHierarchyChanged(false,
        host_->GetWidget()->GetNativeView());
  }
}

void NativeViewHostWin::AddedToWidget() {
  if (!IsWindow(host_->native_view()))
    return;
  HWND parent_hwnd = GetParent(host_->native_view());
  HWND widget_hwnd = host_->GetWidget()->GetNativeView();
  if (parent_hwnd != widget_hwnd)
    SetParent(host_->native_view(), widget_hwnd);
  if (host_->IsVisibleInRootView())
    ShowWindow(host_->native_view(), SW_SHOW);
  else
    ShowWindow(host_->native_view(), SW_HIDE);
  host_->Layout();
}

void NativeViewHostWin::RemovedFromWidget() {
  if (!IsWindow(host_->native_view()))
    return;
  ShowWindow(host_->native_view(), SW_HIDE);
  SetParent(host_->native_view(), NULL);
}

void NativeViewHostWin::InstallClip(int x, int y, int w, int h) {
  HRGN clip_region = CreateRectRgn(x, y, x + w, y + h);
  // NOTE: SetWindowRgn owns the region (as well as the deleting the
  // current region), as such we don't delete the old region.
  SetWindowRgn(host_->native_view(), clip_region, TRUE);
  installed_clip_ = true;
}

bool NativeViewHostWin::HasInstalledClip() {
  return installed_clip_;
}

void NativeViewHostWin::UninstallClip() {
  SetWindowRgn(host_->native_view(), 0, TRUE);
  installed_clip_ = false;
}

void NativeViewHostWin::ShowWidget(int x, int y, int w, int h) {
  UINT swp_flags = SWP_DEFERERASE |
                   SWP_NOACTIVATE |
                   SWP_NOCOPYBITS |
                   SWP_NOOWNERZORDER |
                   SWP_NOZORDER;
  // Only send the SHOWWINDOW flag if we're invisible, to avoid flashing.
  if (!IsWindowVisible(host_->native_view()))
    swp_flags = (swp_flags | SWP_SHOWWINDOW) & ~SWP_NOREDRAW;

  if (host_->fast_resize()) {
    // In a fast resize, we move the window and clip it with SetWindowRgn.
    RECT win_rect;
    GetWindowRect(host_->native_view(), &win_rect);
    gfx::Rect rect(win_rect);
    SetWindowPos(host_->native_view(), 0, x, y, rect.width(), rect.height(),
                 swp_flags);

    InstallClip(0, 0, w, h);
  } else {
    SetWindowPos(host_->native_view(), 0, x, y, w, h, swp_flags);
  }
}

void NativeViewHostWin::HideWidget() {
  if (!IsWindowVisible(host_->native_view()))
    return;  // Currently not visible, nothing to do.

  // The window is currently visible, but its clipped by another view. Hide
  // it.
  SetWindowPos(host_->native_view(), 0, 0, 0, 0, 0,
               SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER |
               SWP_NOREDRAW | SWP_NOOWNERZORDER);
}

void NativeViewHostWin::SetFocus() {
  ::SetFocus(host_->native_view());
}

////////////////////////////////////////////////////////////////////////////////
// NativeViewHostWrapper, public:

// static
NativeViewHostWrapper* NativeViewHostWrapper::CreateWrapper(
    NativeViewHost* host) {
  return new NativeViewHostWin(host);
}

}  // namespace views
<|endoftext|>


<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2015 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include "sequencetimerproperty.h"
#include <inviwo/core/interaction/events/keyboardevent.h>
#include <inviwo/core/interaction/action.h>

namespace inviwo {

PropertyClassIdentifier(SequenceTimerProperty, "org.inviwo.SequenceTimerProperty");

SequenceTimerProperty::SequenceTimerProperty(std::string identifier, std::string displayName,
                                             InvalidationLevel invalidationLevel,
                                             PropertySemantics semantics)
    : CompositeProperty(identifier, displayName, invalidationLevel, semantics)
    , index_("selectedSequenceIndex", "Sequence Index", 1, 1, 1, 1)
    , play_("playSequence", "Play Sequence", false)
    , framesPerSecond_("volumesPerSecond", "Frame rate", 30, 1, 60, 1, InvalidationLevel::Valid)
    , playPause_(
          "playPause", "Play / Pause",
          new KeyboardEvent('P', InteractionEvent::MODIFIER_NONE, KeyboardEvent::KEY_STATE_PRESS),
          new Action([this](Event* e){play_.set(!play_.get());}))
    , timer_(1000 / framesPerSecond_.get(), [this]() { onTimerEvent(); }) {
    play_.onChange(this, &SequenceTimerProperty::onPlaySequenceToggled);

    framesPerSecond_.onChange([this]() { timer_.setInterval(1000 / framesPerSecond_.get()); });
    index_.setSerializationMode(PropertySerializationMode::ALL);
    addProperty(index_);
    addProperty(play_);
    addProperty(framesPerSecond_);
    addProperty(playPause_);
}

SequenceTimerProperty::SequenceTimerProperty(const SequenceTimerProperty& rhs)
    : CompositeProperty(rhs)
    , index_(rhs.index_)
    , play_(rhs.play_)
    , framesPerSecond_(rhs.framesPerSecond_)
    , playPause_(rhs.playPause_)
    , timer_(1000 / framesPerSecond_.get(), [this]() { onTimerEvent(); }) {
    framesPerSecond_.onChange([this]() { timer_.setInterval(1000 / framesPerSecond_.get()); });
    index_.setSerializationMode(PropertySerializationMode::ALL);
    addProperty(index_);
    addProperty(play_);
    addProperty(framesPerSecond_);
    addProperty(playPause_);
}

SequenceTimerProperty& SequenceTimerProperty::operator=(const SequenceTimerProperty& that) {
    if (this != &that) {
        CompositeProperty::operator=(that);
        index_ = that.index_;
        play_ = that.play_;
        framesPerSecond_ = that.framesPerSecond_;
        playPause_ = that.playPause_;

    }
    return *this;
}

SequenceTimerProperty* SequenceTimerProperty::clone() const {
    return new SequenceTimerProperty(*this);
}

void SequenceTimerProperty::updateMax(size_t max) {
    index_.setMaxValue(static_cast<int>(max));
    index_.set(1);
    index_.setCurrentStateAsDefault();
}

void inviwo::SequenceTimerProperty::onTimerEvent() {
    index_ = (index_ < index_.getMaxValue() ? index_ + 1 : 1);
}

void inviwo::SequenceTimerProperty::onPlaySequenceToggled() {
    if (index_.getMaxValue() > 1) {
        if (play_.get()) {
            timer_.start(1000 / framesPerSecond_.get());
            index_.setReadOnly(true);
        } else {
            timer_.stop();
            index_.setReadOnly(false);
        }
    }
}

}  // namespace
<commit_msg>Base: SequenceTimerProperty: Only reset index if max value is actually changing (was always setting it to 1 when deserializing)<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2015 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include "sequencetimerproperty.h"
#include <inviwo/core/interaction/events/keyboardevent.h>
#include <inviwo/core/interaction/action.h>

namespace inviwo {

PropertyClassIdentifier(SequenceTimerProperty, "org.inviwo.SequenceTimerProperty");

SequenceTimerProperty::SequenceTimerProperty(std::string identifier, std::string displayName,
                                             InvalidationLevel invalidationLevel,
                                             PropertySemantics semantics)
    : CompositeProperty(identifier, displayName, invalidationLevel, semantics)
    , index_("selectedSequenceIndex", "Sequence Index", 1, 1, 1, 1)
    , play_("playSequence", "Play Sequence", false)
    , framesPerSecond_("volumesPerSecond", "Frame rate", 30, 1, 60, 1, InvalidationLevel::Valid)
    , playPause_(
          "playPause", "Play / Pause",
          new KeyboardEvent('P', InteractionEvent::MODIFIER_NONE, KeyboardEvent::KEY_STATE_PRESS),
          new Action([this](Event* e){play_.set(!play_.get());}))
    , timer_(1000 / framesPerSecond_.get(), [this]() { onTimerEvent(); }) {
    play_.onChange(this, &SequenceTimerProperty::onPlaySequenceToggled);

    framesPerSecond_.onChange([this]() { timer_.setInterval(1000 / framesPerSecond_.get()); });
    index_.setSerializationMode(PropertySerializationMode::ALL);
    addProperty(index_);
    addProperty(play_);
    addProperty(framesPerSecond_);
    addProperty(playPause_);
}

SequenceTimerProperty::SequenceTimerProperty(const SequenceTimerProperty& rhs)
    : CompositeProperty(rhs)
    , index_(rhs.index_)
    , play_(rhs.play_)
    , framesPerSecond_(rhs.framesPerSecond_)
    , playPause_(rhs.playPause_)
    , timer_(1000 / framesPerSecond_.get(), [this]() { onTimerEvent(); }) {
    framesPerSecond_.onChange([this]() { timer_.setInterval(1000 / framesPerSecond_.get()); });
    index_.setSerializationMode(PropertySerializationMode::ALL);
    addProperty(index_);
    addProperty(play_);
    addProperty(framesPerSecond_);
    addProperty(playPause_);
}

SequenceTimerProperty& SequenceTimerProperty::operator=(const SequenceTimerProperty& that) {
    if (this != &that) {
        CompositeProperty::operator=(that);
        index_ = that.index_;
        play_ = that.play_;
        framesPerSecond_ = that.framesPerSecond_;
        playPause_ = that.playPause_;

    }
    return *this;
}

SequenceTimerProperty* SequenceTimerProperty::clone() const {
    return new SequenceTimerProperty(*this);
}

void SequenceTimerProperty::updateMax(size_t max) {
    if (max != index_.getMaxValue()) {
        index_.setMaxValue(static_cast<int>(max));
        index_.set(1);
        index_.setCurrentStateAsDefault();
    }
}

void inviwo::SequenceTimerProperty::onTimerEvent() {
    index_ = (index_ < index_.getMaxValue() ? index_ + 1 : 1);
}

void inviwo::SequenceTimerProperty::onPlaySequenceToggled() {
    if (index_.getMaxValue() > 1) {
        if (play_.get()) {
            timer_.start(1000 / framesPerSecond_.get());
            index_.setReadOnly(true);
        } else {
            timer_.stop();
            index_.setReadOnly(false);
        }
    }
}

}  // namespace
<|endoftext|>


<commit_before>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"
#include "modules/geolocation/PositionOptions.h"

#include "bindings/core/v8/Dictionary.h"
#include <limits.h>

namespace WebCore {

PositionOptions* PositionOptions::create(const Dictionary& options)
{
    return new PositionOptions(options);
}

PositionOptions::PositionOptions(const Dictionary& options)
    : m_highAccuracy(false)
    , m_maximumAge(0)
    , m_timeout(std::numeric_limits<unsigned>::max())
{
    if (options.hasProperty("enableHighAccuracy"))
        options.get("enableHighAccuracy", m_highAccuracy);
    if (options.hasProperty("maximumAge")) {
        double maximumAge;
        options.get("maximumAge", maximumAge);
        if (maximumAge < 0)
            m_maximumAge = 0;
        else if (maximumAge > std::numeric_limits<unsigned>::max())
            m_maximumAge = std::numeric_limits<unsigned>::max();
        else
            m_maximumAge = maximumAge;
    }
    if (options.hasProperty("timeout")) {
        double timeout;
        options.get("timeout", timeout);
        if (timeout < 0)
            m_timeout = 0;
        else if (timeout > std::numeric_limits<unsigned>::max())
            m_timeout = std::numeric_limits<unsigned>::max();
        else
            m_timeout = timeout;
    }
}

} // namespace WebCore
<commit_msg>maximumAge and timeout should be used after initialization.<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"
#include "modules/geolocation/PositionOptions.h"

#include "bindings/core/v8/Dictionary.h"
#include <limits.h>

namespace WebCore {

PositionOptions* PositionOptions::create(const Dictionary& options)
{
    return new PositionOptions(options);
}

PositionOptions::PositionOptions(const Dictionary& options)
    : m_highAccuracy(false)
    , m_maximumAge(0)
    , m_timeout(std::numeric_limits<unsigned>::max())
{
    if (options.hasProperty("enableHighAccuracy")) {
        bool highAccuracy;
        if (options.get("enableHighAccuracy", highAccuracy))
            m_highAccuracy = highAccuracy;
    }
    if (options.hasProperty("maximumAge")) {
        double maximumAge;
        if (options.get("maximumAge", maximumAge)) {
            if (maximumAge < 0)
                m_maximumAge = 0;
            else if (maximumAge > std::numeric_limits<unsigned>::max())
                m_maximumAge = std::numeric_limits<unsigned>::max();
            else
                m_maximumAge = maximumAge;
        }
    }
    if (options.hasProperty("timeout")) {
        double timeout;
        if (options.get("timeout", timeout)) {
            if (timeout < 0)
                m_timeout = 0;
            else if (timeout > std::numeric_limits<unsigned>::max())
                m_timeout = std::numeric_limits<unsigned>::max();
            else
                m_timeout = timeout;
        }
    }
}

} // namespace WebCore
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: macros.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2001-09-28 09:44:09 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _TOOLKIT_HELPER_MACROS_HXX_
#define _TOOLKIT_HELPER_MACROS_HXX_

// -------------------------------------------------------------------------------------

#define IMPL_XUNOTUNNEL( ClassName ) \
sal_Int64 ClassName::getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rIdentifier ) throw(::com::sun::star::uno::RuntimeException) \
{ \
    if( ( rIdentifier.getLength() == 16 ) && ( 0 == rtl_compareMemory( ClassName::GetUnoTunnelId().getConstArray(), rIdentifier.getConstArray(), 16 ) ) ) \
    { \
        return (sal_Int64)this; \
    } \
    return 0; \
} \
const ::com::sun::star::uno::Sequence< sal_Int8 >& ClassName::GetUnoTunnelId() throw() \
{ \
    static ::com::sun::star::uno::Sequence< sal_Int8 > * pSeq = NULL; \
    if( !pSeq ) \
    { \
        ::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ); \
        if( !pSeq ) \
        { \
            static ::com::sun::star::uno::Sequence< sal_Int8 > aSeq( 16 ); \
            rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); \
            pSeq = &aSeq; \
        } \
    } \
    return *pSeq; \
} \
ClassName* ClassName::GetImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rxIFace ) throw() \
{ \
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XUnoTunnel > xUT( rxIFace, ::com::sun::star::uno::UNO_QUERY ); \
    return xUT.is() ? (ClassName*)xUT->getSomething( ClassName::GetUnoTunnelId() ) : NULL; \
}

#define IMPL_XUNOTUNNEL2( ClassName, BaseClass ) \
sal_Int64 ClassName::getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rIdentifier ) throw(::com::sun::star::uno::RuntimeException) \
{ \
    if( ( rIdentifier.getLength() == 16 ) && ( 0 == rtl_compareMemory( ClassName::GetUnoTunnelId().getConstArray(), rIdentifier.getConstArray(), 16 ) ) ) \
    { \
        return (sal_Int64)this; \
    } \
    return BaseClass::getSomething( rIdentifier ); \
} \
const ::com::sun::star::uno::Sequence< sal_Int8 >& ClassName::GetUnoTunnelId() throw() \
{ \
    static ::com::sun::star::uno::Sequence< sal_Int8 > * pSeq = NULL; \
    if( !pSeq ) \
    { \
        ::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ); \
        if( !pSeq ) \
        { \
            static ::com::sun::star::uno::Sequence< sal_Int8 > aSeq( 16 ); \
            rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); \
            pSeq = &aSeq; \
        } \
    } \
    return *pSeq; \
} \
ClassName* ClassName::GetImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rxIFace ) throw() \
{ \
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XUnoTunnel > xUT( rxIFace, ::com::sun::star::uno::UNO_QUERY ); \
    return xUT.is() ? (ClassName*)xUT->getSomething( ClassName::GetUnoTunnelId() ) : NULL; \
}

// -------------------------------------------------------------------------------------

#define IMPL_XTYPEPROVIDER_START( ClassName )   \
::com::sun::star::uno::Sequence< sal_Int8 > ClassName::getImplementationId() throw(::com::sun::star::uno::RuntimeException) \
{ \
    static ::cppu::OImplementationId* pId = NULL; \
    if( !pId ) \
    { \
        ::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ); \
        if( ! pId ) \
        { \
            static ::cppu::OImplementationId id( sal_False ); \
            pId = &id; \
        } \
    } \
    return (*pId).getImplementationId(); \
} \
::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > ClassName::getTypes() throw(::com::sun::star::uno::RuntimeException) \
{ \
    static ::cppu::OTypeCollection* pCollection = NULL; \
    if( !pCollection ) \
    { \
        ::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ); \
        if( !pCollection ) \
        { \
            static ::cppu::OTypeCollection collection(

// -------------------------------------------------------------------------------------

#define IMPL_XTYPEPROVIDER_END \
            ); \
            pCollection = &collection; \
        } \
    } \
    return (*pCollection).getTypes(); \
}

// -------------------------------------------------------------------------------------

#define DECL_LISTENERMULTIPLEXER_START( ClassName, InterfaceName ) \
class ClassName : public ListenerMultiplexerBase, public InterfaceName \
{ \
public: \
    ClassName( ::cppu::OWeakObject& rSource ); \
    ::com::sun::star::uno::Any  SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException); \
    void                        SAL_CALL acquire() throw()  { ListenerMultiplexerBase::acquire(); } \
    void                        SAL_CALL release() throw()  { ListenerMultiplexerBase::release(); } \
    void                        SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException);

// -------------------------------------------------------------------------------------

#define DECL_LISTENERMULTIPLEXER_END \
};

// -------------------------------------------------------------------------------------

#define IMPL_LISTENERMULTIPLEXER_BASEMETHODS( ClassName, InterfaceName ) \
ClassName::ClassName( ::cppu::OWeakObject& rSource ) \
    : ListenerMultiplexerBase( rSource ) \
{ \
} \
::com::sun::star::uno::Any ClassName::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException) \
{ \
    ::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType, \
                                        SAL_STATIC_CAST( ::com::sun::star::lang::XEventListener*, this ), \
                                        SAL_STATIC_CAST( InterfaceName*, this ) ); \
    return (aRet.hasValue() ? aRet : ListenerMultiplexerBase::queryInterface( rType )); \
} \
void ClassName::disposing( const ::com::sun::star::lang::EventObject& ) throw(::com::sun::star::uno::RuntimeException) \
{ \
}

// -------------------------------------------------------------------------------------

#define IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( ClassName, InterfaceName, MethodName, EventType ) \
void ClassName::MethodName( const EventType& e ) throw(::com::sun::star::uno::RuntimeException) \
{ \
    EventType aMulti( e ); \
    aMulti.Source = &GetContext(); \
    ::cppu::OInterfaceIteratorHelper aIt( *this ); \
    while( aIt.hasMoreElements() ) \
        ((InterfaceName*)aIt.next())->MethodName( aMulti ); \
}

// -------------------------------------------------------------------------------------

#define DECLIMPL_SERVICEINFO( ImplName, ServiceName ) \
    ::rtl::OUString SAL_CALL getImplementationName(  ) throw(::com::sun::star::uno::RuntimeException) { return ::rtl::OUString::createFromAscii( "stardiv.Toolkit." #ImplName ); } \
    ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException)   \
                            { \
                                ::rtl::OUString aServiceName( ServiceName ); \
                                return ::com::sun::star::uno::Sequence< ::rtl::OUString >( &aServiceName, 1);\
                            } \
    sal_Bool SAL_CALL supportsService( const ::rtl::OUString& rServiceName ) throw(::com::sun::star::uno::RuntimeException) \
                            { return rServiceName == ServiceName; }

#endif // _TOOLKIT_HELPER_MACROS_HXX_

<commit_msg>#88707# when implementing the XTypeProvider, always return the XTypeProvider cppu type<commit_after>/*************************************************************************
 *
 *  $RCSfile: macros.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: fs $ $Date: 2001-12-07 16:23:58 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _TOOLKIT_HELPER_MACROS_HXX_
#define _TOOLKIT_HELPER_MACROS_HXX_

// -------------------------------------------------------------------------------------

#define IMPL_XUNOTUNNEL( ClassName ) \
sal_Int64 ClassName::getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rIdentifier ) throw(::com::sun::star::uno::RuntimeException) \
{ \
    if( ( rIdentifier.getLength() == 16 ) && ( 0 == rtl_compareMemory( ClassName::GetUnoTunnelId().getConstArray(), rIdentifier.getConstArray(), 16 ) ) ) \
    { \
        return (sal_Int64)this; \
    } \
    return 0; \
} \
const ::com::sun::star::uno::Sequence< sal_Int8 >& ClassName::GetUnoTunnelId() throw() \
{ \
    static ::com::sun::star::uno::Sequence< sal_Int8 > * pSeq = NULL; \
    if( !pSeq ) \
    { \
        ::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ); \
        if( !pSeq ) \
        { \
            static ::com::sun::star::uno::Sequence< sal_Int8 > aSeq( 16 ); \
            rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); \
            pSeq = &aSeq; \
        } \
    } \
    return *pSeq; \
} \
ClassName* ClassName::GetImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rxIFace ) throw() \
{ \
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XUnoTunnel > xUT( rxIFace, ::com::sun::star::uno::UNO_QUERY ); \
    return xUT.is() ? (ClassName*)xUT->getSomething( ClassName::GetUnoTunnelId() ) : NULL; \
}

#define IMPL_XUNOTUNNEL2( ClassName, BaseClass ) \
sal_Int64 ClassName::getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rIdentifier ) throw(::com::sun::star::uno::RuntimeException) \
{ \
    if( ( rIdentifier.getLength() == 16 ) && ( 0 == rtl_compareMemory( ClassName::GetUnoTunnelId().getConstArray(), rIdentifier.getConstArray(), 16 ) ) ) \
    { \
        return (sal_Int64)this; \
    } \
    return BaseClass::getSomething( rIdentifier ); \
} \
const ::com::sun::star::uno::Sequence< sal_Int8 >& ClassName::GetUnoTunnelId() throw() \
{ \
    static ::com::sun::star::uno::Sequence< sal_Int8 > * pSeq = NULL; \
    if( !pSeq ) \
    { \
        ::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ); \
        if( !pSeq ) \
        { \
            static ::com::sun::star::uno::Sequence< sal_Int8 > aSeq( 16 ); \
            rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); \
            pSeq = &aSeq; \
        } \
    } \
    return *pSeq; \
} \
ClassName* ClassName::GetImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rxIFace ) throw() \
{ \
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XUnoTunnel > xUT( rxIFace, ::com::sun::star::uno::UNO_QUERY ); \
    return xUT.is() ? (ClassName*)xUT->getSomething( ClassName::GetUnoTunnelId() ) : NULL; \
}

// -------------------------------------------------------------------------------------

#define IMPL_XTYPEPROVIDER_START( ClassName )   \
::com::sun::star::uno::Sequence< sal_Int8 > ClassName::getImplementationId() throw(::com::sun::star::uno::RuntimeException) \
{ \
    static ::cppu::OImplementationId* pId = NULL; \
    if( !pId ) \
    { \
        ::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ); \
        if( ! pId ) \
        { \
            static ::cppu::OImplementationId id( sal_False ); \
            pId = &id; \
        } \
    } \
    return (*pId).getImplementationId(); \
} \
::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > ClassName::getTypes() throw(::com::sun::star::uno::RuntimeException) \
{ \
    static ::cppu::OTypeCollection* pCollection = NULL; \
    if( !pCollection ) \
    { \
        ::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ); \
        if( !pCollection ) \
        { \
            static ::cppu::OTypeCollection collection( \
            getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::lang::XTypeProvider>* ) NULL ),

// -------------------------------------------------------------------------------------

#define IMPL_XTYPEPROVIDER_END \
            ); \
            pCollection = &collection; \
        } \
    } \
    return (*pCollection).getTypes(); \
}

// -------------------------------------------------------------------------------------

#define DECL_LISTENERMULTIPLEXER_START( ClassName, InterfaceName ) \
class ClassName : public ListenerMultiplexerBase, public InterfaceName \
{ \
public: \
    ClassName( ::cppu::OWeakObject& rSource ); \
    ::com::sun::star::uno::Any  SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException); \
    void                        SAL_CALL acquire() throw()  { ListenerMultiplexerBase::acquire(); } \
    void                        SAL_CALL release() throw()  { ListenerMultiplexerBase::release(); } \
    void                        SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException);

// -------------------------------------------------------------------------------------

#define DECL_LISTENERMULTIPLEXER_END \
};

// -------------------------------------------------------------------------------------

#define IMPL_LISTENERMULTIPLEXER_BASEMETHODS( ClassName, InterfaceName ) \
ClassName::ClassName( ::cppu::OWeakObject& rSource ) \
    : ListenerMultiplexerBase( rSource ) \
{ \
} \
::com::sun::star::uno::Any ClassName::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException) \
{ \
    ::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType, \
                                        SAL_STATIC_CAST( ::com::sun::star::lang::XEventListener*, this ), \
                                        SAL_STATIC_CAST( InterfaceName*, this ) ); \
    return (aRet.hasValue() ? aRet : ListenerMultiplexerBase::queryInterface( rType )); \
} \
void ClassName::disposing( const ::com::sun::star::lang::EventObject& ) throw(::com::sun::star::uno::RuntimeException) \
{ \
}

// -------------------------------------------------------------------------------------

#define IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( ClassName, InterfaceName, MethodName, EventType ) \
void ClassName::MethodName( const EventType& e ) throw(::com::sun::star::uno::RuntimeException) \
{ \
    EventType aMulti( e ); \
    aMulti.Source = &GetContext(); \
    ::cppu::OInterfaceIteratorHelper aIt( *this ); \
    while( aIt.hasMoreElements() ) \
        ((InterfaceName*)aIt.next())->MethodName( aMulti ); \
}

// -------------------------------------------------------------------------------------

#define DECLIMPL_SERVICEINFO( ImplName, ServiceName ) \
    ::rtl::OUString SAL_CALL getImplementationName(  ) throw(::com::sun::star::uno::RuntimeException) { return ::rtl::OUString::createFromAscii( "stardiv.Toolkit." #ImplName ); } \
    ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException)   \
                            { \
                                ::rtl::OUString aServiceName( ServiceName ); \
                                return ::com::sun::star::uno::Sequence< ::rtl::OUString >( &aServiceName, 1);\
                            } \
    sal_Bool SAL_CALL supportsService( const ::rtl::OUString& rServiceName ) throw(::com::sun::star::uno::RuntimeException) \
                            { return rServiceName == ServiceName; }

#endif // _TOOLKIT_HELPER_MACROS_HXX_

<|endoftext|>


<commit_before>#ifndef Src_Ancona_Util_StateMachine_SharedMachine_H_
#define Src_Ancona_Util_StateMachine_SharedMachine_H_

#include <vector>

namespace ild
{

typedef int MachineState;

#define StateType(TypeName) namespace TypeName { enum Type : MachineState {
#define EndStateType ,Count }; }

/**
 * @brief Used to create a state machine that is shared by multiple objects.
 * @author Jeff Swenson
 */
template <class T, class R, class ... ArgsT>
class SharedMachine
{
    public:
        /**
         * @brief Construct and initialize a shared machine
         *
         * @param stateCount The number of states the machine should contain
         */
        SharedMachine(int maxState) : _actions(maxState, nullptr)
        {

        }

        /**
         * @brief Method Type used by the state machine
         *
         * @param MachineState State the machine is currently in. The machine action may mutate state to change the machine's state.
         * @param ArgsT... The arguments to be passed to the action.
         *
         * @return The result of the action.
         */
        typedef R (T::*MachineAction)(MachineState & state, ArgsT...);

        /**
         * @brief Set the action for the state.
         *
         * @param state State to have the action set.
         * @param action Action to be used for the state.
         */
        void SetAction(const MachineState & state, MachineAction action)
        {
            _actions[state] = action;
        }

        /**
         * @brief Fire the action corresponding to the state on the object.
         *
         * @param object Object that the action method will be called on.
         * @param state State that the object's machine is currently in.  May be mutated by the action to change to the state.
         * @param args Arguments to be passed to the action.
         *
         * @return The result of the action.
         */
        R Update(T & object, MachineState & state, ArgsT ... args)
        {
            return (object.*_actions[state])(state, args ...);
        }
    private:
        std::vector<MachineAction> _actions;
};

}
#endif
<commit_msg>Improve State Machine Template Parameter Descriptions<commit_after>#ifndef Src_Ancona_Util_StateMachine_SharedMachine_H_
#define Src_Ancona_Util_StateMachine_SharedMachine_H_

#include <vector>

namespace ild
{

typedef int MachineState;

#define StateType(TypeName) namespace TypeName { enum Type : MachineState {
#define EndStateType ,Count }; }

/**
 * @brief Used to create a state machine that is shared by multiple objects.
 * @author Jeff Swenson
 *
 * @tparam ObjectType Type of the object that the actions are called on.
 * @tparam ReturnType Return type of the action.
 * @tparam ArgsT Arguments passed to the action.  The call will look like objectType.action(state, ArgsT ...).
 */
template <class ObjectType, class ReturnType, class ... ArgsT>
class SharedMachine
{
    public:
        /**
         * @brief Construct and initialize a shared machine
         *
         * @param stateCount The number of states the machine should contain
         */
        SharedMachine(int maxState) : _actions(maxState, nullptr)
        {

        }

        /**
         * @brief Method Type used by the state machine
         *
         * @param MachineState State the machine is currently in. The machine action may mutate state to change the machine's state.
         * @param ArgsT... The arguments to be passed to the action.
         *
         * @return The result of the action.
         */
        typedef ReturnType (ObjectType::*MachineAction)(MachineState & state, ArgsT...);

        /**
         * @brief Set the action for the state.
         *
         * @param state State to have the action set.
         * @param action Action to be used for the state.
         */
        void SetAction(const MachineState & state, MachineAction action)
        {
            _actions[state] = action;
        }

        /**
         * @brief Fire the action corresponding to the state on the object.
         *
         * @param object Object that the action method will be called on.
         * @param state State that the object's machine is currently in.  May be mutated by the action to change to the state.
         * @param args Arguments to be passed to the action.
         *
         * @return The result of the action.
         */
        ReturnType Update(ObjectType & object, MachineState & state, ArgsT ... args)
        {
            return (object.*_actions[state])(state, args ...);
        }
    private:
        std::vector<MachineAction> _actions;
};

}
#endif
<|endoftext|>