+#include "driver.h"
#include "layout.h"
#include "route.h"
#include "trackiter.h"
{
if(!planner || planner->get_result()!=TrainRoutePlanner::COMPLETE)
return;
+ if(waypoints.empty())
+ return;
const list<Route *> &planned_routes = planner->get_routes_for(train);
if(!sequence_points.empty())
{
const SequencePoint &sp = sequence_points.front();
- if(sp.block==fncb.block() && !sp.is_cleared())
+ if(sp.block==fncb.block() && sp.preceding_train)
{
arrival = WAITING_FOR_SEQUENCE;
sequence_check_pending = true;
void TrainRouter::set_destination(const TrackChain &d)
{
if(waypoints.empty())
- waypoints.push_back(&d);
+ waypoints.push_back(Waypoint(d));
else
- waypoints.back() = &d;
+ waypoints.back() = Waypoint(d);
waypoints_changed = true;
metrics_stale = true;
}
-void TrainRouter::add_waypoint(const TrackChain &wp)
+void TrainRouter::add_waypoint(const TrackChain &chain, TrackChain::Direction dir)
{
- waypoints.push_back(&wp);
+ waypoints.push_back(Waypoint(chain, dir));
waypoints_changed = true;
metrics_stale = true;
}
-const TrackChain &TrainRouter::get_waypoint(unsigned index) const
+const TrainRouter::Waypoint &TrainRouter::get_waypoint(unsigned index) const
{
if(index>=waypoints.size())
throw out_of_range("TrainRouter::is_waypoint");
- return *waypoints[index];
+ return waypoints[index];
}
const TrainRouteMetric &TrainRouter::get_metric(int index) const
}
else if(msg.type=="add-waypoint")
{
- if(msg.value.check_type<TrackChain *>())
+ if(msg.value.check_type<Waypoint>())
+ {
+ Waypoint wp = msg.value.value<Waypoint>();
+ add_waypoint(*wp.chain, wp.direction);
+ }
+ else if(msg.value.check_type<TrackChain *>())
add_waypoint(*msg.value.value<TrackChain *>());
else
add_waypoint(*msg.value.value<const TrackChain *>());
void TrainRouter::tick(const Time::TimeDelta &dt)
{
- if(delay)
- {
- delay -= dt;
- if(delay<Time::zero)
- {
- duration = max(duration+delay, Time::zero);
- delay = Time::zero;
- }
- }
- else if(duration)
- duration = max(duration-dt, Time::zero);
-
if(waypoints_changed && !planner)
start_planning(train.get_layout());
if(planner && planner->check()!=TrainRoutePlanner::PENDING)
apply_plan(train.get_layout(), *planner);
+ Layout &layout = train.get_layout();
+ if(!layout.get_driver().is_halted() && !layout.get_clock().is_stopped())
+ {
+ if(delay)
+ {
+ delay -= dt;
+ if(delay<Time::zero)
+ {
+ duration = max(duration+delay, Time::zero);
+ delay = Time::zero;
+ }
+ }
+ else if(duration)
+ duration = max(duration-dt, Time::zero);
+ }
+
if(sequence_check_pending)
{
if(sequence_points.front().is_cleared())
if(arrival==ADVANCED_TO_END && !train.get_speed())
{
- signal_arrived.emit(waypoints.back());
- signal_event.emit(Message("arrived", waypoints.back()));
+ signal_arrived.emit(waypoints.back().chain);
+ signal_event.emit(Message("arrived", waypoints.back().chain));
arrival = ARRIVED;
}
else if(arrival==ARRIVED && !train.get_block_allocator().is_active())
void TrainRouter::train_advanced(Block &block)
{
- BlockIter b_iter = train.get_block_allocator().iter_for(block);
-
if(!waypoints.empty())
{
// A waypoint is considered reached when the train has advanced through it.
- const TrackChain &wp = *waypoints.front();
+ BlockIter b_iter = train.get_block_allocator().iter_for(block);
+ const Waypoint &wp = waypoints.front();
TrackIter t_iter = b_iter.track_iter();
- if(wp.has_track(*t_iter))
+ if(wp.chain->has_track(*t_iter))
{
- for(; t_iter; t_iter=t_iter.next())
+ while(1)
{
- if(!wp.has_track(*t_iter))
+ TrackIter next = t_iter.next();
+ if(!next)
+ break;
+
+ if(!wp.chain->has_track(*next))
{
+ if(wp.direction!=TrackChain::UNSPECIFIED)
+ if(t_iter!=wp.chain->iter_for(*t_iter, wp.direction))
+ break;
+
if(waypoints.size()==1)
{
if(arrival==RESERVED_TO_END)
}
else
{
+ const TrackChain *chain = wp.chain;
waypoints.erase(waypoints.begin());
metrics_stale = true;
- signal_waypoint_reached.emit(&wp);
- signal_event.emit(Message("waypoint-reached", &wp));
+ signal_waypoint_reached.emit(chain);
+ signal_event.emit(Message("waypoint-reached", chain));
}
break;
}
- else if(!block.has_track(*t_iter))
+ else if(!block.has_track(*next))
break;
+
+ t_iter = next;
}
}
}
if(waypoints.empty())
return;
- for(vector<const TrackChain *>::const_iterator i=waypoints.begin(); i!=waypoints.end(); ++i)
- metrics.push_back(new TrainRouteMetric(**i));
+ for(vector<Waypoint>::const_iterator i=waypoints.begin(); i!=waypoints.end(); ++i)
+ metrics.push_back(new TrainRouteMetric(*i->chain, i->direction));
for(unsigned i=metrics.size()-1; i-->0; )
metrics[i]->chain_to(*metrics[i+1]);
}
+TrainRouter::Waypoint::Waypoint(const TrackChain &c, TrackChain::Direction d):
+ chain(&c),
+ direction(d)
+{ }
+
+
TrainRouter::SequencePoint::SequencePoint(Block &b, unsigned o):
block(&b),
preceding_train(0),