]> git.tdb.fi Git - r2c2.git/commitdiff
Make designer work on generic objects
authorMikko Rasa <tdb@tdb.fi>
Mon, 6 May 2013 18:38:20 +0000 (21:38 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 6 May 2013 18:38:20 +0000 (21:38 +0300)
This introduces a lot of dynamic_casts and other ugliness, since not all
operations are generalized yet.  They'll be worked out in the near future.

source/designer/designer.cpp
source/designer/designer.h
source/designer/manipulator.cpp
source/designer/manipulator.h
source/designer/selection.cpp
source/designer/selection.h
source/designer/trackproperties.cpp
source/designer/trackwrap.cpp

index da897713c8a57987d6f0bd0dcd81a5bde4ca1786..edbec387d12cc6c7a0a161a5ba2814b862cb1a79 100644 (file)
@@ -198,7 +198,7 @@ void Designer::erase_tracks()
        if(mode!=SELECT)
                return;
 
-       set<Track *> tracks = selection.get_tracks();
+       set<Track *> tracks = selection.get_objects<Track>();
        selection.clear();
        for(set<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
        {
@@ -278,7 +278,7 @@ void Designer::add_selection_to_route()
 
        try
        {
-               cur_route->add_tracks(selection.get_tracks());
+               cur_route->add_tracks(selection.get_objects<Track>());
        }
        catch(const exception &e)
        {
@@ -317,7 +317,7 @@ void Designer::add_selection_to_zone()
 
        try
        {
-               cur_zone->add_tracks(selection.get_tracks());
+               cur_zone->add_tracks(selection.get_objects<Track>());
        }
        catch(const exception &e)
        {
@@ -412,7 +412,7 @@ void Designer::key_press(unsigned key)
                erase_tracks();
        else if(key==Msp::Input::KEY_F && shift)
        {
-               const set<Track *> &tracks = selection.get_tracks();
+               const set<Track *> &tracks = selection.get_objects<Track>();
                const set<Track *> &ltracks = layout->get_tracks();
                for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
                {
@@ -457,14 +457,14 @@ void Designer::button_press(unsigned btn)
        {
                if(btn==1)
                {
-                       Track *ctrack = pick_track(pointer);
-                       if(ctrack)
+                       Object *cobj = pick_object(pointer);
+                       if(cobj)
                        {
-                               Track *track = new Track(*layout, ctrack->get_type());
-                               track->set_position(ground);
+                               Object *obj = cobj->clone(layout);
+                               obj->set_position(ground);
 
                                selection.clear();
-                               selection.add_track(track);
+                               selection.add_object(obj);
 
                                mode = SELECT;
                        }
@@ -476,12 +476,12 @@ void Designer::button_press(unsigned btn)
        {
                if(btn==1)
                {
-                       Track *track = pick_track(pointer);
-                       if(track)
+                       Object *obj = pick_object(pointer);
+                       if(obj)
                        {
                                if(!shift)
                                        selection.clear();
-                               selection.toggle_track(track);
+                               selection.toggle_object(obj);
                        }
                }
        }
@@ -526,13 +526,13 @@ void Designer::track_removed(Track &trk)
                new_tracks.erase(i);
 }
 
-Track *Designer::pick_track(const Vector &pointer)
+Object *Designer::pick_object(const Vector &pointer)
 {
        View3D &view = *(mode==CATALOGUE ? cat_view : main_view);
        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_track(Vector(cpos.x, cpos.y, cpos.z), Vector(cray.x, cray.y, cray.z));
+       return view.get_layout().get_layout().pick_object(Vector(cpos.x, cpos.y, cpos.z), Vector(cray.x, cray.y, cray.z));
 }
 
 void Designer::update_track_icon(Track3D &track)
@@ -559,7 +559,7 @@ void Designer::update_track_icon(Track3D &track)
 
 void Designer::selection_changed()
 {
-       const set<Track *> &tracks = selection.get_tracks();
+       const set<Track *> &tracks = selection.get_objects<Track>();
        if(tracks.empty())
                lbl_status->set_text(string());
        else
@@ -611,7 +611,7 @@ void Designer::arrange_toolbars()
 
 void Designer::track_properties_response(int)
 {
-       const set<Track *> &tracks = selection.get_tracks();
+       const set<Track *> &tracks = selection.get_objects<Track>();
        for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
                update_track_icon(layout_3d->get_track(**i));
 }
@@ -630,17 +630,20 @@ void Designer::svg_export_accept(const string &text)
 
 string Designer::tooltip(int x, int y)
 {
-       if(Track *track = pick_track(Vector(x*2.0f/window.get_width()-1.0f, y*2.0f/window.get_height()-1.0f, 0)))
+       if(Object *obj = pick_object(Vector(x*2.0f/window.get_width()-1.0f, y*2.0f/window.get_height()-1.0f, 0)))
        {
-               const TrackType &ttype = track->get_type();
-               string info = format("%d %s", ttype.get_article_number(), ttype.get_description());
-               if(mode!=CATALOGUE && abs(track->get_slope())>1e-4)
-                       info += format(" (slope %.1f%%)", abs(track->get_slope()/ttype.get_total_length()*100));
-               if(track->get_turnout_id())
-                       info += format(" (turnout %d)", track->get_turnout_id());
-               else if(track->get_sensor_id())
-                       info += format(" (sensor %d)", track->get_sensor_id());
-
+               const ObjectType &otype = obj->get_type();
+               string info = format("%d %s", otype.get_article_number(), otype.get_description());
+               if(Track *track = dynamic_cast<Track *>(obj))
+               {
+                       const TrackType &ttype = track->get_type();
+                       if(mode!=CATALOGUE && abs(track->get_slope())>1e-4)
+                               info += format(" (slope %.1f%%)", abs(track->get_slope()/ttype.get_total_length()*100));
+                       if(track->get_turnout_id())
+                               info += format(" (turnout %d)", track->get_turnout_id());
+                       else if(track->get_sensor_id())
+                               info += format(" (sensor %d)", track->get_sensor_id());
+               }
                return info;
        }
 
index f22b25c181e161462e2dfd27a560824def6094e7..5dbb067af15e33528d7880508312c518c3bd8353 100644 (file)
@@ -115,7 +115,7 @@ private:
        void render();
        void track_added(R2C2::Track &);
        void track_removed(R2C2::Track &);
-       R2C2::Track *pick_track(const R2C2::Vector &);
+       R2C2::Object *pick_object(const R2C2::Vector &);
        void update_track_icon(R2C2::Track3D &);
        void selection_changed();
        void manipulation_status(const std::string &);
index 2e16311501ee112e6271ce0d9aa7bd3381d1a64c..5b95d5c4bddab072fbdce0c4d3b0588aa1925e70 100644 (file)
@@ -58,7 +58,7 @@ bool Manipulator::start_extend()
                cancel();
 
        bool ok = false;
-       const set<Track *> &stracks = selection.get_tracks();
+       const set<Track *> &stracks = selection.get_objects<Track>();
        for(set<Track *>::const_iterator i=stracks.begin(); (!ok && i!=stracks.end()); ++i)
        {
                const vector<Track *> &links = (*i)->get_links();
@@ -79,23 +79,20 @@ void Manipulator::duplicate()
        if(mode)
                cancel();
 
-       list<Track *> new_tracks;
-       for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+       list<Object *> new_objs;
+       for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
        {
-               Track *track = new Track(designer.get_layout(), i->track->get_type());
-               track->set_position(i->track->get_position());
-               track->set_rotation(i->track->get_rotation());
-               new_tracks.push_back(track);
+               Object *obj = i->object->clone(&designer.get_layout());
+               if(Track *track = dynamic_cast<Track *>(obj))
+               {
+                       for(list<Object *>::iterator j=new_objs.begin(); j!=new_objs.end(); ++j)
+                               if(Track *track2 = dynamic_cast<Track *>(*j))
+                                       track->snap_to(*track2, true);
+               }
+               new_objs.push_back(obj);
        }
 
-       selection.clear();
-       for(list<Track *>::iterator i=new_tracks.begin(); i!=new_tracks.end(); ++i)
-       {
-               selection.add_track(*i);
-               for(list<Track *>::iterator j=i; j!=new_tracks.end(); ++j)
-                       if(j!=i)
-                               (*i)->snap_to(**j, true);
-       }
+       selection.replace(new_objs.begin(), new_objs.end());
 }
 
 void Manipulator::flatten()
@@ -103,24 +100,30 @@ void Manipulator::flatten()
        if(mode)
                cancel();
 
-       if(tracks.empty()) return;
+       if(objects.empty())
+               return;
 
        float z = 0;
-       for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
-               z += i->track->get_position().z+i->track->get_slope()/2;
-       z /= tracks.size();
+       for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
+       {
+               z += i->object->get_position().z;
+               if(Track *track = dynamic_cast<Track *>(i->object))
+                       z += track->get_slope()/2;
+       }
+       z /= static_cast<int>(objects.size());
 
-       for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+       for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
        {
-               Vector p = i->track->get_position();
-               i->track->set_position(Vector(p.x, p.y, z));
-               i->track->set_slope(0);
+               Vector p = i->object->get_position();
+               i->object->set_position(Vector(p.x, p.y, z));
+               if(Track *track = dynamic_cast<Track *>(i->object))
+                       track->set_slope(0);
        }
 
        for(set<Track *>::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
                (*i)->check_slope();
 
-       update_tracks();
+       update_objects();
 }
 
 void Manipulator::even_slope(bool smooth)
@@ -131,13 +134,15 @@ void Manipulator::even_slope(bool smooth)
        if(neighbors.size()!=2)
                return;
 
-       for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
-               if(i->track->get_type().get_endpoints().size()!=2)
-                       return;
+       for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
+               if(Track *track = dynamic_cast<Track *>(i->object))
+                       if(track->get_type().get_endpoints().size()!=2)
+                               return;
 
        list<Track *> tracks2;
-       for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
-               tracks2.push_back(i->track);
+       for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
+               if(Track *track = dynamic_cast<Track *>(i->object))
+                       tracks2.push_back(track);
 
        float total_len = 0;
 
@@ -207,12 +212,20 @@ void Manipulator::even_slope(bool smooth)
        for(set<Track *>::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
                (*i)->check_slope();
 
-       update_tracks();
+       update_objects();
 }
 
 void Manipulator::connect()
 {
-       if(tracks.size()!=2)
+       if(objects.size()!=2)
+       {
+               signal_status.emit("Exactly two tracks must be selected");
+               return;
+       }
+
+       Track *track1 = dynamic_cast<Track *>(objects.front().object);
+       Track *track2 = dynamic_cast<Track *>(objects.back().object);
+       if(!track1 || !track2)
        {
                signal_status.emit("Exactly two tracks must be selected");
                return;
@@ -220,10 +233,8 @@ void Manipulator::connect()
 
        float limit = designer.get_layout().get_catalogue().get_gauge()/10;
 
-       Track *track1 = tracks.front().track;
        Vector pos1;
        float dir1;
-       Track *track2 = tracks.back().track;
        bool ok = false;
        float gap = 0;
        for(unsigned i=0; i<track1->get_type().get_endpoints().size(); ++i)
@@ -298,10 +309,10 @@ void Manipulator::cancel()
                return;
        mode = NONE;
 
-       for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+       for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
        {
-               i->track->set_position(Vector(center.x+i->pos.x, center.y+i->pos.y, center.z+i->pos.z));
-               i->track->set_rotation(i->rot);
+               i->object->set_position(Vector(center.x+i->pos.x, center.y+i->pos.y, center.z+i->pos.z));
+               i->object->set_rotation(i->rot);
        }
 
        for(set<Track *>::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
@@ -332,20 +343,22 @@ void Manipulator::button_press(unsigned btn)
                if(m!=EXTEND)
                {
                        for(set<Track *>::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
-                               for(vector<MTrack>::iterator j=tracks.begin(); j!=tracks.end(); ++j)
-                                       j->track->break_link(**i);
+                               for(vector<MObject>::iterator j=objects.begin(); j!=objects.end(); ++j)
+                                       if(Track *track = dynamic_cast<Track *>(j->object))
+                                               track->break_link(**i);
                }
 
                const set<Track *> &ltracks = designer.get_layout().get_tracks();
                for(set<Track *>::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i)
                {
                        bool ok = true;
-                       for(vector<MTrack>::iterator j=tracks.begin(); (j!=tracks.end() && ok); ++j)
-                               ok = (j->track!=*i);
+                       for(vector<MObject>::iterator j=objects.begin(); (j!=objects.end() && ok); ++j)
+                               ok = (j->object!=*i);
                        if(!ok) continue;
 
-                       for(vector<MTrack>::iterator j=tracks.begin(); j!=tracks.end(); ++j)
-                               j->track->snap_to(**i, true);
+                       for(vector<MObject>::iterator j=objects.begin(); j!=objects.end(); ++j)
+                               if(Track *track = dynamic_cast<Track *>(j->object))
+                                       track->snap_to(**i, true);
                }
 
                if(m==EXTEND)
@@ -355,7 +368,7 @@ void Manipulator::button_press(unsigned btn)
                }
                else
                {
-                       update_tracks();
+                       update_objects();
                        update_neighbors();
                }
 
@@ -375,42 +388,44 @@ void Manipulator::axis_motion(unsigned axis, float value, float)
        {
                Vector delta(gpointer.x-move_origin.x, gpointer.y-move_origin.y, 0);
                Vector offset(center.x+delta.x, center.y+delta.y, center.z);
-               for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+               for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
                {
-                       i->track->set_position(Vector(offset.x+i->pos.x, offset.y+i->pos.y, offset.z+i->pos.z));
-                       i->track->set_rotation(i->rot);
+                       i->object->set_position(Vector(offset.x+i->pos.x, offset.y+i->pos.y, offset.z+i->pos.z));
+                       i->object->set_rotation(i->rot);
                }
 
                const set<Track *> &ltracks = designer.get_layout().get_tracks();
                float limit = max(designer.get_layout().get_catalogue().get_gauge(),
                        designer.get_camera_controller().get_view_scale()/100.0f);
-               MTrack *snapped = 0;
+               MObject *snapped = 0;
                for(set<Track *>::const_iterator i=ltracks.begin(); (i!=ltracks.end() && !snapped); ++i)
                {
                        bool ok = true;
-                       for(vector<MTrack>::iterator j=tracks.begin(); (j!=tracks.end() && ok); ++j)
-                               ok = (j->track!=*i);
-                       if(!ok) continue;
+                       for(vector<MObject>::iterator j=objects.begin(); (j!=objects.end() && ok); ++j)
+                               ok = (j->object!=*i);
+                       if(!ok)
+                               continue;
 
-                       for(vector<MTrack>::iterator j=tracks.begin(); (j!=tracks.end() && !snapped); ++j)
-                               if(j->track->snap_to(**i, false, limit))
-                                       snapped = &*j;
+                       for(vector<MObject>::iterator j=objects.begin(); (j!=objects.end() && !snapped); ++j)
+                               if(Track *track = dynamic_cast<Track *>(j->object))
+                                       if(track->snap_to(**i, false, limit))
+                                               snapped = &*j;
                }
 
                if(snapped)
                {
-                       float da = snapped->track->get_rotation()-snapped->rot;
+                       float da = snapped->object->get_rotation()-snapped->rot;
                        float c = cos(da);
                        float s = sin(da);
-                       const Vector &sp = snapped->track->get_position();
-                       for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+                       const Vector &sp = snapped->object->get_position();
+                       for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
                        {
                                if(&*i==snapped)
                                        continue;
 
                                Vector dp(i->pos.x-snapped->pos.x, i->pos.y-snapped->pos.y, 0);
-                               i->track->set_position(Vector(sp.x+c*dp.x-s*dp.y, sp.y+s*dp.x+c*dp.y, sp.z+i->pos.z-snapped->pos.z));
-                               i->track->set_rotation(i->rot+da);
+                               i->object->set_position(Vector(sp.x+c*dp.x-s*dp.y, sp.y+s*dp.x+c*dp.y, sp.z+i->pos.z-snapped->pos.z));
+                               i->object->set_rotation(i->rot+da);
                        }
                }
        }
@@ -420,12 +435,12 @@ void Manipulator::axis_motion(unsigned axis, float value, float)
                angle += a-rot_origin;
                rot_origin = a;
 
-               for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+               for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
                {
                        float c = cos(angle);
                        float s = sin(angle);
-                       i->track->set_position(Vector(center.x+c*i->pos.x-s*i->pos.y, center.y+s*i->pos.x+c*i->pos.y, center.z+i->pos.z));
-                       i->track->set_rotation(angle+i->rot);
+                       i->object->set_position(Vector(center.x+c*i->pos.x-s*i->pos.y, center.y+s*i->pos.x+c*i->pos.y, center.z+i->pos.z));
+                       i->object->set_rotation(angle+i->rot);
                }
        }
        else if(mode==ELEVATE && axis==1)
@@ -434,8 +449,8 @@ void Manipulator::axis_motion(unsigned axis, float value, float)
 
                signal_status.emit(format("Elevation: %+.0fmm (%.0fmm)", dz*1000, (center.z+dz)*1000));
 
-               for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
-                       i->track->set_position(Vector(center.x+i->pos.x, center.y+i->pos.y, center.z+i->pos.z+dz));
+               for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
+                       i->object->set_position(Vector(center.x+i->pos.x, center.y+i->pos.y, center.z+i->pos.z+dz));
 
                for(set<Track *>::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
                        (*i)->check_slope();
@@ -445,16 +460,20 @@ void Manipulator::axis_motion(unsigned axis, float value, float)
                Vector pos;
                float dir = 0;
                float length = 0;
-               for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+               for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
                {
-                       unsigned n_endpoints = i->track->get_type().get_endpoints().size();
+                       Track *track = dynamic_cast<Track *>(i->object);
+                       if(!track)
+                               continue;
+
+                       unsigned n_endpoints = track->get_type().get_endpoints().size();
                        for(unsigned j=0; j<n_endpoints; ++j)
                        {
-                               if(i->track->get_link(j))
+                               if(track->get_link(j))
                                        continue;
 
-                               Vector ep_pos = i->track->get_endpoint_position(j);
-                               float ep_dir = i->track->get_endpoint_direction(j);
+                               Vector ep_pos = track->get_endpoint_position(j);
+                               float ep_dir = track->get_endpoint_direction(j);
                                float c = cos(ep_dir);
                                float s = sin(ep_dir);
                                float dx = gpointer.x-ep_pos.x;
@@ -507,51 +526,80 @@ void Manipulator::selection_changed()
        if(mode)
                cancel();
 
-       tracks.clear();
-       const set<Track *> &stracks = selection.get_tracks();
-       tracks.insert(tracks.end(), stracks.begin(), stracks.end());
+       objects.clear();
+       set<Object *> pending = selection.get_objects();
+       while(!pending.empty())
+       {
+               for(set<Object *>::iterator i=pending.begin(); i!=pending.end(); )
+               {
+                       if((*i)->get_parent() && pending.count((*i)->get_parent()))
+                               ++i;
+                       else
+                       {
+                               objects.push_back(*i);
+                               pending.erase(i++);
+                       }
+               }
+       }
 
        update_neighbors();
-       update_tracks();
+       update_objects();
 }
 
-void Manipulator::update_tracks()
+void Manipulator::update_objects()
 {
        Vector minp, maxp;
-       for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+       for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
        {
-               unsigned n_endpoints = i->track->get_type().get_endpoints().size();
-               for(unsigned j=0; j<n_endpoints; ++j)
+               // XXX Use generic bounding box when it is implemented
+               if(Track *track = dynamic_cast<Track *>(i->object))
                {
-                       Vector p = i->track->get_endpoint_position(j);
-                       if(i==tracks.begin() && j==0)
-                               minp = maxp = p;
-                       else
+                       unsigned n_endpoints = track->get_type().get_endpoints().size();
+                       for(unsigned j=0; j<n_endpoints; ++j)
                        {
-                               minp.x = min(minp.x, p.x);
-                               maxp.x = max(maxp.x, p.x);
-                               minp.y = min(minp.y, p.y);
-                               maxp.y = max(maxp.y, p.y);
-                               minp.z = min(minp.z, p.z);
+                               Vector p = track->get_endpoint_position(j);
+                               if(i==objects.begin() && j==0)
+                                       minp = maxp = p;
+                               else
+                               {
+                                       minp.x = min(minp.x, p.x);
+                                       maxp.x = max(maxp.x, p.x);
+                                       minp.y = min(minp.y, p.y);
+                                       maxp.y = max(maxp.y, p.y);
+                                       minp.z = min(minp.z, p.z);
+                               }
                        }
                }
+               else
+               {
+                       const Vector &p = i->object->get_position();
+                       minp.x = min(minp.x, p.x);
+                       maxp.x = max(maxp.x, p.x);
+                       minp.y = min(minp.y, p.y);
+                       maxp.y = max(maxp.y, p.y);
+                       minp.z = min(minp.z, p.z);
+               }
        }
 
        center = Vector((minp.x+maxp.x)/2, (minp.y+maxp.y)/2, minp.z);
-       for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+       for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
        {
-               const Vector &tp = i->track->get_position();
-               i->pos = Vector(tp.x-center.x, tp.y-center.y, tp.z-center.z);
-               i->rot = i->track->get_rotation();
+               const Vector &p = i->object->get_position();
+               i->pos = Vector(p.x-center.x, p.y-center.y, p.z-center.z);
+               i->rot = i->object->get_rotation();
        }
 }
 
 void Manipulator::update_neighbors()
 {
        neighbors.clear();
-       for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+       for(vector<MObject>::iterator i=objects.begin(); i!=objects.end(); ++i)
        {
-               const vector<Track *> &links = i->track->get_links();
+               Track *track = dynamic_cast<Track *>(i->object);
+               if(!track)
+                       continue;
+
+               const vector<Track *> &links = track->get_links();
                for(vector<Track *>::const_iterator j=links.begin(); j!=links.end(); ++j)
                {
                        if(!*j)
@@ -560,8 +608,8 @@ void Manipulator::update_neighbors()
                                continue;
 
                        bool ok = true;
-                       for(vector<MTrack>::iterator k=tracks.begin(); (k!=tracks.end() && ok); ++k)
-                               ok = (k->track!=*j);
+                       for(vector<MObject>::iterator k=objects.begin(); (k!=objects.end() && ok); ++k)
+                               ok = (k->object!=*j);
 
                        if(ok)
                                neighbors.insert(*j);
@@ -666,8 +714,8 @@ vector<Track *> Manipulator::create_straight(const R2C2::Vector &start, float di
 }
 
 
-Manipulator::MTrack::MTrack(Track *t):
-       track(t),
-       pos(track->get_position()),
-       rot(track->get_rotation())
+Manipulator::MObject::MObject(Object *o):
+       object(o),
+       pos(object->get_position()),
+       rot(object->get_rotation())
 { }
index b4216eefd52354f1d6c6aedacc2cf87290afa49a..cb4759ac7ad1a671e757b598cc67945199ccbba0 100644 (file)
@@ -18,13 +18,13 @@ private:
                EXTEND
        };
 
-       struct MTrack
+       struct MObject
        {
-               R2C2::Track *track;
+               R2C2::Object *object;
                R2C2::Vector pos;
                float rot;
 
-               MTrack(R2C2::Track *);
+               MObject(R2C2::Object *);
        };
 
        struct TrackOrder
@@ -43,7 +43,7 @@ private:
        Designer &designer;
        Msp::Input::Mouse &mouse;
        Selection &selection;
-       std::vector<MTrack> tracks;
+       std::vector<MObject> objects;
        R2C2::Vector center;
 
        R2C2::Vector pointer;
@@ -72,7 +72,7 @@ private:
        void button_press(unsigned);
        void axis_motion(unsigned, float, float);
        void selection_changed();
-       void update_tracks();
+       void update_objects();
        void update_neighbors();
        void set_slope(TrackOrder &, float, float);
        std::vector<R2C2::Track *> create_straight(const R2C2::Vector &, float, float, float);
index 855b41cc5e91538d0b4ab062c961af94ff4b5677..c93dd3628e5840394e9c190aaa53d2419e06282f 100644 (file)
@@ -6,36 +6,36 @@ using namespace std;
 using namespace R2C2;
 using namespace Msp;
 
-Track *Selection::get_track() const
+Object *Selection::get_object() const
 {
-       if(tracks.empty())
+       if(objects.empty())
                return 0;
        else
-               return *tracks.begin();
+               return *objects.begin();
 }
 
 void Selection::clear()
 {
-       tracks.clear();
+       objects.clear();
        signal_changed.emit();
 }
 
-void Selection::add_track(Track *t)
+void Selection::add_object(Object *o)
 {
-       if(tracks.insert(t).second)
+       if(objects.insert(o).second)
                signal_changed.emit();
 }
 
-void Selection::remove_track(Track *t)
+void Selection::remove_object(Object *o)
 {
-       if(tracks.erase(t))
+       if(objects.erase(o))
                signal_changed.emit();
 }
 
-void Selection::toggle_track(Track *t)
+void Selection::toggle_object(Object *o)
 {
-       if(!tracks.erase(t))
-               tracks.insert(t);
+       if(!objects.erase(o))
+               objects.insert(o);
 
        signal_changed.emit();
 }
@@ -43,17 +43,18 @@ void Selection::toggle_track(Track *t)
 void Selection::select_more()
 {
        set<Track *> new_tracks;
-       for(set<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
-       {
-               const vector<Track *> &links = (*i)->get_links();
-               for(vector<Track *>::const_iterator j=links.begin(); j!=links.end(); ++j)
-                       if(*j)
-                               new_tracks.insert(*j);
-       }
+       for(set<Object *>::iterator i=objects.begin(); i!=objects.end(); ++i)
+               if(Track *track = dynamic_cast<Track *>(*i))
+               {
+                       const vector<Track *> &links = track->get_links();
+                       for(vector<Track *>::const_iterator j=links.begin(); j!=links.end(); ++j)
+                               if(*j)
+                                       new_tracks.insert(*j);
+               }
 
        bool changed = false;
        for(set<Track *>::iterator i=new_tracks.begin(); i!=new_tracks.end(); ++i)
-               if(tracks.insert(*i).second)
+               if(objects.insert(*i).second)
                        changed = true;
 
        if(changed)
@@ -63,7 +64,11 @@ void Selection::select_more()
 void Selection::select_linked()
 {
        bool changed = false;
-       list<Track *> queue(tracks.begin(), tracks.end());
+       list<Track *> queue;
+       for(set<Object *>::iterator i=objects.begin(); i!=objects.end(); ++i)
+               if(Track *track = dynamic_cast<Track *>(*i))
+                       queue.push_back(track);
+
        while(!queue.empty())
        {
                Track *track = queue.front();
@@ -71,19 +76,12 @@ void Selection::select_linked()
 
                const vector<Track *> &links = track->get_links();
                for(vector<Track *>::const_iterator j=links.begin(); j!=links.end(); ++j)
-                       if(*j && tracks.insert(*j).second)
+                       if(*j && objects.insert(*j).second)
                        {
                                queue.push_back(*j);
                                changed = true;
                        }
        }
-       for(set<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
-       {
-               const vector<Track *> &links = (*i)->get_links();
-               for(vector<Track *>::const_iterator j=links.begin(); j!=links.end(); ++j)
-                       if(*j && tracks.insert(*j).second)
-                               changed = true;
-       }
 
        if(changed)
                signal_changed.emit();
@@ -92,16 +90,14 @@ void Selection::select_linked()
 void Selection::select_blocks()
 {
        bool changed = false;
-       for(set<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
-       {
-               const set<Track *> &btracks = (*i)->get_block().get_tracks();
-               for(set<Track *>::iterator j=btracks.begin(); j!=btracks.end(); ++j)
-                       if(!tracks.count(*j))
-                       {
-                               tracks.insert(*j);
-                               changed = true;
-                       }
-       }
+       for(set<Object *>::iterator i=objects.begin(); i!=objects.end(); ++i)
+               if(Track *track = dynamic_cast<Track *>(*i))
+               {
+                       const set<Track *> &btracks = track->get_block().get_tracks();
+                       for(set<Track *>::iterator j=btracks.begin(); j!=btracks.end(); ++j)
+                               if(objects.insert(*j).second)
+                                       changed = true;
+               }
 
        if(changed)
                signal_changed.emit();
index acf8bf6bf09131a415a6a3a8b56037c86d2e9b22..89f7100e3e6e854945219bf074ad7f4ff3388e4f 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <set>
 #include <sigc++/sigc++.h>
-#include "3d/track.h"
+#include "libr2c2/object.h"
 
 class Selection
 {
@@ -11,27 +11,47 @@ public:
        sigc::signal<void> signal_changed;
 
 private:
-       std::set<R2C2::Track *> tracks;
+       std::set<R2C2::Object *> objects;
 
 public:
-       const std::set<R2C2::Track *> &get_tracks() const { return tracks; }
-       R2C2::Track *get_track() const;
-       unsigned size() const { return tracks.size(); }
-       bool empty() const { return tracks.empty(); }
+       const std::set<R2C2::Object *> &get_objects() const { return objects; }
+       R2C2::Object *get_object() const;
+
+       template<typename T>
+       std::set<T *> get_objects() const
+       {
+               std::set<T *> result;
+               for(std::set<R2C2::Object *>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
+                       if(T *to = dynamic_cast<T *>(*i))
+                               result.insert(to);
+               return result;
+       }
+
+       template<typename T>
+       T *get_object() const
+       {
+               for(std::set<R2C2::Object *>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
+                       if(T *to = dynamic_cast<T *>(*i))
+                               return to;
+               return 0;
+       }
+
+       unsigned size() const { return objects.size(); }
+       bool empty() const { return objects.empty(); }
 
        void clear();
 
        template<typename Iter>
        void replace(Iter begin, Iter end)
        {
-               tracks.clear();
-               tracks.insert(begin, end);
+               objects.clear();
+               objects.insert(begin, end);
                signal_changed.emit();
        }
 
-       void add_track(R2C2::Track *);
-       void remove_track(R2C2::Track *);
-       void toggle_track(R2C2::Track *);
+       void add_object(R2C2::Object *);
+       void remove_object(R2C2::Object *);
+       void toggle_object(R2C2::Object *);
 
        void select_more();
        void select_linked();
index cdb5cb0855b5b62a3c1e37eb0b013b040c1d5b89..9753849eccf3aadae3b4d937e7dbb51e2baecc64 100644 (file)
@@ -1,5 +1,6 @@
 #include <msp/gltk/button.h>
 #include <msp/gltk/label.h>
+#include "libr2c2/track.h"
 #include "libr2c2/tracktype.h"
 #include "selection.h"
 #include "trackproperties.h"
@@ -42,11 +43,11 @@ TrackProperties::TrackProperties(const Selection &s):
 
        if(selection.size()==1)
        {
-               if(unsigned tid = selection.get_track()->get_turnout_id())
+               if(unsigned tid = selection.get_object<Track>()->get_turnout_id())
                        ent_turnout_id->set_text(lexical_cast<string>(tid));
        }
 
-       const set<Track *> &tracks = selection.get_tracks();
+       const set<Track *> &tracks = selection.get_objects<Track>();
        int sensor_id = -1;
        for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
        {
@@ -69,7 +70,7 @@ void TrackProperties::on_response(int code)
        {
                if(selection.size()==1)
                {
-                       Track *track = selection.get_track();
+                       Track *track = selection.get_object<Track>();
                        if(track->get_type().is_turnout())
                                track->set_turnout_id(lexical_cast<unsigned>(ent_turnout_id->get_text()));
                }
@@ -78,7 +79,7 @@ void TrackProperties::on_response(int code)
                if(!sensor_id_text.empty())
                {
                        unsigned sensor_id = lexical_cast<unsigned>(sensor_id_text);
-                       const set<Track *> &tracks = selection.get_tracks();
+                       const set<Track *> &tracks = selection.get_objects<Track>();
                        for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
                                if(!(*i)->get_type().is_turnout())
                                        (*i)->set_sensor_id(sensor_id);
index 523c9678658c0b31acc94c66f42728eb6571c85d..863434fb3d1299d5433f5547e77b1ce7f05621eb 100644 (file)
@@ -37,7 +37,7 @@ void TrackWrap::render(GL::Renderer &renderer, const GL::Tag &) const
 void TrackWrap::selection_changed()
 {
        wraps.clear();
-       const set<Track *> &tracks = selection.get_tracks();
+       const set<Track *> &tracks = selection.get_objects<Track>();
        for(set<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
        {
                Wrap wrap;