void VerletPhysicsSystem::update( EntityManager &entities, EventManager &events, TimeDelta dt )
{
  ComponentHandle<VerletBody> body;
  for( auto __unused e : entities.entities_with_components( body ) )
  {
    auto &b = *body.get();
    auto current = b.position;
    auto velocity = (b.position - b.previous_position) * static_cast<float>((dt / previous_dt)) + b.acceleration * static_cast<float>(dt * dt);
    // Friction as viscous drag.
    velocity *= (1.0 - b.drag);

    /*
    // Friction as a fixed-ish force.
    // Perhaps do some kind of ground test and apply when things are on ground.
    auto l2 = glm::length2(velocity);
    if (l2 > 0.0f) {
      auto len = std::sqrt(l2);
      auto friction = (velocity / len) * std::min(b.friction, len);
      velocity -= friction;
    }
    */

    b.position += velocity;
    b.previous_position = current;

    // We reset the acceleration so other systems/effects can simply add forces each frame.
    // TODO: consider alternative approaches to this.
    b.acceleration = vec3(0);
    previous_dt = dt;
  }

  // solve constraints
  ComponentHandle<VerletDistanceConstraint> constraint;
  const auto constraint_iterations = 2;
  for( auto __unused e : entities.entities_with_components( constraint ) )
  {
    if( (! constraint->a.valid()) || (! constraint->b.valid()) ) {
      // would be cooler if the bodies knew about all constraints on them so this couldn't happen.
      constraint.remove();
      continue;
    }

    for( int i = 0; i < constraint_iterations; i += 1 ) {
      auto &a = *constraint->a.get();
      auto &b = *constraint->b.get();

      auto center = (a.position + b.position) / 2.0f;
      auto delta = a.position - b.position;
      auto len = glm::length( delta );
      if( len < std::numeric_limits<float>::epsilon() ) {
        delta = randVec3();
        len = 1.0f;
      }
      delta *= constraint->distance / (len * 2.0f); // get half delta
      a.position = center + delta;
      b.position = center - delta;
    }
  }
}
void soso::applyPhysicsAttraction(EntityManager &entities)
{
  ComponentHandle<VerletBody>          body;
  ComponentHandle<PhysicsAttraction>  attraction;

  for (auto __unused e : entities.entities_with_components(body, attraction))
  {
    ComponentHandle<PhysicsAttractor> attractor;
    ComponentHandle<VerletBody>        attractor_body;

    for (auto __unused e : entities.entities_with_components(attractor, attractor_body))
    {
      auto delta = attractor_body->position - body->position;
      auto len = glm::length( delta );
      auto t = glm::clamp( len / attractor->distance_falloff, 0.0f, 1.0f );
      t = 1.0f - (t * t);
      auto force = delta * attractor->strength * attraction->strength * t;
      body->nudge( force );
    }
  }
}
void HudSystem::update(EntityManager& entities,
                       EventManager& events,
                       double dt)
{
   SpaceShip::Handle spaceShip;
   Health::Handle health;
   Gun::Handle gun;
   for (Entity entity : entities.entities_with_components(spaceShip, health, gun))
   {
      m_heatBorderSprite.setPosition(50.0f, 485.0f);
      m_window.draw(m_heatBorderSprite);

      m_heatBarSprite.setPosition(50.0f, 485.0f);
      m_heatBarRect.width = static_cast<int>(gun->heat+0.5);
      m_heatBarSprite.setTextureRect(m_heatBarRect);
      m_window.draw(m_heatBarSprite);

      m_healthText.setPosition(50.0f, 500.0f);
      m_window.draw(m_healthText);

      if (!entity.has_component<DeathSentence>())
      {
         float startX = 50.0f;
         for (int i = 0; i < health->health+1; ++i)
         {
            m_healthSprite.setPosition(startX, 540.0f);
            m_window.draw(m_healthSprite);
            startX += 25.0f;
         }
      }

      m_scoreText.setPosition(750.0f, 500.0f);

      m_window.draw(m_scoreText);

      m_scoreView.setPosition(750.0f, 533.0f);

      m_scoreView.draw(spaceShip->score, m_window);

      // Only support one space ship atm
      return;
   }
}
void TransformSystem::update(EntityManager &entities, EventManager &events, TimeDelta dt)
{
  ComponentHandle<Transform> transform;

  /// If/when entityx allows us to order our components in memory based on their hierarchy,
  /// we will be able to walk through and simply update in linear order.
  /// We could also do that if we wrote our own memory allocator for transforms (which we are unlikely to pursue).

  for (Entity __unused e : entities.entities_with_components(transform))
  {
    if (transform->isRoot())
    {
      transform->composeTransform(mat4(1));
      transform->descend([] (const Transform &parent, Transform &child) {
        child.composeTransform(parent.worldTransform());
      });
    }
  }
}