OpenSteer::AbstractVehicle* 
OpenSteer::OpenSteerDemo::findVehicleNearestScreenPosition (int x, int y)
{
    // find the direction from the camera position to the given pixel
    const Vec3 direction = directionFromCameraToScreenPosition (x, y, glutGet (GLUT_WINDOW_HEIGHT));

    // iterate over all vehicles to find the one whose center is nearest the
    // "eye-mouse" selection line
    float minDistance = FLT_MAX;       // smallest distance found so far
    AbstractVehicle* nearest = NULL;   // vehicle whose distance is smallest
    const AVGroup& vehicles = allVehiclesOfSelectedPlugIn();
    for (AVIterator i = vehicles.begin(); i != vehicles.end(); i++)
    {
        // distance from this vehicle's center to the selection line:
        const float d = distanceFromLine ((**i).position(),
                                          camera.position(),
                                          direction);

        // if this vehicle-to-line distance is the smallest so far,
        // store it and this vehicle in the selection registers.
        if (d < minDistance)
        {
            minDistance = d;
            nearest = *i;
        }
    }

    return nearest;
}
void 
	OpenSteer::OpenSteerDemo::updateSelectedPlugIn (const float currentTime,
	const float elapsedTime)
{
	// switch to Update phase
	pushPhase (updatePhase);

	// service queued reset request, if any
	doDelayedResetPlugInXXX ();

	// if no vehicle is selected, and some exist, select the first one
	if (SteeringVehicle::getSelectedVehicle() == nullptr)
	{
		const AVGroup& vehicles = allVehiclesOfSelectedPlugIn();
		if (vehicles.size() > 0) 
			SteeringVehicle::setSelectedVehicle( vehicles.front() );
	}

	// invoke selected Plugin's Update method
	AbstractUpdated* updatedPlugin = dynamic_cast<AbstractUpdated*>(OpenSteer::Plugin::getSelectedPlugin());
	assert( updatedPlugin != nullptr );
	updatedPlugin->update (currentTime, elapsedTime);

	// return to previous phase
	popPhase ();
}
void 
OpenSteer::OpenSteerDemo::selectNextVehicle (void)
{
    if (selectedVehicle != NULL)
    {
        // get a container of all vehicles
        const AVGroup& all = allVehiclesOfSelectedPlugIn ();
        const AVIterator first = all.begin();
        const AVIterator last = all.end();

        // find selected vehicle in container
        const AVIterator s = std::find (first, last, selectedVehicle);

        // normally select the next vehicle in container
        selectedVehicle = *(s+1);

        // if we are at the end of the container, select the first vehicle
        if (s == last-1) selectedVehicle = *first;

        // if the search failed, use NULL
        if (s == last) selectedVehicle = NULL;
    }
}
void 
OpenSteer::OpenSteerDemo::updateSelectedPlugIn (const float currentTime,
                                                const float elapsedTime)
{
    // switch to Update phase
    pushPhase (updatePhase);

    // service queued reset request, if any
    doDelayedResetPlugInXXX ();

    // if no vehicle is selected, and some exist, select the first one
    if (selectedVehicle == NULL)
    {
        const AVGroup& vehicles = allVehiclesOfSelectedPlugIn();
        if (vehicles.size() > 0) selectedVehicle = vehicles.front();
    }

    // invoke selected PlugIn's Update method
    selectedPlugIn->update (currentTime, elapsedTime);

    // return to previous phase
    popPhase ();
}
void 
	OpenSteer::OpenSteerDemo::selectNextVehicle (void)
{
	if (SteeringVehicle::getSelectedVehicle() != nullptr)
	{
		// get a container of all vehicles
		const AVGroup& all = allVehiclesOfSelectedPlugIn ();
		const AVIterator first = all.begin();
		const AVIterator last = all.end();

		// find selected vehicle in container
		const AVIterator s = std::find (first, last, SteeringVehicle::getSelectedVehicle());

		// normally select the next vehicle in container
		SteeringVehicle::setSelectedVehicle( *(s+1) );

		// if we are at the end of the container, select the first vehicle
		if (s == last-1) SteeringVehicle::setSelectedVehicle( *first );

		// if the search failed, use nullptr
		if (s == last) SteeringVehicle::setSelectedVehicle( nullptr );
	}
}