Instead add a function to get an AI of a specific type.
The tags were too clumsy and brittle. Most AIs don't work well with
multiple instances per train, so the type is an adequate identifier.
drp_route->set_selected_index(0);
const Route *current_route = 0;
- if(TrainRouter *router = dynamic_cast<TrainRouter *>(train.get_tagged_ai("router")))
+ if(TrainRouter *router = train.get_ai_of_type<TrainRouter>())
current_route = router->get_route();
const set<Route *> &routes = engineer.get_layout().get_routes();
pnl_extra->set_geometry(GLtk::Geometry(0, 10, geom.w, 135));
pnl_extra->set_visible(false);
- TrainRouter *router = dynamic_cast<TrainRouter *>(train.get_tagged_ai("router"));
+ TrainRouter *router = train.get_ai_of_type<TrainRouter>();
if(!router)
- {
router = new TrainRouter(train);
- router->set_tag("router");
- }
const Route *route = router->get_route();
pnl_extra->add(*(lbl_route = new GLtk::Label((route ? route->get_name() : "Free run"))));
void TrainPanel::timetable_clicked()
{
- Timetable *timetable = dynamic_cast<Timetable *>(train.get_tagged_ai("timetable"));
+ Timetable *timetable = train.get_ai_of_type<Timetable>();
if(!timetable)
- {
timetable = new Timetable(train);
- timetable->set_tag("timetable");
- }
TimetableDialog *dialog = new TimetableDialog(*timetable);
engineer.get_root().add(*dialog);
{
pick_conn.disconnect();
- TrainRouter *router = dynamic_cast<TrainRouter *>(train.get_tagged_ai("router"));
+ TrainRouter *router = train.get_ai_of_type<TrainRouter>();
if(!router || !router->go_to(*track))
engineer.set_status("Could not set route");
}
{
ent_addr->set_text(lexical_cast<string>(train->get_address()));
ent_name->set_text(train->get_name());
- if(TrainRouter *router = dynamic_cast<TrainRouter *>(train->get_tagged_ai("router")))
+ if(TrainRouter *router = train->get_ai_of_type<TrainRouter>())
drp_priority->set_selected_index(router->get_priority()+2);
unsigned n_vehicles = train->get_n_vehicles();
}
train->set_name(ent_name->get_text());
- if(TrainRouter *router = dynamic_cast<TrainRouter *>(train->get_tagged_ai("router")))
+ if(TrainRouter *router = train->get_ai_of_type<TrainRouter>())
router->set_priority(drp_priority->get_selected_index()-2);
// The locomotive is vehicle 0 so we need to add 1
void Timetable::save(list<DataFile::Statement> &st) const
{
- if(!tag.empty())
- st.push_back((DataFile::Statement("tag"), tag));
for(vector<Row>::const_iterator i=rows.begin(); i!=rows.end(); ++i)
st.push_back(i->save());
}
add("route", &Loader::route);
add("speed", &Loader::speed);
add("reverse", &Loader::reverse);
- add("tag", &Loader::tag);
add("travel_to", &Loader::travel_to);
add("travel_past", &Loader::travel_past);
add("wait", &Loader::wait);
obj.rows.push_back(Row(SPEED, s));
}
-void Timetable::Loader::tag(const string &t)
-{
- obj.tag = t;
-}
-
void Timetable::Loader::travel_to(unsigned s)
{
obj.rows.push_back(Row(TRAVEL_TO, s));
void route(const std::string &);
void reverse();
void speed(unsigned);
- void tag(const std::string &);
void travel_to(unsigned);
void travel_past(unsigned);
void wait(unsigned);
ais.erase(i);
}
-TrainAI *Train::get_tagged_ai(const string &tag) const
-{
- for(list<TrainAI *>::const_iterator i=ais.begin(); i!=ais.end(); ++i)
- if((*i)->get_tag()==tag)
- return *i;
-
- return 0;
-}
-
void Train::ai_message(const TrainAI::Message &msg)
{
for(list<TrainAI *>::iterator i=ais.begin(); i!=ais.end(); ++i)
void add_ai(TrainAI &);
void remove_ai(TrainAI &);
- TrainAI *get_tagged_ai(const std::string &) const;
void ai_message(const TrainAI::Message &);
+ template<typename T>
+ T *get_ai_of_type() const
+ {
+ for(std::list<TrainAI *>::const_iterator i=ais.begin(); i!=ais.end(); ++i)
+ if(T *ai = dynamic_cast<T *>(*i))
+ return ai;
+ return 0;
+ }
+
void place(Block &, unsigned);
void unplace();
bool is_placed() const { return !blocks.empty(); }
train.remove_ai(*this);
}
-void TrainAI::set_tag(const string &t)
-{
- tag = t;
-}
-
} // namespace R2C2
protected:
Train &train;
- std::string tag;
TrainAI(Train &);
public:
virtual ~TrainAI();
- void set_tag(const std::string &);
- const std::string &get_tag() const { return tag; }
-
virtual void message(const Message &) { }
virtual void tick(const Msp::Time::TimeStamp &, const Msp::Time::TimeDelta &) { }
};
void TrainRouter::save(list<DataFile::Statement> &st) const
{
- if(!tag.empty())
- st.push_back((DataFile::Statement("tag"), tag));
-
st.push_back((DataFile::Statement("priority"), priority));
if(!routes.empty())
bool exit_conflict = (exit==static_cast<unsigned>(other_entry));
// TODO: speed matching with preceding train
- // XXX Should invent a better way to get our counterpart from the other train
- TrainRouter *other_router = dynamic_cast<TrainRouter *>(other_train->get_tagged_ai("router"));
+ TrainRouter *other_router = other_train->get_ai_of_type<TrainRouter>();
int other_prio = (other_router ? other_router->get_priority() : 0);
if(!entry_conflict && !exit_conflict && other_prio<priority)
{
add("priority", &TrainRouter::priority);
add("route", &Loader::route);
- add("tag", &Loader::tag);
}
void TrainRouter::Loader::route(const string &n)
obj.set_route(&obj.train.get_layout().get_route(n));
}
-void TrainRouter::Loader::tag(const string &t)
-{
- obj.set_tag(t);
-}
-
} // namespace R2C2
Loader(TrainRouter &);
private:
void route(const std::string &);
- void tag(const std::string &);
};
sigc::signal<void, const Route *> signal_route_changed;
pkt.name = train.get_name();
send(pkt);
- TrainStatus *status = new TrainStatus(train);
- status->set_tag("server:status");
- status->signal_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_status_changed), sigc::ref(train)));
+ if(!train.get_ai_of_type<TrainStatus>())
+ new TrainStatus(train);
}
void Server::train_control_changed(const Train &train, const string &control, float value)
pkt.route = route->get_name();
send(pkt);
}
-}
-
-void Server::train_status_changed(const Train &train, const string &status)
-{
- TrainStatusPacket pkt;
- pkt.address = train.get_address();
- pkt.status = status;
- send(pkt);
+ else if(ev.type=="status-changed")
+ {
+ TrainStatusPacket pkt;
+ pkt.address = train.get_address();
+ pkt.status = ev.value.value<std::string>();
+ send(pkt);
+ }
}
template<typename P>
pkt.functions = train.get_functions();
comm.send(pkt);
}
- if(TrainStatus *status = dynamic_cast<TrainStatus *>(train.get_tagged_ai("server:status")))
+ if(TrainStatus *status = train.get_ai_of_type<TrainStatus>())
{
TrainStatusPacket pkt;
pkt.address = train.get_address();
pkt.status = status->get_status();
comm.send(pkt);
}
- if(TrainRouter *router = dynamic_cast<TrainRouter *>(train.get_tagged_ai("router")))
+ if(TrainRouter *router = train.get_ai_of_type<TrainRouter>())
{
TrainRoutePacket pkt;
pkt.address = train.get_address();
void train_control_changed(const Train &, const std::string &, float);
void train_function_changed(const Train &, unsigned, bool);
void train_ai_event(const Train &, TrainAI &, const TrainAI::Message &);
- void train_status_changed(const Train &, const std::string &);
template<typename P>
void send(const P &);