train_panels.push_back(tpanel);
tpanel->set_visible(true);
- placing_train=train;
- placing_block=0;
- main_panel->set_status_text("Select location");
+ place_train(*train);
return train;
}
}
+void Engineer::place_train(Train &train)
+{
+ placing_train=&train;
+ placing_block=0;
+ main_panel->set_status_text("Select location");
+}
+
int Engineer::main()
{
dpy=new Graphics::Display;
{
if(placing_train)
{
- if(btn==1 && placing_block)
+ if(btn==1 && placing_block && !placing_block->get_train())
{
set_block_color(*placing_block, GL::Color(1, 1, 1));
if(&block!=placing_block)
{
if(placing_block)
- set_block_color(*placing_block, GL::Color(1, 1, 1));
+ reset_block_color(*placing_block);
placing_block=█
placing_entry=0;
set_block_color(*placing_block, GL::Color(0.5, 1, 0.7));
layout_3d.get_track(**i).set_color(color);
}
-void Engineer::sensor_event(bool state, Sensor *sensor)
-{
- const list<Track3D *> <racks=layout_3d.get_tracks();
- for(list<Track3D *>::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i)
- if((*i)->get_track().get_sensor_id()==sensor->get_address())
- {
- Block &block=trfc_mgr->get_block_by_track((*i)->get_track());
- if(state)
- (*i)->set_color(GL::Color(1, 0.5, 0.3));
- else if(block.get_train())
- set_block_color(block, GL::Color(1, 1, 0.3));
- else
- (*i)->set_color(GL::Color(1, 1, 1));
- }
-}
-
-void Engineer::block_reserved(const Block &block, const Train *train)
+void Engineer::reset_block_color(const Block &block)
{
if(unsigned sid=block.get_sensor_id())
{
Sensor &sensor=control.get_sensor(sid);
if(sensor.get_state())
+ {
+ set_block_color(block, GL::Color(1, 0.5, 0.3));
return;
+ }
}
- if(train)
+ if(block.get_train())
set_block_color(block, GL::Color(1, 1, 0.3));
else
set_block_color(block, GL::Color(1, 1, 1));
}
+void Engineer::sensor_event(bool, Sensor *sensor)
+{
+ const list<Block *> &blocks=trfc_mgr->get_blocks();
+ for(list<Block *>::const_iterator i=blocks.begin(); i!=blocks.end(); ++i)
+ if((*i)->get_sensor_id()==sensor->get_address())
+ reset_block_color(**i);
+}
+
+void Engineer::block_reserved(const Block &block, const Train *)
+{
+ reset_block_color(block);
+}
+
void Engineer::project_3d()
{
glMatrixMode(GL_PROJECTION);
Marklin::Control &get_control() { return control; }
Marklin::Train *add_train(unsigned);
+ void place_train(Marklin::Train &);
int main();
void quit() { exit(0); }
private:
void pointer_motion(int, int);
void view_all();
void set_block_color(const Marklin::Block &, const Msp::GL::Color &);
+ void reset_block_color(const Marklin::Block &);
void sensor_event(bool, Marklin::Sensor *);
void block_reserved(const Marklin::Block &, const Marklin::Train *);
void project_3d();
#include <msp/gltk/button.h>
#include <msp/strings/formatter.h>
#include "libmarklin/locomotive.h"
+#include "engineer.h"
#include "trainpanel.h"
+using namespace std;
using namespace Msp;
using namespace Marklin;
engineer(e),
train(t)
{
- set_size(200, 100);
+ set_size(200, 131);
- add(*(lbl_addr=new GLtk::Label(res, lexical_cast(train.get_locomotive().get_address(), "%2d"))));
+ add(*(lbl_addr=new GLtk::Label(res, format("%2d", train.get_locomotive().get_address()))));
lbl_addr->set_style("digital");
lbl_addr->set_geometry(GLtk::Geometry(10, geom.h-34, 35, 24));
sld_speed->set_step(1);
sld_speed->signal_value_changed.connect(sigc::mem_fun(this, &TrainPanel::speed_slider_changed));
- add(*(lbl_speed=new GLtk::Label(res, " 0")));
+ add(*(lbl_speed=new GLtk::Label(res, format("%2d", train.get_locomotive().get_speed()))));
lbl_speed->set_style("digital");
lbl_speed->set_geometry(GLtk::Geometry(10, geom.h-63, 35, 24));
train.get_locomotive().signal_speed_changed.connect(sigc::mem_fun(this, &TrainPanel::loco_speed_changed));
+ add(*(lbl_status=new GLtk::Label(res, train.get_status())));
+ lbl_status->set_style("digital");
+ lbl_status->set_geometry(GLtk::Geometry(10, geom.h-92, geom.w-20, 24));
+ train.signal_status_changed.connect(sigc::mem_fun(this, &TrainPanel::train_status_changed));
+
GLtk::Button *btn;
add(*(btn=new GLtk::Button(res, "Edit")));
btn->set_geometry(GLtk::Geometry(geom.w-50, 10, 40, 24));
+
+ add(*(btn=new GLtk::Button(res, "Place")));
+ btn->set_geometry(GLtk::Geometry(geom.w-90, 10, 40, 24));
+ btn->signal_clicked.connect(sigc::mem_fun(this, &TrainPanel::place_clicked));
}
void TrainPanel::speed_slider_changed(double v)
{
lbl_speed->set_text(format("%2d", speed));
}
+
+void TrainPanel::train_status_changed(const string &s)
+{
+ lbl_status->set_text(s);
+}
+
+void TrainPanel::place_clicked()
+{
+ engineer.place_train(train);
+}
Msp::GLtk::HSlider *sld_speed;
Marklin::Locomotive *loco;
Msp::GLtk::Label *lbl_speed;
+ Msp::GLtk::Label *lbl_status;
public:
TrainPanel(Engineer &, const Msp::GLtk::Resources &, Marklin::Train &);
private:
void speed_slider_changed(double);
void loco_speed_changed(unsigned);
+ void train_status_changed(const std::string &);
+ void place_clicked();
};
#endif
engineer(e),
train(t)
{
- set_size(200, 75);
+ set_size(200, 95);
add(*(ent_addr=new GLtk::Entry(res)));
- ent_addr->set_geometry(GLtk::Geometry(10, geom.h-25, 40, 20));
+ ent_addr->set_geometry(GLtk::Geometry(10, geom.h-30, 40, 20));
add(*(ent_name=new GLtk::Entry(res, "Train")));
- ent_name->set_geometry(GLtk::Geometry(10, geom.h-50, geom.w-20, 20));
+ ent_name->set_geometry(GLtk::Geometry(10, geom.h-55, geom.w-20, 20));
GLtk::Button *btn;
{
train=t;
if(train)
- cout<<"Block "<<this<<" reserved for train "<<train<<'\n';
+ cout<<"Block "<<this<<" reserved for train "<<train->get_name()<<'\n';
else
cout<<"Block "<<this<<" freed\n";
trfc_mgr.signal_block_reserved.emit(*this, train);
~TrafficManager();
Control &get_control() const { return control; }
+ const std::list<Block *> &get_blocks() const { return blocks; }
Block &get_block_by_track(const Track &) const;
const std::list<Train *> &get_trains() const { return trains; }
void add_train(Train *);
Train::Train(TrafficManager &tm, Locomotive &l):
trfc_mgr(tm),
loco(l),
- target_speed(0)
+ target_speed(0),
+ status("Unplaced")
{
trfc_mgr.add_train(this);
target_speed=speed;
if(!target_speed)
{
+ // XXX We might roll onto a new sensor and get confused - should delay freeing blocks a bit
for(list<BlockRef>::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
i->block->reserve(0);
rsv_blocks.clear();
+ try_reserve=Time::TimeStamp();
}
else if(rsv_blocks.empty() && !reserve_more())
return;
+
loco.set_speed(speed);
+ set_status(target_speed ? "Traveling" : "Stopped");
}
void Train::place(Block *block, unsigned entry)
}
if(!block->reserve(this))
+ {
+ set_status("Unplaced");
return;
+ }
cur_blocks.push_back(BlockRef(block, entry));
+
+ set_status("Stopped");
}
bool Train::free_block(Block *block)
{
if(try_reserve && t>try_reserve)
{
- if(reserve_more())
+ if(reserve_more() || !rsv_blocks.empty())
{
loco.set_speed(target_speed);
+ set_status("Traveling");
try_reserve=Time::TimeStamp();
}
else
void Train::sensor_event(bool state, Sensor *sensor)
{
- if(!loco.get_speed())
- return;
-
unsigned addr=sensor->get_address();
if(state)
for(i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
if(i->block->get_sensor_id() && i->block->get_sensor_id()!=addr)
break;
- cur_blocks.splice(cur_blocks.end(), rsv_blocks, rsv_blocks.begin(), i);
- cout<<"Train "<<this<<" advanced, "<<cur_blocks.size()<<" cur_blocks, "<<rsv_blocks.size()<<" rsv_blocks\n";
+ if(i!=rsv_blocks.begin())
+ {
+ cur_blocks.splice(cur_blocks.end(), rsv_blocks, rsv_blocks.begin(), i);
+ cout<<"Train "<<name<<" advanced, "<<cur_blocks.size()<<" cur_blocks, "<<rsv_blocks.size()<<" rsv_blocks\n";
+ }
- if(rsv_blocks.empty() && !reserve_more())
+ if(target_speed && rsv_blocks.empty() && !reserve_more())
{
loco.set_speed(0);
try_reserve=Time::now()+2*Time::sec;
+ set_status("Blocked");
}
}
else
{
- cout<<"Train "<<this<<" finding blocks to free\n";
+ cout<<"Train "<<name<<" finding blocks to free\n";
list<BlockRef>::iterator i;
for(i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
{
}
}
- reserve_more();
+ if(target_speed)
+ reserve_more();
}
}
if(!last)
return false;
- cout<<"Train "<<this<<" reserving more blocks\n";
+ cout<<"Train "<<name<<" reserving more blocks\n";
bool result=false;
unsigned size=rsv_blocks.size();
return result;
}
+void Train::set_status(const string &s)
+{
+ status=s;
+ signal_status_changed.emit(s);
+}
+
} // namespace Marklin
std::list<BlockRef> rsv_blocks;
unsigned target_speed;
Msp::Time::TimeStamp try_reserve;
+ std::string status;
public:
sigc::signal<void, const std::string &> signal_name_changed;
+ sigc::signal<void, const std::string &> signal_status_changed;
Train(TrafficManager &, Locomotive &);
void set_speed(unsigned);
const std::string &get_name() const { return name; }
Locomotive &get_locomotive() const { return loco; }
+ const std::string &get_status() const { return status; }
void place(Block *, unsigned);
bool free_block(Block *);
void tick(const Msp::Time::TimeStamp &);
private:
void sensor_event(bool, Sensor *);
bool reserve_more();
+ void set_status(const std::string &);
};
} // namespace Marklin