sun.set_position(0, -0.259, 0.966, 0);
lighting.attach(0, sun);
- layout.signal_track_added.connect(sigc::mem_fun(this, &Layout3D::track_added));
- layout.signal_track_removed.connect(sigc::mem_fun(this, &Layout3D::track_removed));
- layout.signal_vehicle_added.connect(sigc::mem_fun(this, &Layout3D::vehicle_added));
- layout.signal_vehicle_removed.connect(sigc::mem_fun(this, &Layout3D::vehicle_removed));
- layout.signal_signal_added.connect(sigc::mem_fun(this, &Layout3D::signal_added));
- layout.signal_signal_removed.connect(sigc::mem_fun(this, &Layout3D::signal_removed));
-
- const set<Track *> <racks = layout.get_tracks();
- for(set<Track *>::iterator i=ltracks.begin(); i!=ltracks.end(); ++i)
- track_added(**i);
- const set<Signal *> &lsignals = layout.get_signals();
- for(set<Signal *>::iterator i=lsignals.begin(); i!=lsignals.end(); ++i)
- signal_added(**i);
+ layout.signal_object_added.connect(sigc::mem_fun(this, &Layout3D::object_added));
+ layout.signal_object_removed.connect(sigc::mem_fun(this, &Layout3D::object_removed));
+
+ const set<Object *> &lobjs = layout.get_all<Object>();
+ for(set<Object *>::iterator i=lobjs.begin(); i!=lobjs.end(); ++i)
+ object_added(**i);
}
Layout3D::~Layout3D()
return *get_item(signals, &s);
}
-void Layout3D::track_added(Track &t)
-{
- new Track3D(*this, t);
-}
-
-void Layout3D::track_removed(Track &t)
-{
- TrackMap::iterator i = tracks.find(&t);
- if(i!=tracks.end())
- delete i->second;
-}
-
-void Layout3D::vehicle_added(Vehicle &v)
-{
- new Vehicle3D(*this, v);
-}
-
-void Layout3D::vehicle_removed(Vehicle &v)
-{
- VehicleMap::iterator i = vehicles.find(&v);
- if(i!=vehicles.end())
- delete i->second;
-}
-
-void Layout3D::signal_added(Signal &s)
-{
- new Signal3D(*this, s);
-}
-
-void Layout3D::signal_removed(Signal &s)
-{
- SignalMap::iterator i = signals.find(&s);
- if(i!=signals.end())
- delete i->second;
+void Layout3D::object_added(Object &o)
+{
+ if(Track *t = dynamic_cast<Track *>(&o))
+ new Track3D(*this, *t);
+ else if(Signal *s = dynamic_cast<Signal *>(&o))
+ new Signal3D(*this, *s);
+ else if(Vehicle *v = dynamic_cast<Vehicle *>(&o))
+ new Vehicle3D(*this, *v);
+}
+
+void Layout3D::object_removed(Object &o)
+{
+ if(Track *t = dynamic_cast<Track *>(&o))
+ {
+ TrackMap::iterator i = tracks.find(t);
+ if(i!=tracks.end())
+ delete i->second;
+ }
+ else if(Signal *s = dynamic_cast<Signal *>(&o))
+ {
+ SignalMap::iterator i = signals.find(s);
+ if(i!=signals.end())
+ delete i->second;
+ }
+ else if(Vehicle *v = dynamic_cast<Vehicle *>(&o))
+ {
+ VehicleMap::iterator i = vehicles.find(v);
+ if(i!=vehicles.end())
+ delete i->second;
+ }
}
} // namespace R2C2
const Msp::GL::Lighting &get_lighting() const { return lighting; }
private:
- void track_added(Track &);
- void track_removed(Track &);
- void vehicle_added(Vehicle &);
- void vehicle_removed(Vehicle &);
- void signal_added(Signal &);
- void signal_removed(Signal &);
+ void object_added(Object &);
+ void object_removed(Object &);
};
} // namespace R2C2
void View3D::view_all(bool tight)
{
- const set<Track *> &tracks = layout.get_layout().get_tracks();
+ const set<Track *> &tracks = layout.get_layout().get_all<Track>();
Geometry::BoundingBox<float, 3> bbox;
for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
bbox = bbox|(*i)->get_bounding_box();
layout = new Layout(catalogue);
layout_3d = new Layout3D(*layout);
- layout->signal_track_added.connect(sigc::mem_fun(this, &Designer::track_added));
- layout->signal_track_removed.connect(sigc::mem_fun(this, &Designer::track_removed));
+ layout->signal_object_added.connect(sigc::mem_fun(this, &Designer::object_added));
+ layout->signal_object_removed.connect(sigc::mem_fun(this, &Designer::object_removed));
if(argc>1)
{
else if(key==Msp::Input::KEY_F && shift)
{
const set<Track *> &tracks = selection.get_objects<Track>();
- const set<Track *> <racks = layout->get_tracks();
+ const set<Track *> <racks = layout->get_all<Track>();
for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
(*i)->set_flex(!(*i)->get_flex());
glColor3f(1.0, 1.0, 1.0);
}
-void Designer::track_added(Track &trk)
+void Designer::object_added(Object &obj)
{
- new_tracks.push_back(&trk);
+ if(Track *trk = dynamic_cast<Track *>(&obj))
+ new_tracks.push_back(trk);
}
-void Designer::track_removed(Track &trk)
+void Designer::object_removed(Object &obj)
{
- list<Track *>::iterator i = find(new_tracks.begin(), new_tracks.end(), &trk);
- if(i!=new_tracks.end())
- new_tracks.erase(i);
+ if(Track *trk = dynamic_cast<Track *>(&obj))
+ {
+ list<Track *>::iterator i = find(new_tracks.begin(), new_tracks.end(), trk);
+ if(i!=new_tracks.end())
+ new_tracks.erase(i);
+ }
}
Object *Designer::pick_object(const Vector &pointer)
const GL::Vector3 &cpos = view.get_camera().get_position();
GL::Vector4 cray = view.get_camera().unproject(GL::Vector4(pointer.x, pointer.y, 0, 0));
- return view.get_layout().get_layout().pick_object(Ray(cpos, Vector(cray)));
+ return view.get_layout().get_layout().pick<Object>(Ray(cpos, Vector(cray)));
}
void Designer::update_track_icon(Track3D &track)
void Designer::clear_paths()
{
- const set<Track *> <racks = layout->get_tracks();
+ const set<Track *> <racks = layout->get_all<Track>();
for(set<Track *>::iterator i=ltracks.begin(); i!=ltracks.end(); ++i)
{
Track3D &t3d = layout_3d->get_track(**i);
void axis_motion(unsigned, float, float);
void apply_camera();
void render();
- void track_added(R2C2::Track &);
- void track_removed(R2C2::Track &);
+ void object_added(R2C2::Object &);
+ void object_removed(R2C2::Object &);
R2C2::Object *pick_object(const R2C2::Vector &);
void update_track_icon(R2C2::Track3D &);
void selection_changed();
j->object->break_link(**i);
}
- const set<Track *> <racks = designer.get_layout().get_tracks();
+ const set<Track *> <racks = designer.get_layout().get_all<Track>();
for(set<Track *>::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i)
{
bool ok = true;
i->object->set_rotation(i->rot);
}
- const set<Track *> <racks = designer.get_layout().get_tracks();
+ const set<Track *> <racks = designer.get_layout().get_all<Track>();
float limit = max(designer.get_layout().get_catalogue().get_gauge(),
designer.get_camera_controller().get_view_scale()/100.0f);
MObject *snapped = 0;
void Measure::snap_to_tracks(Snap &sn)
{
- const set<Track *> <racks = designer.get_layout().get_tracks();
+ const set<Track *> <racks = designer.get_layout().get_all<Track>();
for(set<Track *>::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i)
if((*i)->snap(sn, 0.01, SNAP_NODE))
return;
Vector minp;
Vector maxp;
- const set<Track *> &tracks = layout.get_tracks();
+ const set<Track *> &tracks = layout.get_all<Track>();
for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
xmlpp::Element *elem = root->add_child("g");
const GL::Vector3 &start = camera.get_position();
GL::Vector4 ray = camera.unproject(GL::Vector4(p.x, p.y, 0, 0));
- return layout.pick_track(Ray(start, Vector(ray)));
+ return layout.pick<Track>(Ray(start, Vector(ray)));
}
void Engineer::process_new_train(Train &train)
layout.signal_block_reserved.connect(sigc::mem_fun(this, &BlockAllocator::block_reserved));
layout.signal_sensor_state_changed.connect(sigc::mem_fun(this, &BlockAllocator::sensor_state_changed));
- const set<Track *> &tracks = layout.get_tracks();
+ const set<Track *> &tracks = layout.get_all<Track>();
for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
if((*i)->get_turnout_id())
(*i)->signal_path_changed.connect(sigc::hide(sigc::bind(sigc::mem_fun(this, &BlockAllocator::turnout_path_changed), sigc::ref(**i))));
#include "trackcircuit.h"
#include "tracktype.h"
#include "train.h"
+#include "vehicle.h"
#include "vehicletype.h"
#include "zone.h"
delete *routes.begin();
while(!zones.empty())
delete *zones.begin();
- while(!signals.empty())
- delete *signals.begin();
- while(!tracks.empty())
- delete *tracks.begin();
+ objects.del<Signal>();
+ objects.del<Track>();
while(!blocks.empty())
delete *blocks.begin();
}
return *driver;
}
-void Layout::add_track(Track &t)
+void Layout::add(Object &o)
{
- if(tracks.insert(&t).second)
+ if(objects.insert(o))
+ signal_object_added.emit(o);
+}
+
+void Layout::add(Track &t)
+{
+ if(objects.insert(t))
{
+ // Blocks must be recreated first
create_blocks();
- signal_track_added.emit(t);
+ signal_object_added.emit(t);
}
}
-Track *Layout::pick_track(const Ray &ray)
+template<>
+const set<Object *> &Layout::get_all<Object>() const
{
- return pick(tracks, ray);
+ return objects.get();
}
-void Layout::remove_track(Track &t)
+template<>
+const set<Track *> &Layout::get_all<Track>() const
{
- if(tracks.erase(&t))
- {
- create_blocks(t);
- signal_track_removed.emit(t);
- }
+ return objects.get<Track>();
}
-unsigned Layout::allocate_turnout_id()
+template<>
+const set<Signal *> &Layout::get_all<Signal>() const
{
- set<unsigned> used_ids;
- for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
- if((*i)->get_turnout_id())
- used_ids.insert((*i)->get_turnout_id());
-
- unsigned result = next_turnout_id;
- while(used_ids.count(result))
- ++result;
- next_turnout_id = result+1;
-
- return result;
+ return objects.get<Signal>();
}
-void Layout::add_signal(Signal &s)
+template<>
+const set<Vehicle *> &Layout::get_all<Vehicle>() const
{
- if(signals.insert(&s).second)
- signal_signal_added.emit(s);
+ return objects.get<Vehicle>();
}
-Signal *Layout::pick_signal(const Ray &ray)
+template<typename T>
+T *Layout::pick(const Ray &ray)
{
- return pick(signals, ray);
+ const set<Object *> &objs = objects.get();
+ for(set<Object *>::const_iterator i=objs.begin(); i!=objs.end(); ++i)
+ if(T *t = dynamic_cast<T *>(*i))
+ if(t->collide_ray(ray))
+ return t;
+
+ return 0;
}
-void Layout::remove_signal(Signal &s)
+template Object *Layout::pick<Object>(const Ray &);
+template Track *Layout::pick<Track>(const Ray &);
+template Signal *Layout::pick<Signal>(const Ray &);
+template Vehicle *Layout::pick<Vehicle>(const Ray &);
+
+void Layout::remove(Object &o)
{
- if(signals.erase(&s))
- signal_signal_removed.emit(s);
+ if(objects.erase(o))
+ signal_object_removed.emit(o);
}
-Object *Layout::pick_object(const Ray &ray)
+void Layout::remove(Track &t)
{
- if(Object *obj = pick_track(ray))
- return obj;
- else if((obj = pick_signal(ray)))
- return obj;
- return 0;
+ if(objects.erase(t))
+ {
+ // Blocks must be recreated first
+ create_blocks(t);
+ signal_object_removed.emit(t);
+ }
}
-template<typename T>
-T *Layout::pick(const set<T *> &objs, const Ray &ray)
+unsigned Layout::allocate_turnout_id()
{
- for(typename set<T *>::const_iterator i=objs.begin(); i!=objs.end(); ++i)
- if((*i)->collide_ray(ray))
- return *i;
+ set<unsigned> used_ids;
+ const set<Track *> &tracks = objects.get<Track>();
+ for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ if((*i)->get_turnout_id())
+ used_ids.insert((*i)->get_turnout_id());
- return 0;
+ unsigned result = next_turnout_id;
+ while(used_ids.count(result))
+ ++result;
+ next_turnout_id = result+1;
+
+ return result;
}
void Layout::add_block(Block &b)
used_tracks.insert(btracks.begin(), btracks.end());
}
+ const set<Track *> &tracks = objects.get<Track>();
for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
if(used_tracks.count(*i)==0)
{
signal_train_removed.emit(t);
}
-void Layout::add_vehicle(Vehicle &v)
-{
- if(vehicles.insert(&v).second)
- signal_vehicle_added.emit(v);
-}
-
-void Layout::remove_vehicle(Vehicle &v)
-{
- if(vehicles.erase(&v))
- signal_vehicle_removed.emit(v);
-}
-
void Layout::add_sensor(Sensor &s)
{
if(sensors.insert(&s).second)
for(set<Sensor *>::iterator i=sensors.begin(); i!=sensors.end(); ++i)
(*i)->tick(dt);
+ const set<Signal *> &signals = objects.get<Signal>();
for(set<Signal *>::iterator i=signals.begin(); i!=signals.end(); ++i)
(*i)->tick(dt);
for(map<unsigned, Train *>::iterator i=trains.begin(); i!=trains.end(); ++i)
if(!base.empty())
writer.write((DataFile::Statement("base"), base));
+ const set<Track *> &tracks = objects.get<Track>();
for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
DataFile::Statement st("track");
writer.write(st);
}
+ const set<Signal *> &signals = objects.get<Signal>();
for(set<Signal *>::const_iterator i=signals.begin(); i!=signals.end(); ++i)
{
DataFile::Statement st("signal");
IO::BufferedFile out(fn, IO::M_WRITE);
DataFile::Writer writer(out);
+ const set<Track *> &tracks = objects.get<Track>();
for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
if(unsigned tid = (*i)->get_turnout_id())
writer.write((DataFile::Statement("turnout"), tid, (*i)->get_active_path()));
}
+template<typename B>
+Layout::Storage<B>::~Storage()
+{
+ while(!base.empty())
+ delete *base.begin();
+}
+
+template<typename B>
+bool Layout::Storage<B>::insert(B &b)
+{
+ bool result = base.insert(&b).second;
+ if(result)
+ caches.clear();
+ return result;
+}
+
+template<typename B>
+bool Layout::Storage<B>::erase(B &b)
+{
+ bool result = base.erase(&b);
+ if(result)
+ caches.clear();
+ return result;
+}
+
+template<typename B>
+template<typename T>
+const set<T *> &Layout::Storage<B>::get() const
+{
+ for(list<Variant>::const_iterator i=caches.begin(); i!=caches.end(); ++i)
+ if(i->check_type<set<T *> >())
+ return i->value<set<T *> >();
+
+ caches.push_back(set<T *>());
+ set<T *> &result = caches.back().value<set<T *> >();
+ for(typename set<B *>::const_iterator i=base.begin(); i!=base.end(); ++i)
+ if(T *t = dynamic_cast<T *>(*i))
+ result.insert(t);
+
+ return result;
+}
+
+template<typename B>
+template<typename T>
+void Layout::Storage<B>::del()
+{
+ set<T *> ts = get<T>();
+ for(typename set<T *>::iterator i=ts.begin(); i!=ts.end(); ++i)
+ if(base.count(*i))
+ delete *i;
+}
+
+
Layout::Loader::Loader(Layout &l):
DataFile::ObjectLoader<Layout>(l),
new_tracks(false)
Track *trk = new Track(obj, obj.catalogue.get_track(art_nr));
load_sub(*trk);
new_tracks = true;
- for(set<Track *>::iterator i=obj.tracks.begin(); i!=obj.tracks.end(); ++i)
+ const set<Track *> &tracks = obj.objects.get<Track>();
+ for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
if(*i!=trk)
trk->link_to(**i);
}
void zone();
};
+private:
+ template<typename B>
+ class Storage
+ {
+ private:
+ std::set<B *> base;
+ mutable std::list<Msp::Variant> caches;
+
+ public:
+ ~Storage();
+
+ bool insert(B &);
+ bool erase(B &);
+
+ const std::set<B *> &get() const { return base; }
+
+ template<typename T>
+ const std::set<T *> &get() const;
+
+ template<typename T>
+ void del();
+ };
+
+public:
typedef std::set<Zone *> ZoneSet;
typedef std::vector<Zone *> ZoneArray;
- sigc::signal<void, Track &> signal_track_added;
- sigc::signal<void, Track &> signal_track_removed;
- sigc::signal<void, Signal &> signal_signal_added;
- sigc::signal<void, Signal &> signal_signal_removed;
+ sigc::signal<void, Object &> signal_object_added;
+ sigc::signal<void, Object &> signal_object_removed;
sigc::signal<void, Route &> signal_route_added;
sigc::signal<void, Route &> signal_route_removed;
sigc::signal<void, Zone &> signal_zone_added;
sigc::signal<void, Zone &> signal_zone_removed;
sigc::signal<void, Train &> signal_train_added;
sigc::signal<void, Train &> signal_train_removed;
- sigc::signal<void, Vehicle &> signal_vehicle_added;
- sigc::signal<void, Vehicle &> signal_vehicle_removed;
sigc::signal<void, Block &, Train *> signal_block_reserved;
sigc::signal<void, Sensor &, Sensor::State> signal_sensor_state_changed;
sigc::signal<void, const std::string &> signal_emergency;
Catalogue &catalogue;
Driver *driver;
std::string base;
- std::set<Track *> tracks;
- std::set<Signal *> signals;
+ Storage<Object> objects;
std::set<Route *> routes;
ZoneSet zones;
std::set<Block *> blocks;
std::set<Sensor *> sensors;
std::map<unsigned, Train *> trains;
- std::set<Vehicle *> vehicles;
Msp::Time::TimeStamp last_tick;
unsigned next_turnout_id;
Driver &get_driver() const;
const std::string &get_base() const { return base; }
- void add_track(Track &);
- const std::set<Track *> &get_tracks() const { return tracks; }
- Track *pick_track(const Ray &);
- void remove_track(Track &);
- unsigned allocate_turnout_id();
-
- void add_signal(Signal &);
- const std::set<Signal *> &get_signals() const { return signals; }
- Signal *pick_signal(const Ray &);
- void remove_signal(Signal &);
+ void add(Object &);
+ void add(Track &);
- Object *pick_object(const Ray &);
+ template<typename T>
+ const std::set<T *> &get_all() const;
-private:
template<typename T>
- static T *pick(const std::set<T *> &, const Ray &);
+ T *pick(const Ray &);
+
+ void remove(Object &);
+ void remove(Track &);
+
+ unsigned allocate_turnout_id();
-public:
void add_block(Block &);
Block &get_block(unsigned) const;
const std::set<Block *> &get_blocks() const { return blocks; }
const std::map<unsigned, Train *> &get_trains() const { return trains; }
void remove_train(Train &);
- void add_vehicle(Vehicle &);
- void remove_vehicle(Vehicle &);
-
void add_sensor(Sensor &);
void remove_sensor(Sensor &);
temporary(false)
{
layout.add_route(*this);
- layout.signal_track_removed.connect(sigc::mem_fun(this, &Route::track_removed));
+ layout.signal_object_removed.connect(sigc::mem_fun(this, &Route::object_removed));
}
Route::~Route()
return static_cast<RouteValidityMask>(result);
}
-void Route::track_removed(Track &t)
+void Route::object_removed(Object &o)
{
- tracks.erase(&t);
+ if(Track *t = dynamic_cast<Track *>(&o))
+ tracks.erase(t);
}
Route *Route::find(const TrackIter &from, Track &to)
void Route::Loader::finish()
{
- const set<Track *> <racks = obj.layout.get_tracks();
+ const set<Track *> <racks = obj.layout.get_all<Track>();
for(set<Track *>::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i)
{
unsigned tid = (*i)->get_turnout_id();
namespace R2C2 {
class Layout;
+class Object;
class Track;
class TrackIter;
class Zone;
void save(std::list<Msp::DataFile::Statement> &) const;
private:
RouteValidityMask check_validity(Track &) const;
- void track_removed(Track &);
+ void object_removed(Object &);
public:
static Route *find(const TrackIter &, Track &);
check_allocated_blocks(false),
passing(false)
{
- layout.add_signal(*this);
+ layout.add(*this);
layout.signal_block_reserved.connect(sigc::mem_fun(this, &Signal::block_reserved));
}
Signal::~Signal()
{
- layout.remove_signal(*this);
+ layout.remove(*this);
}
Signal *Signal::clone(Layout *to_layout) const
void Signal::update_location()
{
- const set<Track *> &tracks = layout.get_tracks();
+ const set<Track *> &tracks = layout.get_all<Track>();
float limit = layout.get_catalogue().get_gauge()*2;
float dist = -1;
for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
if(type.is_turnout())
turnout_id = layout.allocate_turnout_id();
- layout.add_track(*this);
+ layout.add(*this);
if(layout.has_driver())
layout.get_driver().signal_turnout.connect(sigc::mem_fun(this, &Track::turnout_event));
Track::~Track()
{
break_links();
- layout.remove_track(*this);
+ layout.remove(*this);
}
Track *Track::clone(Layout *to_layout) const
bogies.assign(type.get_bogies().begin(), type.get_bogies().end());
rods.assign(type.get_rods().begin(), type.get_rods().end());
- layout.add_vehicle(*this);
+ layout.add(*this);
}
Vehicle::~Vehicle()
detach_back();
if(prev)
detach_front();
- layout.remove_vehicle(*this);
+ layout.remove(*this);
}
Vehicle *Vehicle::clone(Layout *to_layout) const
virtual unsigned get_n_link_slots() const;
virtual Vehicle *get_link(unsigned) const;
virtual int get_link_slot(const Object &) const;
-
- virtual bool collide_ray(const Vector &, const Vector &) const { return false; }
};
} // namespace R2C2