<commit_before>/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

 Module:       FGPosition.cpp
 Author:       Jon S. Berndt
 Date started: 01/05/99
 Purpose:      Integrate the EOM to determine instantaneous position
 Called by:    FGFDMExec

 ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------

 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
 Foundation; either version 2 of the License, or (at your option) any later
 version.

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 details.

 You should have received a copy of the GNU General Public License along with
 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 Place - Suite 330, Boston, MA  02111-1307, USA.

 Further information about the GNU General Public License can also be found on
 the world wide web at http://www.gnu.org.

FUNCTIONAL DESCRIPTION
--------------------------------------------------------------------------------
This class encapsulates the integration of rates and accelerations to get the
current position of the aircraft.

HISTORY
--------------------------------------------------------------------------------
01/05/99   JSB   Created

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES,  and NOTES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[1] Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling
    Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420  Naval Postgraduate
    School, January 1994
[2] D. M. Henderson, "Euler Angles, Quaternions, and Transformation Matrices",
    JSC 12960, July 1977
[3] Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
    NASA-Ames", NASA CR-2497, January 1975
[4] Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
    Wiley & Sons, 1979 ISBN 0-471-03032-5
[5] Bernard Etkin, "Dynamics of Flight, Stability and Control", Wiley & Sons,
    1982 ISBN 0-471-08936-2

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

#ifdef FGFS
#  include <simgear/compiler.h>
#  ifdef SG_HAVE_STD_INCLUDES
#    include <cmath>
#    include <iomanip>
#  else
#    include <math.h>
#    include <iomanip.h>
#  endif
#else
#  if defined(sgi) && !defined(__GNUC__)
#    include <math.h>
#    if (_COMPILER_VERSION < 740)
#      include <iomanip.h>
#    else
#      include <iomanip>
#    endif
#  else
#    include <cmath>
#    include <iomanip>
#  endif
#endif

#include "FGPosition.h"
#include "FGState.h"
#include "FGFDMExec.h"
#include "FGAircraft.h"
#include "FGMassBalance.h"
#include "FGTranslation.h"
#include "FGRotation.h"
#include "FGInertial.h"
#include "FGPropertyManager.h"

namespace JSBSim {

static const char *IdSrc = "$Id: FGPosition.cpp,v 1.66 2004/02/26 15:03:56 jberndt Exp $";
static const char *IdHdr = ID_POSITION;

/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

extern double globalTriNormal[3];
extern double globalSceneryAltitude;
extern double globalSeaLevelRadius;

FGPosition::FGPosition(FGFDMExec* fdmex) : FGModel(fdmex)
{
  Name = "FGPosition";
  LongitudeDot = LatitudeDot = RadiusDot = 0.0;

  for (int i=0;i<4;i++) {
    LatitudeDot_prev[i]  = 0.0;
    LongitudeDot_prev[i] = 0.0;
    RadiusDot_prev[i]    = 0.0;
  }

  vVRPoffset.InitMatrix();

  Longitude = Latitude = 0.0;
  LongitudeVRP = LatitudeVRP = 0.0;
  gamma = Vt = Vground = 0.0;
  hoverbmac = hoverbcg = 0.0;
  psigt = 0.0;
  bind();
  Debug(0);
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

FGPosition::~FGPosition(void)
{
  unbind();
  Debug(1);
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

bool FGPosition::InitModel(void)
{
  FGModel::InitModel();

  h = 3.0;                                 // Est. height of aircraft cg off runway
  SeaLevelRadius = Inertial->RefRadius();  // For initialization ONLY
  Radius         = SeaLevelRadius + h;
  RunwayRadius   = SeaLevelRadius;
  DistanceAGL    = Radius - RunwayRadius;  // Geocentric
  vRunwayNormal(3) = -1.0;                 // Initialized for standalone mode
  b = 1;
  return true;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/*
Purpose: Called on a schedule to perform Positioning algorithms
Notes:   [TP] Make sure that -Vt <= hdot <= Vt, which, of course, should always
         be the case
         [JB] Run in standalone mode, SeaLevelRadius will be reference radius.
	       In FGFS, SeaLevelRadius is stuffed from FGJSBSim in JSBSim.cxx each pass.
*/

bool FGPosition::Run(void)
{
  double cosLat;
  double hdot_Vt;

  if (!FGModel::Run()) {
    GetState();

    Vground = sqrt( vVel(eNorth)*vVel(eNorth) + vVel(eEast)*vVel(eEast) );
    psigt =  atan2(vVel(eEast), vVel(eNorth));
    if (psigt < 0.0)
      psigt += 2*M_PI;

    Radius    = h + SeaLevelRadius;

    cosLat = cos(Latitude);
    if (cosLat != 0) LongitudeDot = vVel(eEast) / (Radius * cosLat);
    LatitudeDot = vVel(eNorth) / Radius;
    RadiusDot   = -vVel(eDown);

    Longitude += State->Integrate(FGState::TRAPZ, dt*rate, LongitudeDot, LongitudeDot_prev);
    Latitude  += State->Integrate(FGState::TRAPZ, dt*rate, LatitudeDot, LatitudeDot_prev);
    Radius    += State->Integrate(FGState::TRAPZ, dt*rate, RadiusDot, RadiusDot_prev);

    h = Radius - SeaLevelRadius;           // Geocentric

    vVRPoffset = State->GetTb2l() * MassBalance->StructuralToBody(Aircraft->GetXYZvrp());

    // vVRP  - the vector to the Visual Reference Point - now contains the
    // offset from the CG to the VRP, in units of feet, in the Local coordinate
    // frame, where X points north, Y points East, and Z points down. This needs
    // to be converted to Lat/Lon/Alt, now.

    if (cosLat != 0)
      LongitudeVRP = vVRPoffset(eEast) / (Radius * cosLat) + Longitude;

    LatitudeVRP = vVRPoffset(eNorth) / Radius + Latitude;
    hVRP = h - vVRPoffset(eDown);
/*
cout << "Lat/Lon/Alt : " << Latitude << " / " << Longitude << " / " << h << endl;
cout << "Lat/Lon/Alt VRP: " << LatitudeVRP << " / " << LongitudeVRP << " / " << hVRP << endl << endl;
*/
    DistanceAGL = Radius - RunwayRadius;   // Geocentric

    hoverbcg = DistanceAGL/b;

    vMac = State->GetTb2l()*MassBalance->StructuralToBody(Aircraft->GetXYZrp());
    hoverbmac = (DistanceAGL + vMac(3)) / b;

    if (Vt > 0) {
      hdot_Vt = RadiusDot/Vt;
      if (fabs(hdot_Vt) <= 1) gamma = asin(hdot_Vt);
    } else {
      gamma = 0.0;
    }

    return false;

  } else {
    return true;
  }
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGPosition::GetState(void)
{
  dt = State->Getdt();

  Vt        = Translation->GetVt();
  vVel      = State->GetTb2l() * Translation->GetUVW();
  vVelDot   = State->GetTb2l() * Translation->GetUVWdot();

  b = Aircraft->GetWingSpan();
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGPosition::Seth(double tt)
{
 h = tt;
 Radius    = h + SeaLevelRadius;
 DistanceAGL = Radius - RunwayRadius;   // Geocentric
 hoverbcg = DistanceAGL/b;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGPosition::SetDistanceAGL(double tt)
{
  DistanceAGL=tt;
  Radius = RunwayRadius + DistanceAGL;
  h = Radius - SeaLevelRadius;
  hoverbcg = DistanceAGL/b;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGPosition::bind(void)
{
  PropertyManager->Tie("velocities/v-north-fps", this,
                       &FGPosition::GetVn);
  PropertyManager->Tie("velocities/v-east-fps", this,
                       &FGPosition::GetVe);
  PropertyManager->Tie("velocities/v-down-fps", this,
                       &FGPosition::GetVd);
  PropertyManager->Tie("velocities/vg-fps", this,
                       &FGPosition::GetVground);
  PropertyManager->Tie("flight-path/psi-gt-rad", this,
                       &FGPosition::GetGroundTrack);
  PropertyManager->Tie("position/h-sl-ft", this,
                       &FGPosition::Geth,
                       &FGPosition::Seth,
                       true);
  PropertyManager->Tie("velocities/h-dot-fps", this,
                       &FGPosition::Gethdot);
  PropertyManager->Tie("position/lat-gc-rad", this,
                       &FGPosition::GetLatitude,
                       &FGPosition::SetLatitude);
  PropertyManager->Tie("position/lat-dot-gc-rad", this,
                       &FGPosition::GetLatitudeDot);
  PropertyManager->Tie("position/long-gc-rad", this,
                       &FGPosition::GetLongitude,
                       &FGPosition::SetLongitude,
                       true);
  PropertyManager->Tie("position/long-dot-gc-rad", this,
                       &FGPosition::GetLongitudeDot);
  PropertyManager->Tie("metrics/runway-radius", this,
                       &FGPosition::GetRunwayRadius,
                       &FGPosition::SetRunwayRadius);
  PropertyManager->Tie("position/h-agl-ft", this,
                       &FGPosition::GetDistanceAGL,
                       &FGPosition::SetDistanceAGL);
  PropertyManager->Tie("position/radius-to-vehicle-ft", this,
                       &FGPosition::GetRadius);
  PropertyManager->Tie("flight-path/gamma-rad", this,
                       &FGPosition::GetGamma,
                       &FGPosition::SetGamma);
  PropertyManager->Tie("aero/h_b-cg-ft", this,
                       &FGPosition::GetHOverBCG);
  PropertyManager->Tie("aero/h_b-mac-ft", this,
                       &FGPosition::GetHOverBMAC);
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGPosition::unbind(void)
{
  PropertyManager->Untie("velocities/v-north-fps");
  PropertyManager->Untie("velocities/v-east-fps");
  PropertyManager->Untie("velocities/v-down-fps");
  PropertyManager->Untie("velocities/vg-fps");
  PropertyManager->Untie("flight-path/psi-gt-rad");
  PropertyManager->Untie("position/h-sl-ft");
  PropertyManager->Untie("velocities/h-dot-fps");
  PropertyManager->Untie("position/lat-gc-rad");
  PropertyManager->Untie("position/lat-dot-gc-rad");
  PropertyManager->Untie("position/long-gc-rad");
  PropertyManager->Untie("position/long-dot-gc-rad");
  PropertyManager->Untie("metrics/runway-radius");
  PropertyManager->Untie("position/h-agl-ft");
  PropertyManager->Untie("position/radius-to-vehicle-ft");
  PropertyManager->Untie("flight-path/gamma-rad");
  PropertyManager->Untie("aero/h_b-cg-ft");
  PropertyManager->Untie("aero/h_b-mac-ft");
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//    The bitmasked value choices are as follows:
//    unset: In this case (the default) JSBSim would only print
//       out the normally expected messages, essentially echoing
//       the config files as they are read. If the environment
//       variable is not set, debug_lvl is set to 1 internally
//    0: This requests JSBSim not to output any messages
//       whatsoever.
//    1: This value explicity requests the normal JSBSim
//       startup messages
//    2: This value asks for a message to be printed out when
//       a class is instantiated
//    4: When this value is set, a message is displayed when a
//       FGModel object executes its Run() method
//    8: When this value is set, various runtime state variables
//       are printed out periodically
//    16: When set various parameters are sanity checked and
//       a message is printed out when they go out of bounds

void FGPosition::Debug(int from)
{
  if (debug_lvl <= 0) return;

  if (debug_lvl & 1) { // Standard console startup message output
    if (from == 0) { // Constructor

    }
  }
  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
    if (from == 0) cout << "Instantiated: FGPosition" << endl;
    if (from == 1) cout << "Destroyed:    FGPosition" << endl;
  }
  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
  }
  if (debug_lvl & 8 ) { // Runtime state variables
  }
  if (debug_lvl & 16) { // Sanity checking
  }
  if (debug_lvl & 64) {
    if (from == 0) { // Constructor
      cout << IdSrc << endl;
      cout << IdHdr << endl;
    }
  }
}
}
<commit_msg>Set protection for a div-by-zero.<commit_after>/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

 Module:       FGPosition.cpp
 Author:       Jon S. Berndt
 Date started: 01/05/99
 Purpose:      Integrate the EOM to determine instantaneous position
 Called by:    FGFDMExec

 ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------

 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
 Foundation; either version 2 of the License, or (at your option) any later
 version.

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 details.

 You should have received a copy of the GNU General Public License along with
 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 Place - Suite 330, Boston, MA  02111-1307, USA.

 Further information about the GNU General Public License can also be found on
 the world wide web at http://www.gnu.org.

FUNCTIONAL DESCRIPTION
--------------------------------------------------------------------------------
This class encapsulates the integration of rates and accelerations to get the
current position of the aircraft.

HISTORY
--------------------------------------------------------------------------------
01/05/99   JSB   Created

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES,  and NOTES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[1] Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling
    Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420  Naval Postgraduate
    School, January 1994
[2] D. M. Henderson, "Euler Angles, Quaternions, and Transformation Matrices",
    JSC 12960, July 1977
[3] Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
    NASA-Ames", NASA CR-2497, January 1975
[4] Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
    Wiley & Sons, 1979 ISBN 0-471-03032-5
[5] Bernard Etkin, "Dynamics of Flight, Stability and Control", Wiley & Sons,
    1982 ISBN 0-471-08936-2

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

#ifdef FGFS
#  include <simgear/compiler.h>
#  ifdef SG_HAVE_STD_INCLUDES
#    include <cmath>
#    include <iomanip>
#  else
#    include <math.h>
#    include <iomanip.h>
#  endif
#else
#  if defined(sgi) && !defined(__GNUC__)
#    include <math.h>
#    if (_COMPILER_VERSION < 740)
#      include <iomanip.h>
#    else
#      include <iomanip>
#    endif
#  else
#    include <cmath>
#    include <iomanip>
#  endif
#endif

#include "FGPosition.h"
#include "FGState.h"
#include "FGFDMExec.h"
#include "FGAircraft.h"
#include "FGMassBalance.h"
#include "FGTranslation.h"
#include "FGRotation.h"
#include "FGInertial.h"
#include "FGPropertyManager.h"

namespace JSBSim {

static const char *IdSrc = "$Id: FGPosition.cpp,v 1.67 2004/02/27 13:23:05 jberndt Exp $";
static const char *IdHdr = ID_POSITION;

/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

extern double globalTriNormal[3];
extern double globalSceneryAltitude;
extern double globalSeaLevelRadius;

FGPosition::FGPosition(FGFDMExec* fdmex) : FGModel(fdmex)
{
  Name = "FGPosition";
  LongitudeDot = LatitudeDot = RadiusDot = 0.0;

  for (int i=0;i<4;i++) {
    LatitudeDot_prev[i]  = 0.0;
    LongitudeDot_prev[i] = 0.0;
    RadiusDot_prev[i]    = 0.0;
  }

  vVRPoffset.InitMatrix();

  Longitude = Latitude = 0.0;
  LongitudeVRP = LatitudeVRP = 0.0;
  gamma = Vt = Vground = 0.0;
  hoverbmac = hoverbcg = 0.0;
  psigt = 0.0;
  bind();
  Debug(0);
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

FGPosition::~FGPosition(void)
{
  unbind();
  Debug(1);
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

bool FGPosition::InitModel(void)
{
  FGModel::InitModel();

  h = 3.0;                                 // Est. height of aircraft cg off runway
  SeaLevelRadius = Inertial->RefRadius();  // For initialization ONLY
  Radius         = SeaLevelRadius + h;
  RunwayRadius   = SeaLevelRadius;
  DistanceAGL    = Radius - RunwayRadius;  // Geocentric
  vRunwayNormal(3) = -1.0;                 // Initialized for standalone mode
  b = 1;
  return true;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/*
Purpose: Called on a schedule to perform Positioning algorithms
Notes:   [TP] Make sure that -Vt <= hdot <= Vt, which, of course, should always
         be the case
         [JB] Run in standalone mode, SeaLevelRadius will be reference radius.
               In FGFS, SeaLevelRadius is stuffed from FGJSBSim in JSBSim.cxx each pass.
*/

bool FGPosition::Run(void)
{
  double cosLat;
  double hdot_Vt;

  if (!FGModel::Run()) {
    GetState();

    Vground = sqrt( vVel(eNorth)*vVel(eNorth) + vVel(eEast)*vVel(eEast) );

    if (vVel(eNorth) == 0) psigt = 0;
    else psigt =  atan2(vVel(eEast), vVel(eNorth));

    if (psigt < 0.0) psigt += 2*M_PI;

    Radius    = h + SeaLevelRadius;

    cosLat = cos(Latitude);
    if (cosLat != 0) LongitudeDot = vVel(eEast) / (Radius * cosLat);
    LatitudeDot = vVel(eNorth) / Radius;
    RadiusDot   = -vVel(eDown);

    Longitude += State->Integrate(FGState::TRAPZ, dt*rate, LongitudeDot, LongitudeDot_prev);
    Latitude  += State->Integrate(FGState::TRAPZ, dt*rate, LatitudeDot, LatitudeDot_prev);
    Radius    += State->Integrate(FGState::TRAPZ, dt*rate, RadiusDot, RadiusDot_prev);

    h = Radius - SeaLevelRadius;           // Geocentric

    vVRPoffset = State->GetTb2l() * MassBalance->StructuralToBody(Aircraft->GetXYZvrp());

    // vVRP  - the vector to the Visual Reference Point - now contains the
    // offset from the CG to the VRP, in units of feet, in the Local coordinate
    // frame, where X points north, Y points East, and Z points down. This needs
    // to be converted to Lat/Lon/Alt, now.

    if (cosLat != 0)
      LongitudeVRP = vVRPoffset(eEast) / (Radius * cosLat) + Longitude;

    LatitudeVRP = vVRPoffset(eNorth) / Radius + Latitude;
    hVRP = h - vVRPoffset(eDown);
/*
cout << "Lat/Lon/Alt : " << Latitude << " / " << Longitude << " / " << h << endl;
cout << "Lat/Lon/Alt VRP: " << LatitudeVRP << " / " << LongitudeVRP << " / " << hVRP << endl << endl;
*/
    DistanceAGL = Radius - RunwayRadius;   // Geocentric

    hoverbcg = DistanceAGL/b;

    vMac = State->GetTb2l()*MassBalance->StructuralToBody(Aircraft->GetXYZrp());
    hoverbmac = (DistanceAGL + vMac(3)) / b;

    if (Vt > 0) {
      hdot_Vt = RadiusDot/Vt;
      if (fabs(hdot_Vt) <= 1) gamma = asin(hdot_Vt);
    } else {
      gamma = 0.0;
    }

    return false;

  } else {
    return true;
  }
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGPosition::GetState(void)
{
  dt = State->Getdt();

  Vt        = Translation->GetVt();
  vVel      = State->GetTb2l() * Translation->GetUVW();
  vVelDot   = State->GetTb2l() * Translation->GetUVWdot();

  b = Aircraft->GetWingSpan();
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGPosition::Seth(double tt)
{
 h = tt;
 Radius    = h + SeaLevelRadius;
 DistanceAGL = Radius - RunwayRadius;   // Geocentric
 hoverbcg = DistanceAGL/b;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGPosition::SetDistanceAGL(double tt)
{
  DistanceAGL=tt;
  Radius = RunwayRadius + DistanceAGL;
  h = Radius - SeaLevelRadius;
  hoverbcg = DistanceAGL/b;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGPosition::bind(void)
{
  PropertyManager->Tie("velocities/v-north-fps", this,
                       &FGPosition::GetVn);
  PropertyManager->Tie("velocities/v-east-fps", this,
                       &FGPosition::GetVe);
  PropertyManager->Tie("velocities/v-down-fps", this,
                       &FGPosition::GetVd);
  PropertyManager->Tie("velocities/vg-fps", this,
                       &FGPosition::GetVground);
  PropertyManager->Tie("flight-path/psi-gt-rad", this,
                       &FGPosition::GetGroundTrack);
  PropertyManager->Tie("position/h-sl-ft", this,
                       &FGPosition::Geth,
                       &FGPosition::Seth,
                       true);
  PropertyManager->Tie("velocities/h-dot-fps", this,
                       &FGPosition::Gethdot);
  PropertyManager->Tie("position/lat-gc-rad", this,
                       &FGPosition::GetLatitude,
                       &FGPosition::SetLatitude);
  PropertyManager->Tie("position/lat-dot-gc-rad", this,
                       &FGPosition::GetLatitudeDot);
  PropertyManager->Tie("position/long-gc-rad", this,
                       &FGPosition::GetLongitude,
                       &FGPosition::SetLongitude,
                       true);
  PropertyManager->Tie("position/long-dot-gc-rad", this,
                       &FGPosition::GetLongitudeDot);
  PropertyManager->Tie("metrics/runway-radius", this,
                       &FGPosition::GetRunwayRadius,
                       &FGPosition::SetRunwayRadius);
  PropertyManager->Tie("position/h-agl-ft", this,
                       &FGPosition::GetDistanceAGL,
                       &FGPosition::SetDistanceAGL);
  PropertyManager->Tie("position/radius-to-vehicle-ft", this,
                       &FGPosition::GetRadius);
  PropertyManager->Tie("flight-path/gamma-rad", this,
                       &FGPosition::GetGamma,
                       &FGPosition::SetGamma);
  PropertyManager->Tie("aero/h_b-cg-ft", this,
                       &FGPosition::GetHOverBCG);
  PropertyManager->Tie("aero/h_b-mac-ft", this,
                       &FGPosition::GetHOverBMAC);
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGPosition::unbind(void)
{
  PropertyManager->Untie("velocities/v-north-fps");
  PropertyManager->Untie("velocities/v-east-fps");
  PropertyManager->Untie("velocities/v-down-fps");
  PropertyManager->Untie("velocities/vg-fps");
  PropertyManager->Untie("flight-path/psi-gt-rad");
  PropertyManager->Untie("position/h-sl-ft");
  PropertyManager->Untie("velocities/h-dot-fps");
  PropertyManager->Untie("position/lat-gc-rad");
  PropertyManager->Untie("position/lat-dot-gc-rad");
  PropertyManager->Untie("position/long-gc-rad");
  PropertyManager->Untie("position/long-dot-gc-rad");
  PropertyManager->Untie("metrics/runway-radius");
  PropertyManager->Untie("position/h-agl-ft");
  PropertyManager->Untie("position/radius-to-vehicle-ft");
  PropertyManager->Untie("flight-path/gamma-rad");
  PropertyManager->Untie("aero/h_b-cg-ft");
  PropertyManager->Untie("aero/h_b-mac-ft");
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//    The bitmasked value choices are as follows:
//    unset: In this case (the default) JSBSim would only print
//       out the normally expected messages, essentially echoing
//       the config files as they are read. If the environment
//       variable is not set, debug_lvl is set to 1 internally
//    0: This requests JSBSim not to output any messages
//       whatsoever.
//    1: This value explicity requests the normal JSBSim
//       startup messages
//    2: This value asks for a message to be printed out when
//       a class is instantiated
//    4: When this value is set, a message is displayed when a
//       FGModel object executes its Run() method
//    8: When this value is set, various runtime state variables
//       are printed out periodically
//    16: When set various parameters are sanity checked and
//       a message is printed out when they go out of bounds

void FGPosition::Debug(int from)
{
  if (debug_lvl <= 0) return;

  if (debug_lvl & 1) { // Standard console startup message output
    if (from == 0) { // Constructor

    }
  }
  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
    if (from == 0) cout << "Instantiated: FGPosition" << endl;
    if (from == 1) cout << "Destroyed:    FGPosition" << endl;
  }
  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
  }
  if (debug_lvl & 8 ) { // Runtime state variables
  }
  if (debug_lvl & 16) { // Sanity checking
  }
  if (debug_lvl & 64) {
    if (from == 0) { // Constructor
      cout << IdSrc << endl;
      cout << IdHdr << endl;
    }
  }
}
}
<|endoftext|>


<commit_before>#ifndef APPLICATION_INCLUDED
#define APPLICATION_INCLUDED

#include <map>
#include "InputHandlers.hpp"
#include "renderer/OpenGL.hpp"
#include "renderer/Texture.hpp"

/*
 * main application
 */
class Application
{
public:
    Application::Application() : m_running(true)
    {
    }

    ~Application();

    void OnStart();
    void OnRender();

    inline bool Running() const  { return m_running; }
    inline void Terminate()      { m_running = false; }

    void OnKeyPress(KeyCode key);
private:
    bool m_running;

    // rendered quad data
    GLuint m_vertexBuffer;
    GLuint m_colorBuffer;
    GLuint m_texcoordBuffer;
    GLuint m_vertexArray;
    Texture *m_texture;

};

#endif
<commit_msg>removed unncessary include<commit_after>#ifndef APPLICATION_INCLUDED
#define APPLICATION_INCLUDED

#include "InputHandlers.hpp"
#include "renderer/OpenGL.hpp"
#include "renderer/Texture.hpp"

/*
 * main application
 */
class Application
{
public:
    Application::Application() : m_running(true)
    {
    }

    ~Application();

    void OnStart();
    void OnRender();

    inline bool Running() const  { return m_running; }
    inline void Terminate()      { m_running = false; }

    void OnKeyPress(KeyCode key);
private:
    bool m_running;

    // rendered quad data
    GLuint m_vertexBuffer;
    GLuint m_colorBuffer;
    GLuint m_texcoordBuffer;
    GLuint m_vertexArray;
    Texture *m_texture;

};

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2010 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/animation/bounds_animator.h"

#include "app/slide_animation.h"
#include "base/scoped_ptr.h"
#include "views/view.h"

// Duration in milliseconds for animations.
static const int kAnimationDuration = 200;

namespace views {

BoundsAnimator::BoundsAnimator(View* parent)
    : parent_(parent),
      observer_(NULL),
      container_(new AnimationContainer()) {
  container_->set_observer(this);
}

BoundsAnimator::~BoundsAnimator() {
  // Reset the delegate so that we don't attempt to notify our observer from
  // the destructor.
  container_->set_observer(NULL);

  // Delete all the animations, but don't remove any child views. We assume the
  // view owns us and is going to be deleted anyway.
  for (ViewToDataMap::iterator i = data_.begin(); i != data_.end(); ++i)
    delete i->second.animation;
}

void BoundsAnimator::AnimateViewTo(View* view,
                                   const gfx::Rect& target,
                                   bool delete_when_done) {
  DCHECK_EQ(view->GetParent(), parent_);

  scoped_ptr<Animation> current_animation;

  if (data_.find(view) != data_.end()) {
    // Currently animating this view, blow away the current animation and
    // we'll create another animation below.
    // We delay deleting the view until the end so that we don't prematurely
    // send out notification that we're done.
    current_animation.reset(ResetAnimationForView(view));
  }

  // NOTE: we don't check if the view is already at the target location. Doing
  // so leads to odd cases where no animations may be present after invoking
  // AnimateViewTo. AnimationProgressed does nothing when the bounds of the
  // view don't change.

  Data& data = data_[view];
  data.start_bounds = view->bounds();
  data.target_bounds = target;
  data.animation = CreateAnimation();
  data.delete_when_done = delete_when_done;

  animation_to_view_[data.animation] = view;

  data.animation->Show();
}

void BoundsAnimator::SetAnimationForView(View* view,
                                         SlideAnimation* animation) {
  scoped_ptr<SlideAnimation> animation_wrapper(animation);
  if (data_.find(view) == data_.end())
    return;

  // We delay deleting the animation until the end so that we don't prematurely
  // send out notification that we're done.
  scoped_ptr<Animation> old_animation(ResetAnimationForView(view));

  data_[view].animation = animation_wrapper.release();
  animation_to_view_[animation] = view;

  animation->set_delegate(this);
  animation->SetContainer(container_.get());
  animation->Show();
}

const SlideAnimation* BoundsAnimator::GetAnimationForView(View* view) {
  return data_.find(view) == data_.end() ? NULL : data_[view].animation;
}

void BoundsAnimator::SetAnimationDelegate(View* view,
                                          AnimationDelegate* delegate,
                                          bool delete_when_done) {
  DCHECK(IsAnimating(view));
  data_[view].delegate = delegate;
  data_[view].delete_delegate_when_done = delete_when_done;
}

void BoundsAnimator::StopAnimatingView(View* view) {
  if (data_.find(view) == data_.end())
    return;

  data_[view].animation->Stop();
}

bool BoundsAnimator::IsAnimating(View* view) const {
  return data_.find(view) != data_.end();
}

bool BoundsAnimator::IsAnimating() const {
  return !data_.empty();
}

void BoundsAnimator::Cancel() {
  if (data_.empty())
    return;

  while (!data_.empty())
    data_.begin()->second.animation->Stop();

  // Invoke AnimationContainerProgressed to force a repaint and notify delegate.
  AnimationContainerProgressed(container_.get());
}

SlideAnimation* BoundsAnimator::CreateAnimation() {
  SlideAnimation* animation = new SlideAnimation(this);
  animation->SetContainer(container_.get());
  animation->SetSlideDuration(kAnimationDuration);
  animation->SetTweenType(SlideAnimation::EASE_OUT);
  return animation;
}

void BoundsAnimator::RemoveFromMapsAndDelete(View* view) {
  DCHECK(data_.count(view) > 0);

  Data& data = data_[view];
  animation_to_view_.erase(data.animation);
  if (data.delete_when_done)
    delete view;
  data_.erase(view);
}

void BoundsAnimator::CleanupData(Data* data) {
  if (data->delete_delegate_when_done) {
    delete static_cast<OwnedAnimationDelegate*>(data->delegate);
    data->delegate = NULL;
  }

  delete data->animation;
  data->animation = NULL;
}

Animation* BoundsAnimator::ResetAnimationForView(View* view) {
  if (data_.find(view) == data_.end())
    return NULL;

  Animation* old_animation = data_[view].animation;
  animation_to_view_.erase(old_animation);
  data_[view].animation = NULL;
  // Reset the delegate so that we don't attempt any processing when the
  // animation calls us back.
  old_animation->set_delegate(NULL);
  return old_animation;
}

void BoundsAnimator::AnimationProgressed(const Animation* animation) {
  DCHECK(animation_to_view_.find(animation) != animation_to_view_.end());

  View* view = animation_to_view_[animation];
  const Data& data = data_[view];
  gfx::Rect new_bounds =
      animation->CurrentValueBetween(data.start_bounds, data.target_bounds);
  if (new_bounds != view->bounds()) {
    gfx::Rect total_bounds = new_bounds.Union(view->bounds());

    // Build up the region to repaint in repaint_bounds_. We'll do the repaint
    // when all animations complete (in AnimationContainerProgressed).
    if (repaint_bounds_.IsEmpty())
      repaint_bounds_ = total_bounds;
    else
      repaint_bounds_ = repaint_bounds_.Union(total_bounds);

    view->SetBounds(new_bounds);
  }

  if (data_[view].delegate)
    data_[view].delegate->AnimationProgressed(animation);
}

void BoundsAnimator::AnimationEnded(const Animation* animation) {
  View* view = animation_to_view_[animation];
  AnimationDelegate* delegate = data_[view].delegate;

  // Make a copy of the data as Remove empties out the maps.
  Data data = data_[view];

  RemoveFromMapsAndDelete(view);

  if (delegate)
    delegate->AnimationEnded(animation);

  CleanupData(&data);
}

void BoundsAnimator::AnimationCanceled(const Animation* animation) {
  View* view = animation_to_view_[animation];
  AnimationDelegate* delegate = data_[view].delegate;

  // Make a copy of the data as Remove empties out the maps.
  Data data = data_[view];

  RemoveFromMapsAndDelete(view);

  if (delegate)
    delegate->AnimationCanceled(animation);

  CleanupData(&data);
}

void BoundsAnimator::AnimationContainerProgressed(
    AnimationContainer* container) {
  if (!repaint_bounds_.IsEmpty()) {
    parent_->SchedulePaint(repaint_bounds_, false);
    repaint_bounds_.SetRect(0, 0, 0, 0);
  }

  if (observer_ && !IsAnimating()) {
    // Notify here rather than from AnimationXXX to avoid deleting the animation
    // while the animaion is calling us.
    observer_->OnBoundsAnimatorDone(this);
  }
}

void BoundsAnimator::AnimationContainerEmpty(AnimationContainer* container) {
}

}  // namespace views
<commit_msg>Fixes leak in boundsanimator.<commit_after>// Copyright (c) 2010 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/animation/bounds_animator.h"

#include "app/slide_animation.h"
#include "base/scoped_ptr.h"
#include "views/view.h"

// Duration in milliseconds for animations.
static const int kAnimationDuration = 200;

namespace views {

BoundsAnimator::BoundsAnimator(View* parent)
    : parent_(parent),
      observer_(NULL),
      container_(new AnimationContainer()) {
  container_->set_observer(this);
}

BoundsAnimator::~BoundsAnimator() {
  // Reset the delegate so that we don't attempt to notify our observer from
  // the destructor.
  container_->set_observer(NULL);

  // Delete all the animations, but don't remove any child views. We assume the
  // view owns us and is going to be deleted anyway.
  for (ViewToDataMap::iterator i = data_.begin(); i != data_.end(); ++i)
    CleanupData(&(i->second));
}

void BoundsAnimator::AnimateViewTo(View* view,
                                   const gfx::Rect& target,
                                   bool delete_when_done) {
  DCHECK_EQ(view->GetParent(), parent_);

  scoped_ptr<Animation> current_animation;

  if (data_.find(view) != data_.end()) {
    // Currently animating this view, blow away the current animation and
    // we'll create another animation below.
    // We delay deleting the view until the end so that we don't prematurely
    // send out notification that we're done.
    current_animation.reset(ResetAnimationForView(view));
  }

  // NOTE: we don't check if the view is already at the target location. Doing
  // so leads to odd cases where no animations may be present after invoking
  // AnimateViewTo. AnimationProgressed does nothing when the bounds of the
  // view don't change.

  Data& data = data_[view];
  data.start_bounds = view->bounds();
  data.target_bounds = target;
  data.animation = CreateAnimation();
  data.delete_when_done = delete_when_done;

  animation_to_view_[data.animation] = view;

  data.animation->Show();
}

void BoundsAnimator::SetAnimationForView(View* view,
                                         SlideAnimation* animation) {
  scoped_ptr<SlideAnimation> animation_wrapper(animation);
  if (data_.find(view) == data_.end())
    return;

  // We delay deleting the animation until the end so that we don't prematurely
  // send out notification that we're done.
  scoped_ptr<Animation> old_animation(ResetAnimationForView(view));

  data_[view].animation = animation_wrapper.release();
  animation_to_view_[animation] = view;

  animation->set_delegate(this);
  animation->SetContainer(container_.get());
  animation->Show();
}

const SlideAnimation* BoundsAnimator::GetAnimationForView(View* view) {
  return data_.find(view) == data_.end() ? NULL : data_[view].animation;
}

void BoundsAnimator::SetAnimationDelegate(View* view,
                                          AnimationDelegate* delegate,
                                          bool delete_when_done) {
  DCHECK(IsAnimating(view));
  data_[view].delegate = delegate;
  data_[view].delete_delegate_when_done = delete_when_done;
}

void BoundsAnimator::StopAnimatingView(View* view) {
  if (data_.find(view) == data_.end())
    return;

  data_[view].animation->Stop();
}

bool BoundsAnimator::IsAnimating(View* view) const {
  return data_.find(view) != data_.end();
}

bool BoundsAnimator::IsAnimating() const {
  return !data_.empty();
}

void BoundsAnimator::Cancel() {
  if (data_.empty())
    return;

  while (!data_.empty())
    data_.begin()->second.animation->Stop();

  // Invoke AnimationContainerProgressed to force a repaint and notify delegate.
  AnimationContainerProgressed(container_.get());
}

SlideAnimation* BoundsAnimator::CreateAnimation() {
  SlideAnimation* animation = new SlideAnimation(this);
  animation->SetContainer(container_.get());
  animation->SetSlideDuration(kAnimationDuration);
  animation->SetTweenType(SlideAnimation::EASE_OUT);
  return animation;
}

void BoundsAnimator::RemoveFromMapsAndDelete(View* view) {
  DCHECK(data_.count(view) > 0);

  Data& data = data_[view];
  animation_to_view_.erase(data.animation);
  if (data.delete_when_done)
    delete view;
  data_.erase(view);
}

void BoundsAnimator::CleanupData(Data* data) {
  if (data->delete_delegate_when_done) {
    delete static_cast<OwnedAnimationDelegate*>(data->delegate);
    data->delegate = NULL;
  }

  delete data->animation;
  data->animation = NULL;
}

Animation* BoundsAnimator::ResetAnimationForView(View* view) {
  if (data_.find(view) == data_.end())
    return NULL;

  Animation* old_animation = data_[view].animation;
  animation_to_view_.erase(old_animation);
  data_[view].animation = NULL;
  // Reset the delegate so that we don't attempt any processing when the
  // animation calls us back.
  old_animation->set_delegate(NULL);
  return old_animation;
}

void BoundsAnimator::AnimationProgressed(const Animation* animation) {
  DCHECK(animation_to_view_.find(animation) != animation_to_view_.end());

  View* view = animation_to_view_[animation];
  const Data& data = data_[view];
  gfx::Rect new_bounds =
      animation->CurrentValueBetween(data.start_bounds, data.target_bounds);
  if (new_bounds != view->bounds()) {
    gfx::Rect total_bounds = new_bounds.Union(view->bounds());

    // Build up the region to repaint in repaint_bounds_. We'll do the repaint
    // when all animations complete (in AnimationContainerProgressed).
    if (repaint_bounds_.IsEmpty())
      repaint_bounds_ = total_bounds;
    else
      repaint_bounds_ = repaint_bounds_.Union(total_bounds);

    view->SetBounds(new_bounds);
  }

  if (data_[view].delegate)
    data_[view].delegate->AnimationProgressed(animation);
}

void BoundsAnimator::AnimationEnded(const Animation* animation) {
  View* view = animation_to_view_[animation];
  AnimationDelegate* delegate = data_[view].delegate;

  // Make a copy of the data as Remove empties out the maps.
  Data data = data_[view];

  RemoveFromMapsAndDelete(view);

  if (delegate)
    delegate->AnimationEnded(animation);

  CleanupData(&data);
}

void BoundsAnimator::AnimationCanceled(const Animation* animation) {
  View* view = animation_to_view_[animation];
  AnimationDelegate* delegate = data_[view].delegate;

  // Make a copy of the data as Remove empties out the maps.
  Data data = data_[view];

  RemoveFromMapsAndDelete(view);

  if (delegate)
    delegate->AnimationCanceled(animation);

  CleanupData(&data);
}

void BoundsAnimator::AnimationContainerProgressed(
    AnimationContainer* container) {
  if (!repaint_bounds_.IsEmpty()) {
    parent_->SchedulePaint(repaint_bounds_, false);
    repaint_bounds_.SetRect(0, 0, 0, 0);
  }

  if (observer_ && !IsAnimating()) {
    // Notify here rather than from AnimationXXX to avoid deleting the animation
    // while the animaion is calling us.
    observer_->OnBoundsAnimatorDone(this);
  }
}

void BoundsAnimator::AnimationContainerEmpty(AnimationContainer* container) {
}

}  // namespace views
<|endoftext|>


<commit_before>#include <Player.h>
#include <Globals.h>

using namespace uth;

pmath::Vec2 control()
{
	pmath::Vec2 retVal;

	if (uthInput.Keyboard.IsKeyDown(Keyboard::Numpad1))
	{
		retVal.x -= 1;
		retVal.y += 1;
	}
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Numpad2) || uthInput.Keyboard.IsKeyDown(Keyboard::Down))
	{
		retVal.y += 1;
	}
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Numpad3))
	{
		retVal.x += 1;
		retVal.y += 1;
	}
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Numpad4) || uthInput.Keyboard.IsKeyDown(Keyboard::Left))
	{
		retVal.x -= 1;
	}
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Numpad6) || uthInput.Keyboard.IsKeyDown(Keyboard::Right))
	{
		retVal.x += 1;
	}
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Numpad7))
	{
		retVal.x -= 1;
		retVal.y -= 1;
	}
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Numpad8) || uthInput.Keyboard.IsKeyDown(Keyboard::Up))
	{
		retVal.y -= 1;
	}
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Numpad9))
	{
		retVal.y -= 1;
		retVal.x += 1;
	}
	if (retVal != pmath::Vec2())
		return retVal.normalize();
	return retVal;
}

Player::Player(Object* map)
	: GameObject("Player"),
	m_map(map)
{
	AddChild(m_topShadow = new GameObject());
	m_topShadow->AddTags({ "Player", "Shadow" });
	m_topShadow->AddComponent(new Sprite("TopBottom.png"));

	AddChild(m_top = new GameObject());
	m_top->AddTags({ "Player", "Base" });
	m_top->AddComponent(new Sprite("TopTop.png"));

	AddChild(m_tip = new GameObject());
	m_tip->AddTags({ "Player", "Tip" });
	m_tip->AddComponent(new Sprite("PlayerTip.png"));

	Globals::SCORE = 0;
}

void Player::update(float dt)
{
	static int movementType = 1;

	setDifficulty();

	//Globals::DIFFICULTY += 0.1f * dt;

	Transform& tipT = m_tip->transform;

	if (uthInput.Keyboard.IsKeyDown(Keyboard::Key1))
		Globals::DIFFICULTY = 1;
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Key2))
		Globals::DIFFICULTY = 2;
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Key3))
		Globals::DIFFICULTY = 3;
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Key4))
		Globals::DIFFICULTY = 4;
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Key5))
		Globals::DIFFICULTY = 5;
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Key6))
		Globals::DIFFICULTY = 6;
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Key7))
		Globals::DIFFICULTY = 7;
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Key8))
		Globals::DIFFICULTY = 8;
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Key9))
		Globals::DIFFICULTY = 9;
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Key0))
	{
		Globals::DIFFICULTY = 0;

		setDifficulty();

		PlayerPos = pmath::Vec2();
		tipT.SetPosition(pmath::Vec2());
		m_top->transform.SetPosition(pmath::Vec2());

		Globals::PLAYER_POS = pmath::Vec2();
	}

	const pmath::Vec2 tipPos = tipT.GetPosition();

	tipT.Move(pmath::Mat2::createRotation(180) * control() * dt * 80);

	// Making tip make random movement, more the further it is from base
	tipT.Move(
		(tipPos/15 + uth::Randomizer::InsideCircle(
			(450 + pow(tipPos.length(), 1.8f)) / 5))
		* m_tipRandomMovementMultiplier * dt);

	// Move Player
	PlayerPos += pmath::Mat2::createRotation(90)
		* tipT.GetPosition()
		* (m_speed + pow(tipT.GetPosition().length(), 0.7)) * dt * m_speedMultiplier;

	// Keep spinning
	const float SpinAmount = (1 + pow(tipT.GetPosition().lengthSquared(), m_spinPow))
		* dt * m_spinMultiplier;

	tipT.SetPosition(pmath::Mat2::createRotation(SpinAmount) * tipT.GetPosition());

	m_top->transform.Rotate(SpinAmount)

	// Keep tip in rational range
	if (tipT.GetPosition().lengthSquared() > 12000)
		tipT.SetPosition(tipT.GetPosition().normalized() * 109);

	// Keep top in opposite direction of tip
	m_baseTargetPos = -tipT.GetPosition();
	m_top->transform.Move((m_baseTargetPos - m_top->transform.GetPosition()) * dt * 3);
	m_topShadow->transform.SetPosition(m_top->transform.GetPosition() * 0.90);

	//float rotation = dt * (tipPos.length() + 100);
	//m_map->transform.Rotate(rotation);
	//tipT.SetPosition(pmath::Mat2::createRotation(-rotation) * tipT.GetPosition());

	Globals::PLAYER_POS = PlayerPos;
	Globals::PLAYER_TIP = PlayerPos + tipT.GetPosition();

	m_map->transform.SetOrigin(Globals::PLAYER_POS);
}

void Player::setDifficulty()
{
	const float dif = Globals::DIFFICULTY;
	const float difSqrt = sqrt(dif);

	m_tipRandomMovementMultiplier = 1;
	m_spinMultiplier = 9;
	m_spinPow = 0.45f;
	m_speed = 3;
	m_speedMultiplier = 0.5;

	m_tipRandomMovementMultiplier += difSqrt * 0.01f;
	m_spinMultiplier += difSqrt * sin(dif) * 0.01;
	m_spinPow += difSqrt * 0.01f;
	m_speed += difSqrt * 0.1;
	m_speedMultiplier += 0.05 * difSqrt;

}
<commit_msg>Fixed one missing semicolon<commit_after>#include <Player.h>
#include <Globals.h>

using namespace uth;

pmath::Vec2 control()
{
	pmath::Vec2 retVal;

	if (uthInput.Keyboard.IsKeyDown(Keyboard::Numpad1))
	{
		retVal.x -= 1;
		retVal.y += 1;
	}
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Numpad2) || uthInput.Keyboard.IsKeyDown(Keyboard::Down))
	{
		retVal.y += 1;
	}
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Numpad3))
	{
		retVal.x += 1;
		retVal.y += 1;
	}
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Numpad4) || uthInput.Keyboard.IsKeyDown(Keyboard::Left))
	{
		retVal.x -= 1;
	}
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Numpad6) || uthInput.Keyboard.IsKeyDown(Keyboard::Right))
	{
		retVal.x += 1;
	}
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Numpad7))
	{
		retVal.x -= 1;
		retVal.y -= 1;
	}
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Numpad8) || uthInput.Keyboard.IsKeyDown(Keyboard::Up))
	{
		retVal.y -= 1;
	}
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Numpad9))
	{
		retVal.y -= 1;
		retVal.x += 1;
	}
	if (retVal != pmath::Vec2())
		return retVal.normalize();
	return retVal;
}

Player::Player(Object* map)
	: GameObject("Player"),
	m_map(map)
{
	AddChild(m_topShadow = new GameObject());
	m_topShadow->AddTags({ "Player", "Shadow" });
	m_topShadow->AddComponent(new Sprite("TopBottom.png"));

	AddChild(m_top = new GameObject());
	m_top->AddTags({ "Player", "Base" });
	m_top->AddComponent(new Sprite("TopTop.png"));

	AddChild(m_tip = new GameObject());
	m_tip->AddTags({ "Player", "Tip" });
	m_tip->AddComponent(new Sprite("PlayerTip.png"));

	Globals::SCORE = 0;
}

void Player::update(float dt)
{
	static int movementType = 1;

	setDifficulty();

	//Globals::DIFFICULTY += 0.1f * dt;

	Transform& tipT = m_tip->transform;

	if (uthInput.Keyboard.IsKeyDown(Keyboard::Key1))
		Globals::DIFFICULTY = 1;
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Key2))
		Globals::DIFFICULTY = 2;
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Key3))
		Globals::DIFFICULTY = 3;
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Key4))
		Globals::DIFFICULTY = 4;
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Key5))
		Globals::DIFFICULTY = 5;
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Key6))
		Globals::DIFFICULTY = 6;
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Key7))
		Globals::DIFFICULTY = 7;
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Key8))
		Globals::DIFFICULTY = 8;
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Key9))
		Globals::DIFFICULTY = 9;
	if (uthInput.Keyboard.IsKeyDown(Keyboard::Key0))
	{
		Globals::DIFFICULTY = 0;

		setDifficulty();

		PlayerPos = pmath::Vec2();
		tipT.SetPosition(pmath::Vec2());
		m_top->transform.SetPosition(pmath::Vec2());

		Globals::PLAYER_POS = pmath::Vec2();
	}

	const pmath::Vec2 tipPos = tipT.GetPosition();

	tipT.Move(pmath::Mat2::createRotation(180) * control() * dt * 80);

	// Making tip make random movement, more the further it is from base
	tipT.Move(
		(tipPos/15 + uth::Randomizer::InsideCircle(
			(450 + pow(tipPos.length(), 1.8f)) / 5))
		* m_tipRandomMovementMultiplier * dt);

	// Move Player
	PlayerPos += pmath::Mat2::createRotation(90)
		* tipT.GetPosition()
		* (m_speed + pow(tipT.GetPosition().length(), 0.7)) * dt * m_speedMultiplier;

	// Keep spinning
	const float SpinAmount = (1 + pow(tipT.GetPosition().lengthSquared(), m_spinPow))
		* dt * m_spinMultiplier;

	tipT.SetPosition(pmath::Mat2::createRotation(SpinAmount) * tipT.GetPosition());

	m_top->transform.Rotate(SpinAmount);

	// Keep tip in rational range
	if (tipT.GetPosition().lengthSquared() > 12000)
		tipT.SetPosition(tipT.GetPosition().normalized() * 109);

	// Keep top in opposite direction of tip
	m_baseTargetPos = -tipT.GetPosition();
	m_top->transform.Move((m_baseTargetPos - m_top->transform.GetPosition()) * dt * 3);
	m_topShadow->transform.SetPosition(m_top->transform.GetPosition() * 0.90);

	//float rotation = dt * (tipPos.length() + 100);
	//m_map->transform.Rotate(rotation);
	//tipT.SetPosition(pmath::Mat2::createRotation(-rotation) * tipT.GetPosition());

	Globals::PLAYER_POS = PlayerPos;
	Globals::PLAYER_TIP = PlayerPos + tipT.GetPosition();

	m_map->transform.SetOrigin(Globals::PLAYER_POS);
}

void Player::setDifficulty()
{
	const float dif = Globals::DIFFICULTY;
	const float difSqrt = sqrt(dif);

	m_tipRandomMovementMultiplier = 1;
	m_spinMultiplier = 9;
	m_spinPow = 0.45f;
	m_speed = 3;
	m_speedMultiplier = 0.5;

	m_tipRandomMovementMultiplier += difSqrt * 0.01f;
	m_spinMultiplier += difSqrt * sin(dif) * 0.01;
	m_spinPow += difSqrt * 0.01f;
	m_speed += difSqrt * 0.1;
	m_speedMultiplier += 0.05 * difSqrt;

}
<|endoftext|>


<commit_before>#include <array>
#include <vector>
#include <iostream>
#include <random>
#include <SFML/Graphics.hpp>
#include <noise/noise.h>

#include "force.h"
#include "particle.h"

#include "util.h"

using namespace noise;

constexpr int cell_size = 5;

namespace util {
    double map(double val, double from_min, double from_max, double to_min, double to_max)
    {
        double from_range, to_range;
        from_range = from_max - from_min;
        to_range = to_max - to_min;
        double new_val = (((val - from_min) * to_range) / from_range) + to_min;
        if (new_val > to_max)
            return to_max;
        if (new_val < to_min)
            return to_min;
        return new_val;
    }

    sf::Color avgColor(std::array<sf::Color, cell_size*cell_size> pixels)
    {
        unsigned int red = 0, blue = 0, green = 0;
        for (const auto& c : pixels)
        {
            red += c.r;
            green += c.g;
            blue += c.b;
        }
        sf::Color avg(red/pixels.size(), green/pixels.size(), blue/pixels.size());

        return avg;
    }
}

int main()
{
    // These values are used to compute perlin noise
    double xn = 0, yn = 0, zn = 0;
    const double xoffset = 0.05;
    const double yoffset = 0.05;
    //const double zoffset = 0.001;
    const double zoffset = 0.01;

    // Window size
    constexpr int width = 1280;
    constexpr int height = 840;

    constexpr int num_particles = 10000;

    constexpr float flow_strength = 3.f;

    const int cols = width / cell_size;
    const int rows = height / cell_size;

    // Random number generator setup
    std::random_device rd;
    std::default_random_engine gen(rd());
    // distributions for random x and y coordinates
    std::uniform_int_distribution<int> rand_x(0, width-1);
    std::uniform_int_distribution<int> rand_y(0, height-1);
    // distribution for random hue values
    std::uniform_real_distribution<float> rand_h(0.f, 360.f);

    // Setup noise generator
    module::Perlin noise;
    noise.SetSeed(rand_y(gen));

    // Create and initialize the force vectors on a grid layout
    std::vector< std::vector<Force> > forces(rows, std::vector<Force> (cols, Force()));
    std::vector< std::vector<sf::Color> > colours(rows, std::vector<sf::Color> (cols, sf::Color()));

    const std::string img_name = "KRL-LIZARD-2.png";
    sf::Image img;
    img.loadFromFile(img_name);

    for (unsigned int y = 0; y < rows; y++)
    {
        for (unsigned int x = 0; x < cols; x++)
        {
            forces[y][x].setPosition(x * cell_size, y * cell_size);
            forces[y][x].setMagnitude(cell_size);
            forces[y][x].setAngle(0.f);

            std::array<sf::Color, cell_size*cell_size> pixels;
            int a = 0;
            for (unsigned int j = y*cell_size; j < (y+1)*cell_size; j++)
            {
                for (unsigned int i = x*cell_size; i < (x+1)*cell_size; i++)
                {
                    pixels[a] = img.getPixel(i, j);
                    a++;
                }
            }
            colours[y][x] = util::avgColor(pixels);
        }
    }

    // Create and initialize the particles
    Particle particles[num_particles];
    for (int i = 0; i < num_particles; i++)
    {
        particles[i].current.position = sf::Vector2f(rand_x(gen), rand_y(gen));

        float r,g,b,h,s = 1,v = 1;
        h = rand_h(gen);
        HSVtoRGB(r, g, b, h, s, v);

        // Random color for each line (with alpha)
        //particles[i].current.color = sf::Color(r*255, g*255, b*255, 10);

        // All black with alpha
        particles[i].current.color = sf::Color::Black;
        particles[i].current.color.a = 10;
    }

    sf::RenderWindow window(sf::VideoMode(width, height), "Perlin", sf::Style::Close);
    window.setFramerateLimit(60);

    window.clear(sf::Color::White);

    sf::Clock clock;
    sf::Time time;
    int frames = 0;

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        //window.clear();

        yn = 0;
        for (unsigned int y = 0; y < rows; y++)
        {
            xn = 0;
            for (unsigned int x = 0; x < cols; x++)
            {
                double n = noise.GetValue(xn, yn, zn);
                float dir = util::map(n, -1, 1, 0, 360);

                forces[y][x].setAngle(dir);
                //forces[y][x].draw(window);

                xn += xoffset;
            }
            yn += yoffset;
        }

        for (int i = 0; i < num_particles; i++)
        {
            Particle *p = &particles[i];
            int gx, gy;
            gx = p->current.position.x / cell_size;
            gy = p->current.position.y / cell_size;
            p->current.color = colours[gy][gx];
            p->current.color.a = 5;
            p->acceleration = forces[gy][gx].getVector() / (float)cell_size * flow_strength;
            p->update(window);
            p->draw(window);
        }

        window.display();
        zn += zoffset;

        // Calculate FPS
        frames += 1;
        time += clock.restart();
        if (time.asSeconds() > 1)
        {
            std::cout << 1.f / time.asSeconds() * frames << std::endl;
            time = sf::Time();
            frames = 0;
        }

    }
}
<commit_msg>Made some minor modifications to parameters that gives a better effect.<commit_after>#include <array>
#include <vector>
#include <iostream>
#include <random>
#include <SFML/Graphics.hpp>
#include <noise/noise.h>

#include "force.h"
#include "particle.h"

#include "util.h"

using namespace noise;

constexpr int cell_size = 5;

namespace util {
    double map(double val, double from_min, double from_max, double to_min, double to_max)
    {
        double from_range, to_range;
        from_range = from_max - from_min;
        to_range = to_max - to_min;
        double new_val = (((val - from_min) * to_range) / from_range) + to_min;
        if (new_val > to_max)
            return to_max;
        if (new_val < to_min)
            return to_min;
        return new_val;
    }

    sf::Color avgColor(std::array<sf::Color, cell_size*cell_size> pixels)
    {
        unsigned int red = 0, blue = 0, green = 0;
        for (const auto& c : pixels)
        {
            red += c.r;
            green += c.g;
            blue += c.b;
        }
        sf::Color avg(red/pixels.size(), green/pixels.size(), blue/pixels.size());

        return avg;
    }
}

int main()
{
    // These values are used to compute perlin noise
    double xn = 0, yn = 0, zn = 0;

    // Some good defaults w/ cell size 10  and flow_strength 3.f
    /*const double xoffset = 0.05;
    const double yoffset = 0.05;
    const double zoffset = 0.01;*/

    const double xoffset = 0.01;
    const double yoffset = 0.01;
    const double zoffset = 0.01;

    // Window size
    constexpr int width = 1280;
    constexpr int height = 840;

    constexpr int num_particles = 10000;
    constexpr int alpha = 10;
    constexpr float flow_strength = 3.f;

    const int cols = width / cell_size;
    const int rows = height / cell_size;

    // Random number generator setup
    std::random_device rd;
    std::default_random_engine gen(rd());
    // distributions for random x and y coordinates
    std::uniform_int_distribution<int> rand_x(0, width-1);
    std::uniform_int_distribution<int> rand_y(0, height-1);
    // distribution for random hue values
    std::uniform_real_distribution<float> rand_h(0.f, 360.f);

    // Setup noise generator
    module::Perlin noise;
    noise.SetSeed(rand_y(gen));

    // Create and initialize the force vectors on a grid layout
    std::vector< std::vector<Force> > forces(rows, std::vector<Force> (cols, Force()));
    std::vector< std::vector<sf::Color> > colours(rows, std::vector<sf::Color> (cols, sf::Color()));

    const std::string img_name = "KRL-LIZARD-2.png";
    sf::Image img;
    img.loadFromFile(img_name);

    for (unsigned int y = 0; y < rows; y++)
    {
        for (unsigned int x = 0; x < cols; x++)
        {
            forces[y][x].setPosition(x * cell_size, y * cell_size);
            forces[y][x].setMagnitude(cell_size);
            forces[y][x].setAngle(0.f);

            std::array<sf::Color, cell_size*cell_size> pixels;
            int a = 0;
            for (unsigned int j = y*cell_size; j < (y+1)*cell_size; j++)
            {
                for (unsigned int i = x*cell_size; i < (x+1)*cell_size; i++)
                {
                    pixels[a] = img.getPixel(i, j);
                    a++;
                }
            }
            colours[y][x] = util::avgColor(pixels);
        }
    }

    // Create and initialize the particles
    Particle particles[num_particles];
    for (int i = 0; i < num_particles; i++)
    {
        particles[i].current.position = sf::Vector2f(rand_x(gen), rand_y(gen));

        float r,g,b,h,s = 1,v = 1;
        h = rand_h(gen);
        HSVtoRGB(r, g, b, h, s, v);

        // Random color for each line (with alpha)
        //particles[i].current.color = sf::Color(r*255, g*255, b*255, 10);

        // All black with alpha
        particles[i].current.color = sf::Color::Black;
        particles[i].current.color.a = alpha;
    }

    sf::RenderWindow window(sf::VideoMode(width, height), "Perlin", sf::Style::Close);
    window.setFramerateLimit(60);

    window.clear(sf::Color::Black);

    sf::Clock clock;
    sf::Time time;
    int frames = 0;

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        //window.clear();

        yn = 0;
        for (unsigned int y = 0; y < rows; y++)
        {
            xn = 0;
            for (unsigned int x = 0; x < cols; x++)
            {
                double n = noise.GetValue(xn, yn, zn);
                float dir = util::map(n, -1, 1, 0, 270);

                forces[y][x].setAngle(dir);
                //forces[y][x].draw(window);

                xn += xoffset;
            }
            yn += yoffset;
        }

        for (int i = 0; i < num_particles; i++)
        {
            Particle *p = &particles[i];
            int gx, gy;
            gx = p->current.position.x / cell_size;
            gy = p->current.position.y / cell_size;
            p->current.color = colours[gy][gx];
            p->current.color.a = 5;
            p->acceleration = forces[gy][gx].getVector() / (float)cell_size * flow_strength;
            p->update(window);
            p->draw(window);
        }

        window.display();
        zn += zoffset;

        // Calculate FPS
        frames += 1;
        time += clock.restart();
        if (time.asSeconds() > 1)
        {
            std::cout << 1.f / time.asSeconds() * frames << std::endl;
            time = sf::Time();
            frames = 0;
        }

    }
}
<|endoftext|>


<commit_before><commit_msg>fix update of TPC track parameters after propagation through ITS material: we should update the TPCInner param which are defined at the vertex and leave the Inner param (defined at inner end of TPC) unchanged<commit_after><|endoftext|>


<commit_before>#include "StdAfx.h"
#include "CheckButton.h"

CDuiCheckButton::CDuiCheckButton(HWND hWnd, CDuiObject* pDuiObject)
						   : CControlBaseFont(hWnd, pDuiObject)
{
	m_bTabStop = TRUE;	// Ӧtab
	m_bIsFocus = FALSE;
	m_bShowFocus = TRUE;
	m_enButtonState = enBSNormal;
	m_pImage = NULL;
	m_bDown = false;
	m_bMouseDown = false;
	m_uVAlignment = VAlign_Middle;
	m_clrText = Color(254, 0, 0, 0);
	SetBitmapCount(6);
}

CDuiCheckButton::CDuiCheckButton(HWND hWnd, CDuiObject* pDuiObject, UINT uControlID, CRect rc, CString strTitle/*= TEXT("")*/, BOOL bIsVisible/* = TRUE*/,
						   BOOL bIsDisable/* = FALSE*/ ,BOOL bIsPressDown/* = FALSE*/)
						   : CControlBaseFont(hWnd, pDuiObject, uControlID, rc, strTitle, bIsVisible, bIsDisable)
{
	m_bTabStop = TRUE;	// Ӧtab
	m_bIsFocus = FALSE;
	m_bShowFocus = TRUE;
	m_enButtonState = enBSNormal;
	m_pImage = NULL;
	m_bDown = false;
	m_bMouseDown = false;
	m_uVAlignment = VAlign_Middle;
	m_clrText = Color(254, 0, 0, 0);
	SetBitmapCount(6);
}

CDuiCheckButton::~CDuiCheckButton(void)
{
}

BOOL CDuiCheckButton::GetCheck()
{
	return m_bDown;
}

BOOL CDuiCheckButton::SetCheck(BOOL bCheck)
{
	if (m_bIsDisable)
	{
		return m_bDown;
	}

	BOOL bDown = m_bDown;
	m_bDown = bCheck;
	if(m_bDown)
	{
		m_enButtonState = enBSDown;
	}
	else
	{
		 m_enButtonState = enBSNormal;
	}
	if(m_bDown != bDown)
	{
		UpdateControl();
	}
	return m_bDown;
}

// XMLcheck
HRESULT CDuiCheckButton::OnAttributeCheck(const CString& strValue, BOOL bLoading)
{
	if (strValue.IsEmpty()) return E_FAIL;

	BOOL bCheck = (strValue == "true");
	SetCheck(bCheck);

	return bLoading?S_FALSE:S_OK;
}

// ÿؼĽ
BOOL CDuiCheckButton::SetControlFocus(BOOL bFocus)
{
	__super::SetControlFocus(bFocus);

	if(!GetVisible() || GetDisable())
	{
		return FALSE;
	}

	m_bIsFocus = bFocus;
	UpdateControl(true);

	return TRUE;
}

BOOL CDuiCheckButton::OnControlMouseMove(UINT nFlags, CPoint point)
{
	enumButtonState buttonState = m_enButtonState;
	if (!m_bIsDisable && !m_bMouseDown)
	{
		if(m_rc.PtInRect(point))
		{
			if(m_bDown)
			{
				m_enButtonState = enBSHoverDown;
			}
			else
			{
				m_enButtonState = enBSHover;
			}
		}
		else
		{
			if(m_bDown)
			{
				m_enButtonState = enBSDown;
			}
			else
			{
				m_enButtonState = enBSNormal;
			}
		}
	}

	if(buttonState != m_enButtonState)
	{
		UpdateControl();
		return true;
	}
	return false;
}

BOOL CDuiCheckButton::OnControlLButtonDown(UINT nFlags, CPoint point)
{
	enumButtonState buttonState = m_enButtonState;
	if (!m_bIsDisable)
	{
		if(m_rc.PtInRect(point))
		{
			m_bMouseDown = true;
			if(m_bDown)
			{
				m_enButtonState = enBSHoverDown;
				// Ϊǰڼ״̬
				m_bIsFocus = TRUE;
			}
			else
			{
				m_enButtonState = enBSHover;
			}
		}
	}

	if(buttonState != m_enButtonState)
	{
		UpdateControl();
		return true;
	}
	return false;
}

BOOL CDuiCheckButton::OnControlLButtonUp(UINT nFlags, CPoint point)
{
	enumButtonState buttonState = m_enButtonState;
	if (!m_bIsDisable)
	{
		if(m_rc.PtInRect(point))
		{
			if(m_bMouseDown)
			{
				m_bDown = !m_bDown;
				SendMessage(MSG_BUTTON_UP, 0, 0);
			}
			if(m_bDown)
			{
				m_enButtonState = enBSHoverDown;
			}
			else
			{
				m_enButtonState = enBSHover;
			}
		}
		else
		{
			if(m_bDown)
			{
				m_enButtonState = enBSDown;
			}
			else
			{
				m_enButtonState = enBSNormal;
			}
		}
	}
	m_bMouseDown = false;

	if(buttonState != m_enButtonState)
	{
		UpdateControl();
		return true;
	}
	return false;
}

// ¼
BOOL CDuiCheckButton::OnControlKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	// ݼ
	if((m_nShortcutKey != 0) && (nChar == m_nShortcutKey) && (nFlags == m_nShortcutFlag))
	{
		SetCheck(!GetCheck());
		SendMessage(MSG_BUTTON_CHECK, 0, GetCheck());
		return true;
	}

	// ǰڽ״̬,ÿոлcheck
	if(m_bIsFocus && (nChar == VK_SPACE) && (nFlags == 0))
	{
		SetCheck(!GetCheck());
		SendMessage(MSG_BUTTON_CHECK, 0, GetCheck());
		return true;
	}

	return false;
}

void CDuiCheckButton::SetControlDisable(BOOL bIsDisable)
{
	if(m_bIsDisable != bIsDisable)
	{
		m_bIsDisable = bIsDisable;
		if(bIsDisable)
		{
			if(m_bDown)
			{
				m_enButtonState = enBSDisableDown;
			}
			else
			{
				m_enButtonState = enBSDisable;
			}
		}
		else
		{
			if(m_bDown)
			{
				m_enButtonState = enBSDown;
			}
			else
			{
				m_enButtonState = enBSNormal;
			}
		}
		::InvalidateRect(m_hWnd, &m_rc, true);
	}
}

void CDuiCheckButton::DrawControl(CDC &dc, CRect rcUpdate)
{
	int nWidth = m_rc.Width();
	int nHeight = m_rc.Height();

	if(!m_bUpdate)
	{
		UpdateMemDC(dc, nWidth * 6, nHeight);

		Graphics graphics(m_memDC);
		CRect  rcTemp(0, 0, nWidth, nHeight);

		for(int i = 0; i < 6; i++)
		{
			m_memDC.BitBlt(i * nWidth, 0, nWidth, nHeight, &dc, m_rc.left ,m_rc.top, SRCCOPY);

			graphics.DrawImage(m_pImage, Rect(rcTemp.left, rcTemp.top + (nHeight - m_sizeImage.cy) / 2,   m_sizeImage.cx, m_sizeImage.cy),
				i * m_sizeImage.cx, 0, m_sizeImage.cx, m_sizeImage.cy, UnitPixel);

			rcTemp.OffsetRect(nWidth, 0);
		}

		if(!m_strTitle.IsEmpty())
		{
			m_memDC.SetBkMode(TRANSPARENT);

			rcTemp.SetRect(0, 0, nWidth, nHeight);

			BSTR bsFont = m_strFont.AllocSysString();
			FontFamily fontFamily(bsFont);
			Font font(&fontFamily, (REAL)m_nFontWidth, m_fontStyle, UnitPixel);
			graphics.SetTextRenderingHint( TextRenderingHintClearTypeGridFit );
			::SysFreeString(bsFont);

			StringFormat strFormat;
			strFormat.SetAlignment(StringAlignmentNear);
			strFormat.SetFormatFlags( StringFormatFlagsNoWrap | StringFormatFlagsMeasureTrailingSpaces);
			Size size = GetTextBounds(font, strFormat, m_strTitle);
			CPoint point = GetOriginPoint(nWidth - m_sizeImage.cx - 3, nHeight, size.Width, size.Height,
							GetGDIAlignment(m_uAlignment), GetGDIVAlignment(m_uVAlignment));

			for(int i = 0; i < 6; i++)
			{
				SolidBrush solidBrush(enBSDisable == i ? Color(128, 128, 128) : m_clrText);

				RectF rect((Gdiplus::REAL)(m_sizeImage.cx + 3 + point.x + i * nWidth), (Gdiplus::REAL)point.y, (Gdiplus::REAL)(nWidth - m_sizeImage.cx - 3 - point.x), (Gdiplus::REAL)size.Height);
				BSTR bsTitle = m_strTitle.AllocSysString();
				graphics.DrawString(bsTitle, (INT)wcslen(bsTitle), &font, rect, &strFormat, &solidBrush);
				::SysFreeString(bsTitle);

				// (߿)
				if(m_bIsFocus && m_bShowFocus)
				{
					Pen pen(Color(128, 128, 128), 1);
					pen.SetDashStyle(DashStyleDot);
					RectF rectFocus((Gdiplus::REAL)(point.x + i * nWidth), (Gdiplus::REAL)point.y, (Gdiplus::REAL)(m_sizeImage.cx + 6 + size.Width), (Gdiplus::REAL)size.Height);
					graphics.DrawRectangle(&pen, rectFocus);
				}
			}
		}
	}

	dc.BitBlt(m_rc.left,m_rc.top, m_rc.Width(), m_rc.Height(), &m_memDC, m_enButtonState * nWidth, 0, SRCCOPY);
}<commit_msg>检查框控件的图片增加DPI适配。<commit_after>#include "StdAfx.h"
#include "CheckButton.h"

CDuiCheckButton::CDuiCheckButton(HWND hWnd, CDuiObject* pDuiObject)
						   : CControlBaseFont(hWnd, pDuiObject)
{
	m_bTabStop = TRUE;	// Ӧtab
	m_bIsFocus = FALSE;
	m_bShowFocus = TRUE;
	m_enButtonState = enBSNormal;
	m_pImage = NULL;
	m_bDown = false;
	m_bMouseDown = false;
	m_uVAlignment = VAlign_Middle;
	m_clrText = Color(254, 0, 0, 0);
	SetBitmapCount(6);
}

CDuiCheckButton::CDuiCheckButton(HWND hWnd, CDuiObject* pDuiObject, UINT uControlID, CRect rc, CString strTitle/*= TEXT("")*/, BOOL bIsVisible/* = TRUE*/,
						   BOOL bIsDisable/* = FALSE*/ ,BOOL bIsPressDown/* = FALSE*/)
						   : CControlBaseFont(hWnd, pDuiObject, uControlID, rc, strTitle, bIsVisible, bIsDisable)
{
	m_bTabStop = TRUE;	// Ӧtab
	m_bIsFocus = FALSE;
	m_bShowFocus = TRUE;
	m_enButtonState = enBSNormal;
	m_pImage = NULL;
	m_bDown = false;
	m_bMouseDown = false;
	m_uVAlignment = VAlign_Middle;
	m_clrText = Color(254, 0, 0, 0);
	SetBitmapCount(6);
}

CDuiCheckButton::~CDuiCheckButton(void)
{
}

BOOL CDuiCheckButton::GetCheck()
{
	return m_bDown;
}

BOOL CDuiCheckButton::SetCheck(BOOL bCheck)
{
	if (m_bIsDisable)
	{
		return m_bDown;
	}

	BOOL bDown = m_bDown;
	m_bDown = bCheck;
	if(m_bDown)
	{
		m_enButtonState = enBSDown;
	}
	else
	{
		 m_enButtonState = enBSNormal;
	}
	if(m_bDown != bDown)
	{
		UpdateControl();
	}
	return m_bDown;
}

// XMLcheck
HRESULT CDuiCheckButton::OnAttributeCheck(const CString& strValue, BOOL bLoading)
{
	if (strValue.IsEmpty()) return E_FAIL;

	BOOL bCheck = (strValue == "true");
	SetCheck(bCheck);

	return bLoading?S_FALSE:S_OK;
}

// ÿؼĽ
BOOL CDuiCheckButton::SetControlFocus(BOOL bFocus)
{
	__super::SetControlFocus(bFocus);

	if(!GetVisible() || GetDisable())
	{
		return FALSE;
	}

	m_bIsFocus = bFocus;
	UpdateControl(true);

	return TRUE;
}

BOOL CDuiCheckButton::OnControlMouseMove(UINT nFlags, CPoint point)
{
	enumButtonState buttonState = m_enButtonState;
	if (!m_bIsDisable && !m_bMouseDown)
	{
		if(m_rc.PtInRect(point))
		{
			if(m_bDown)
			{
				m_enButtonState = enBSHoverDown;
			}
			else
			{
				m_enButtonState = enBSHover;
			}
		}
		else
		{
			if(m_bDown)
			{
				m_enButtonState = enBSDown;
			}
			else
			{
				m_enButtonState = enBSNormal;
			}
		}
	}

	if(buttonState != m_enButtonState)
	{
		UpdateControl();
		return true;
	}
	return false;
}

BOOL CDuiCheckButton::OnControlLButtonDown(UINT nFlags, CPoint point)
{
	enumButtonState buttonState = m_enButtonState;
	if (!m_bIsDisable)
	{
		if(m_rc.PtInRect(point))
		{
			m_bMouseDown = true;
			if(m_bDown)
			{
				m_enButtonState = enBSHoverDown;
				// Ϊǰڼ״̬
				m_bIsFocus = TRUE;
			}
			else
			{
				m_enButtonState = enBSHover;
			}
		}
	}

	if(buttonState != m_enButtonState)
	{
		UpdateControl();
		return true;
	}
	return false;
}

BOOL CDuiCheckButton::OnControlLButtonUp(UINT nFlags, CPoint point)
{
	enumButtonState buttonState = m_enButtonState;
	if (!m_bIsDisable)
	{
		if(m_rc.PtInRect(point))
		{
			if(m_bMouseDown)
			{
				m_bDown = !m_bDown;
				SendMessage(MSG_BUTTON_UP, 0, 0);
			}
			if(m_bDown)
			{
				m_enButtonState = enBSHoverDown;
			}
			else
			{
				m_enButtonState = enBSHover;
			}
		}
		else
		{
			if(m_bDown)
			{
				m_enButtonState = enBSDown;
			}
			else
			{
				m_enButtonState = enBSNormal;
			}
		}
	}
	m_bMouseDown = false;

	if(buttonState != m_enButtonState)
	{
		UpdateControl();
		return true;
	}
	return false;
}

// ¼
BOOL CDuiCheckButton::OnControlKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	// ݼ
	if((m_nShortcutKey != 0) && (nChar == m_nShortcutKey) && (nFlags == m_nShortcutFlag))
	{
		SetCheck(!GetCheck());
		SendMessage(MSG_BUTTON_CHECK, 0, GetCheck());
		return true;
	}

	// ǰڽ״̬,ÿոлcheck
	if(m_bIsFocus && (nChar == VK_SPACE) && (nFlags == 0))
	{
		SetCheck(!GetCheck());
		SendMessage(MSG_BUTTON_CHECK, 0, GetCheck());
		return true;
	}

	return false;
}

void CDuiCheckButton::SetControlDisable(BOOL bIsDisable)
{
	if(m_bIsDisable != bIsDisable)
	{
		m_bIsDisable = bIsDisable;
		if(bIsDisable)
		{
			if(m_bDown)
			{
				m_enButtonState = enBSDisableDown;
			}
			else
			{
				m_enButtonState = enBSDisable;
			}
		}
		else
		{
			if(m_bDown)
			{
				m_enButtonState = enBSDown;
			}
			else
			{
				m_enButtonState = enBSNormal;
			}
		}
		::InvalidateRect(m_hWnd, &m_rc, true);
	}
}

void CDuiCheckButton::DrawControl(CDC &dc, CRect rcUpdate)
{
	int nWidth = m_rc.Width();
	int nHeight = m_rc.Height();

	if(!m_bUpdate)
	{
		UpdateMemDC(dc, nWidth * 6, nHeight);

		Graphics graphics(m_memDC);
		CRect  rcTemp(0, 0, nWidth, nHeight);

		for(int i = 0; i < 6; i++)
		{
			m_memDC.BitBlt(i * nWidth, 0, nWidth, nHeight, &dc, m_rc.left ,m_rc.top, SRCCOPY);

			graphics.DrawImage(m_pImage, Rect(rcTemp.left, rcTemp.top + (nHeight - m_sizeImageDpi.cy) / 2,   m_sizeImageDpi.cx, m_sizeImageDpi.cy),
				i * m_sizeImage.cx, 0, m_sizeImage.cx, m_sizeImage.cy, UnitPixel);

			rcTemp.OffsetRect(nWidth, 0);
		}

		if(!m_strTitle.IsEmpty())
		{
			m_memDC.SetBkMode(TRANSPARENT);

			rcTemp.SetRect(0, 0, nWidth, nHeight);

			BSTR bsFont = m_strFont.AllocSysString();
			FontFamily fontFamily(bsFont);
			Font font(&fontFamily, (REAL)m_nFontWidth, m_fontStyle, UnitPixel);
			graphics.SetTextRenderingHint( TextRenderingHintClearTypeGridFit );
			::SysFreeString(bsFont);

			StringFormat strFormat;
			strFormat.SetAlignment(StringAlignmentNear);
			strFormat.SetFormatFlags( StringFormatFlagsNoWrap | StringFormatFlagsMeasureTrailingSpaces);
			Size size = GetTextBounds(font, strFormat, m_strTitle);
			CPoint point = GetOriginPoint(nWidth - m_sizeImageDpi.cx - 3, nHeight, size.Width, size.Height,
							GetGDIAlignment(m_uAlignment), GetGDIVAlignment(m_uVAlignment));

			for(int i = 0; i < 6; i++)
			{
				SolidBrush solidBrush(enBSDisable == i ? Color(128, 128, 128) : m_clrText);

				RectF rect((Gdiplus::REAL)(m_sizeImageDpi.cx + 3 + point.x + i * nWidth), (Gdiplus::REAL)point.y, (Gdiplus::REAL)(nWidth - m_sizeImageDpi.cx - 3 - point.x), (Gdiplus::REAL)size.Height);
				BSTR bsTitle = m_strTitle.AllocSysString();
				graphics.DrawString(bsTitle, (INT)wcslen(bsTitle), &font, rect, &strFormat, &solidBrush);
				::SysFreeString(bsTitle);

				// (߿)
				if(m_bIsFocus && m_bShowFocus)
				{
					Pen pen(Color(128, 128, 128), 1);
					pen.SetDashStyle(DashStyleDot);
					RectF rectFocus((Gdiplus::REAL)(point.x + i * nWidth), (Gdiplus::REAL)point.y, (Gdiplus::REAL)(m_sizeImageDpi.cx + 6 + size.Width), (Gdiplus::REAL)size.Height);
					graphics.DrawRectangle(&pen, rectFocus);
				}
			}
		}
	}

	dc.BitBlt(m_rc.left,m_rc.top, m_rc.Width(), m_rc.Height(), &m_memDC, m_enButtonState * nWidth, 0, SRCCOPY);
}<|endoftext|>