add_type<GL::Program>().creator(&Catalogue3D::create<GL::Program>);
add_type<GL::Technique>().creator(&Catalogue3D::create<GL::Technique>);
- catalogue.signal_track_added.connect(sigc::mem_fun(this, &Catalogue3D::track_added));
- catalogue.signal_vehicle_added.connect(sigc::mem_fun(this, &Catalogue3D::vehicle_added));
- catalogue.signal_signal_added.connect(sigc::mem_fun(this, &Catalogue3D::signal_added));
+ catalogue.signal_object_added.connect(sigc::mem_fun(this, &Catalogue3D::object_added));
- const Catalogue::TrackMap &trks = catalogue.get_tracks();
- for(Catalogue::TrackMap::const_iterator i=trks.begin(); i!=trks.end(); ++i)
- track_added(*i->second);
- const Catalogue::SignalMap &sigs = catalogue.get_signals();
- for(Catalogue::SignalMap::const_iterator i=sigs.begin(); i!=sigs.end(); ++i)
- signal_added(*i->second);
+ const Catalogue::ObjectMap &objs = catalogue.get_all();
+ for(Catalogue::ObjectMap::const_iterator i=objs.begin(); i!=objs.end(); ++i)
+ object_added(*i->second);
build_endpoint_mesh();
}
Catalogue3D::~Catalogue3D()
{
- for(map<const TrackType *, TrackType3D *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(map<const ObjectType *, ObjectType3D *>::iterator i=objects.begin(); i!=objects.end(); ++i)
delete i->second;
- for(map<const VehicleType *, VehicleType3D *>::iterator i=vehicles.begin(); i!=vehicles.end(); ++i)
- delete i->second;
- for(map<const SignalType *, SignalType3D *>::iterator i=signals.begin(); i!=signals.end(); ++i)
- delete i->second;
-}
-
-const TrackType3D &Catalogue3D::get_track(const TrackType &tt) const
-{
- return *get_item(tracks, &tt);
-}
-
-const VehicleType3D &Catalogue3D::get_vehicle(const VehicleType &vt) const
-{
- return *get_item(vehicles, &vt);
-}
-
-const SignalType3D &Catalogue3D::get_signal(const SignalType &vt) const
-{
- return *get_item(signals, &vt);
-}
-
-void Catalogue3D::track_added(const TrackType &track)
-{
- tracks[&track] = new TrackType3D(*this, track);
}
-void Catalogue3D::vehicle_added(const VehicleType &veh)
+void Catalogue3D::object_added(const ObjectType &ot)
{
- vehicles[&veh] = new VehicleType3D(*this, veh);
+ if(const TrackType *tt = dynamic_cast<const TrackType *>(&ot))
+ objects[&ot] = new TrackType3D(*this, *tt);
+ else if(const SignalType *st = dynamic_cast<const SignalType *>(&ot))
+ objects[&ot] = new SignalType3D(*this, *st);
+ else if(const VehicleType *vt = dynamic_cast<const VehicleType *>(&ot))
+ objects[&ot] = new VehicleType3D(*this, *vt);
}
-void Catalogue3D::signal_added(const SignalType &sig)
+const ObjectType3D &Catalogue3D::get_3d(const ObjectType &ot) const
{
- signals[&sig] = new SignalType3D(*this, sig);
+ return *get_item(objects, &ot);
}
void Catalogue3D::build_endpoint_mesh()
#include <msp/gl/material.h>
#include <msp/gl/mesh.h>
#include "libr2c2/catalogue.h"
+#include "typemap.h"
namespace R2C2 {
-class SignalType3D;
-class TrackType3D;
-class VehicleType3D;
+class ObjectType3D;
class Catalogue3D: public Msp::DataFile::Collection
{
private:
Catalogue &catalogue;
- std::map<const TrackType *, TrackType3D *> tracks;
- std::map<const VehicleType *, VehicleType3D *> vehicles;
- std::map<const SignalType *, SignalType3D *> signals;
+ std::map<const ObjectType *, ObjectType3D *> objects;
Msp::GL::Mesh endpoint_mesh;
public:
~Catalogue3D();
const Catalogue &get_catalogue() const { return catalogue; }
- const TrackType3D &get_track(const TrackType &) const;
- const VehicleType3D &get_vehicle(const VehicleType &) const;
- const SignalType3D &get_signal(const SignalType &) const;
- const Msp::GL::Mesh &get_endpoint_mesh() const { return endpoint_mesh; }
private:
- void track_added(const TrackType &);
- void vehicle_added(const VehicleType &);
- void signal_added(const SignalType &);
+ void object_added(const ObjectType &);
+public:
+ const ObjectType3D &get_3d(const ObjectType &) const;
+
+ template<typename T>
+ const typename TypeMap3D<T>::Type3D &get_3d(const T &ot) const
+ { return dynamic_cast<const typename TypeMap3D<T>::Type3D &>(get_3d(static_cast<const ObjectType &>(ot))); }
+
+private:
void build_endpoint_mesh();
+public:
+ const Msp::GL::Mesh &get_endpoint_mesh() const { return endpoint_mesh; }
+private:
Msp::FS::Path locate_file(const std::string &);
template<typename T>
--- /dev/null
+#ifndef R2C2_3D_OBJECTTYPE_H_
+#define R2C2_3D_OBJECTTYPE_H_
+
+namespace R2C2 {
+
+class Catalogue3D;
+
+class ObjectType3D
+{
+protected:
+ Catalogue3D &catalogue;
+
+ ObjectType3D(Catalogue3D &c): catalogue(c) { }
+public:
+ virtual ~ObjectType3D() { }
+};
+
+} // namespace R2C2
+
+#endif
Signal3D::Signal3D(Layout3D &l, Signal &s):
Object3D(l, s),
- GL::ObjectInstance(l.get_catalogue().get_signal(s.get_type()).get_object()),
+ GL::ObjectInstance(l.get_catalogue().get_3d(s.get_type()).get_object()),
signal(s)
{
layout.get_scene().add(*this);
namespace R2C2 {
SignalType3D::SignalType3D(Catalogue3D &c, const SignalType &type):
- catalogue(c),
+ ObjectType3D(c),
object(catalogue.get<GL::Object>(type.get_object()))
{ }
#include <msp/gl/object.h>
#include "libr2c2/signaltype.h"
+#include "objecttype.h"
namespace R2C2 {
-class Catalogue3D;
-
-class SignalType3D
+class SignalType3D: public ObjectType3D
{
private:
- Catalogue3D &catalogue;
Msp::GL::Object &object;
public:
Track3D::Track3D(Layout3D &l, Track &t):
Object3D(l, t),
- GL::ObjectInstance(l.get_catalogue().get_track(t.get_type()).get_object()),
+ GL::ObjectInstance(l.get_catalogue().get_3d(t.get_type()).get_object()),
track(t),
- type(layout.get_catalogue().get_track(track.get_type()))
+ type(layout.get_catalogue().get_3d(track.get_type()))
{
layout.get_scene().add(*this);
namespace R2C2 {
-TrackType3D::TrackType3D(Catalogue3D &cat3d, const TrackType &tt):
- catalogue(cat3d),
+TrackType3D::TrackType3D(Catalogue3D &c, const TrackType &tt):
+ ObjectType3D(c),
mesh(0),
object(0),
own_data(false)
{
- const Catalogue &cat = cat3d.get_catalogue();
+ const Catalogue &cat = catalogue.get_catalogue();
const vector<TrackPart> &parts = tt.get_parts();
const Profile &ballast_profile = cat.get_ballast_profile();
#include <msp/gl/object.h>
#include "libr2c2/profile.h"
#include "libr2c2/tracktype.h"
+#include "objecttype.h"
namespace R2C2 {
-class Catalogue3D;
-
-class TrackType3D
+class TrackType3D: public ObjectType3D
{
private:
- Catalogue3D &catalogue;
Msp::GL::Mesh *mesh;
Msp::GL::Object *object;
bool own_data;
#include <msp/core/meta.h>
#include "signal.h"
+#include "signaltype.h"
#include "track.h"
+#include "tracktype.h"
#include "vehicle.h"
+#include "vehicletype.h"
namespace R2C2 {
{ };
template<> struct TypeMap3D<Signal> { typedef Signal3D Type3D; };
+template<> struct TypeMap3D<SignalType> { typedef SignalType3D Type3D; };
template<> struct TypeMap3D<Track> { typedef Track3D Type3D; };
+template<> struct TypeMap3D<TrackType> { typedef TrackType3D Type3D; };
template<> struct TypeMap3D<Vehicle> { typedef Vehicle3D Type3D; };
+template<> struct TypeMap3D<VehicleType> { typedef VehicleType3D Type3D; };
} // namespace R2C2
Vehicle3D::Vehicle3D(Layout3D &l, Vehicle &v):
Object3D(l, v),
- GL::ObjectInstance(*l.get_catalogue().get_vehicle(v.get_type()).get_body_object()),
+ GL::ObjectInstance(*l.get_catalogue().get_3d(v.get_type()).get_body_object()),
vehicle(v),
- type(layout.get_catalogue().get_vehicle(vehicle.get_type()))
+ type(layout.get_catalogue().get_3d(vehicle.get_type()))
{
unsigned n_axles = vehicle.get_type().get_axles().size();
for(unsigned i=0; i<n_axles; ++i)
namespace R2C2 {
VehicleType3D::VehicleType3D(Catalogue3D &c, const VehicleType &t):
- catalogue(c),
+ ObjectType3D(c),
type(t),
body_object(0)
{
#include <msp/gl/mesh.h>
#include <msp/gl/object.h>
#include "libr2c2/vehicletype.h"
+#include "objecttype.h"
namespace R2C2 {
-class Catalogue3D;
-
-class VehicleType3D
+class VehicleType3D: public ObjectType3D
{
private:
- Catalogue3D &catalogue;
const VehicleType &type;
std::map<std::string, Msp::GL::Object *> objects;
Msp::GL::Object *body_object;
vector<Track *> ExtendTool::create_straight(const Vector &start, const Angle &dir, float length, float limit)
{
- const Catalogue::TrackMap &track_types = designer.get_catalogue().get_tracks();
+ const Catalogue::ObjectMap &object_types = designer.get_catalogue().get_all();
map<float, const TrackType *> types_by_length;
unsigned preference = 0;
- for(Catalogue::TrackMap::const_iterator i=track_types.begin(); i!=track_types.end(); ++i)
- {
- const vector<TrackPart> &parts = i->second->get_parts();
- if(parts.size()!=1)
- continue;
- if(parts.front().is_curved() || parts.front().is_dead_end())
- continue;
+ for(Catalogue::ObjectMap::const_iterator i=object_types.begin(); i!=object_types.end(); ++i)
+ if(const TrackType *tt = dynamic_cast<const TrackType *>(i->second))
+ {
+ const vector<TrackPart> &parts = tt->get_parts();
+ if(parts.size()!=1)
+ continue;
+ if(parts.front().is_curved() || parts.front().is_dead_end())
+ continue;
- types_by_length[parts.front().get_length()] = i->second;
- preference = max(preference, i->second->get_autofit_preference());
- }
+ types_by_length[parts.front().get_length()] = tt;
+ preference = max(preference, tt->get_autofit_preference());
+ }
vector<float> lengths;
float removed = 0;
drp_protocol->set_selected_index(0);
- const Catalogue::VehicleMap &cat_vtypes = engineer.get_layout().get_catalogue().get_vehicles();
- for(Catalogue::VehicleMap::const_iterator i=cat_vtypes.begin(); i!=cat_vtypes.end(); ++i)
- if(i->second->is_locomotive())
- loco_types.append(i->second);
+ const Catalogue::ObjectMap &obj_types = engineer.get_layout().get_catalogue().get_all();
+ for(Catalogue::ObjectMap::const_iterator i=obj_types.begin(); i!=obj_types.end(); ++i)
+ if(const VehicleType *vt = dynamic_cast<const VehicleType *>(i->second))
+ if(vt->is_locomotive())
+ loco_types.append(vt);
}
void NewTrainDialog::on_response(int code)
dynamic_cast<GLtk::Button *>(get_item(widgets, "btn_add"))->signal_clicked.connect(sigc::mem_fun(this, &NewVehicleDialog::add_clicked));
- const Catalogue::VehicleMap &cat_vtypes = train.get_layout().get_catalogue().get_vehicles();
- for(Catalogue::VehicleMap::const_iterator i=cat_vtypes.begin(); i!=cat_vtypes.end(); ++i)
- {
- if(i->second->is_locomotive())
- loco_types.append(i->second);
- else
- wagon_types.append(i->second);
- }
+ const Catalogue::ObjectMap &obj_types = train.get_layout().get_catalogue().get_all();
+ for(Catalogue::ObjectMap::const_iterator i=obj_types.begin(); i!=obj_types.end(); ++i)
+ if(const VehicleType *vt = dynamic_cast<const VehicleType *>(i->second))
+ {
+ if(vt->is_locomotive())
+ loco_types.append(vt);
+ else
+ wagon_types.append(vt);
+ }
}
void NewVehicleDialog::toggle_list(bool show, GLtk::List *lst)
Catalogue::~Catalogue()
{
- for(TrackMap::iterator i=tracks.begin(); i!=tracks.end(); ++i)
- delete i->second;
- for(SignalMap::iterator i=signals.begin(); i!=signals.end(); ++i)
- delete i->second;
- for(VehicleMap::iterator i=vehicles.begin(); i!=vehicles.end(); ++i)
+ for(ObjectMap::iterator i=objects.begin(); i!=objects.end(); ++i)
delete i->second;
}
return ballast_profile.get_height()+rail_profile.get_height();
}
-void Catalogue::add_track(TrackType &track)
-{
- insert_unique(tracks, track.get_article_number(), &track);
- signal_track_added.emit(track);
-}
-
-const TrackType &Catalogue::get_track(const ArticleNumber &art_nr) const
-{
- return *get_item(tracks, art_nr);
-}
-
-void Catalogue::add_vehicle(VehicleType &veh)
-{
- insert_unique(vehicles, veh.get_article_number(), &veh);
- signal_vehicle_added.emit(veh);
-}
-
-const VehicleType &Catalogue::get_vehicle(const ArticleNumber &art_nr) const
-{
- return *get_item(vehicles, art_nr);
-}
-
-void Catalogue::add_signal(SignalType &sig)
+void Catalogue::add(ObjectType &object)
{
- insert_unique(signals, sig.get_article_number(), &sig);
- signal_signal_added.emit(sig);
+ insert_unique(objects, object.get_article_number(), &object);
+ signal_object_added.emit(object);
}
-const SignalType &Catalogue::get_signal(const ArticleNumber &art_nr) const
+const ObjectType &Catalogue::get(const ArticleNumber &art_nr) const
{
- return *get_item(signals, art_nr);
+ return *get_item(objects, art_nr);
}
void Catalogue::Loader::signal(ArticleNumber art_nr)
{
- if(obj.signals.count(art_nr))
+ if(obj.objects.count(art_nr))
throw key_error(art_nr);
RefPtr<SignalType> sig = new SignalType(art_nr);
load_sub(*sig);
- obj.add_signal(*sig.release());
+ obj.add(*sig.release());
}
void Catalogue::Loader::track(ArticleNumber art_nr)
{
- if(obj.tracks.count(art_nr))
+ if(obj.objects.count(art_nr))
throw key_error(art_nr);
RefPtr<TrackType> trk = new TrackType(art_nr);
load_sub(*trk);
- obj.add_track(*trk.release());
+ obj.add(*trk.release());
}
void Catalogue::Loader::vehicle(ArticleNumber art_nr)
{
- if(obj.vehicles.count(art_nr))
+ if(obj.objects.count(art_nr))
throw key_error(art_nr);
RefPtr<VehicleType> veh = new VehicleType(art_nr);
load_sub(*veh);
- obj.add_vehicle(*veh.release());
+ obj.add(*veh.release());
}
} // namespace R2C2
namespace R2C2 {
-class SignalType;
-class TrackType;
-class VehicleType;
+class ObjectType;
class Catalogue
{
void vehicle(ArticleNumber);
};
- typedef std::map<ArticleNumber, TrackType *> TrackMap;
- typedef std::map<ArticleNumber, VehicleType *> VehicleMap;
- typedef std::map<ArticleNumber, SignalType *> SignalMap;
+ typedef std::map<ArticleNumber, ObjectType *> ObjectMap;
- sigc::signal<void, const TrackType &> signal_track_added;
- sigc::signal<void, const VehicleType &> signal_vehicle_added;
- sigc::signal<void, const SignalType &> signal_signal_added;
+ sigc::signal<void, const ObjectType &> signal_object_added;
private:
float scale;
Profile rail_profile;
Profile ballast_profile;
std::string track_technique;
- TrackMap tracks;
- VehicleMap vehicles;
- SignalMap signals;
+ ObjectMap objects;
Layout layout;
public:
const Profile &get_ballast_profile() const { return ballast_profile; }
const std::string &get_track_technique() const { return track_technique; }
- void add_track(TrackType &);
- const TrackType &get_track(const ArticleNumber &) const;
- const TrackMap &get_tracks() const { return tracks; }
+ void add(ObjectType &);
+ const ObjectType &get(const ArticleNumber &) const;
+ const ObjectMap &get_all() const { return objects; }
- void add_vehicle(VehicleType &);
- const VehicleType &get_vehicle(const ArticleNumber &) const;
- const VehicleMap &get_vehicles() const { return vehicles; }
-
- void add_signal(SignalType &);
- const SignalType &get_signal(const ArticleNumber &) const;
- const SignalMap &get_signals() const { return signals; }
+ template<typename T>
+ const T &get(const ArticleNumber &an) const
+ { return dynamic_cast<const T &>(get(an)); }
Layout &get_layout() { return layout; }
};
void Layout::Loader::signal(ArticleNumber art_nr)
{
- Signal *sig = new Signal(obj, obj.catalogue.get_signal(art_nr));
+ Signal *sig = new Signal(obj, obj.catalogue.get<SignalType>(art_nr));
load_sub(*sig);
}
void Layout::Loader::track(ArticleNumber art_nr)
{
- Track *trk = new Track(obj, obj.catalogue.get_track(art_nr));
+ Track *trk = new Track(obj, obj.catalogue.get<TrackType>(art_nr));
load_sub(*trk);
new_tracks = true;
const set<Track *> &tracks = obj.objects.get<Track>();
void Layout::Loader::train(ArticleNumber art_nr, unsigned addr, const std::string &proto)
{
- Train *trn = new Train(obj, obj.catalogue.get_vehicle(art_nr), addr, proto);
+ Train *trn = new Train(obj, obj.catalogue.get<VehicleType>(art_nr), addr, proto);
load_sub(*trn);
}
void Train::Loader::vehicle(ArticleNumber art_nr)
{
- const VehicleType &vtype = obj.layout.get_catalogue().get_vehicle(art_nr);
+ const VehicleType &vtype = obj.layout.get_catalogue().get<VehicleType>(art_nr);
Vehicle *veh = new Vehicle(obj.layout, vtype);
obj.vehicles.back()->attach_back(*veh);
obj.vehicles.push_back(veh);
NetTrain::NetTrain(Client &c, const TrainInfoPacket &pkt):
client(c),
- loco_type(client.get_catalogue().get_vehicle(pkt.loco_type)),
+ loco_type(client.get_catalogue().get<VehicleType>(pkt.loco_type)),
address(pkt.address),
name(pkt.name),
functions(0)