]> git.tdb.fi Git - r2c2.git/blobdiff - source/engineer/controlpanel.cpp
Reflect the current state of functions in a newly opened train dialog
[r2c2.git] / source / engineer / controlpanel.cpp
index e81d25c366d9b671b7193a312b84e3853232aed7..cc2fa079fbebc03bd984ee8d74e4b44380f20a9e 100644 (file)
@@ -6,6 +6,7 @@
 #include "libr2c2/vehicle.h"
 #include "controlpanel.h"
 #include "engineer.h"
+#include "placementghost.h"
 #include "trainview.h"
 
 using namespace std;
@@ -15,7 +16,8 @@ using namespace R2C2;
 ControlPanel::ControlPanel(Engineer &e, Train &t):
        engineer(e),
        train(t),
-       updating(false)
+       updating(false),
+       placing(false)
 {
        Loader::WidgetMap widgets;
        DataFile::load(*this, "data/controlpanel.ui", widgets);
@@ -34,6 +36,7 @@ ControlPanel::ControlPanel(Engineer &e, Train &t):
        for(VehicleType::FunctionMap::const_iterator i=funcs.begin(); i!=funcs.end(); ++i)
        {
                GLtk::Toggle *tgl = new GLtk::Toggle(i->second);
+               tgl->set_value(train.get_function(i->first));
                tgl->signal_toggled.connect(sigc::bind(sigc::mem_fun(this, &ControlPanel::ui_function_toggled), i->first));
                pnl_functions->add(*tgl);
                tgl_funcs[i->first] = tgl;
@@ -58,14 +61,13 @@ void ControlPanel::train_function_changed(unsigned func, bool value)
 
 void ControlPanel::place_clicked()
 {
-       pick_conn = engineer.signal_pick_done.connect(sigc::mem_fun(this, &ControlPanel::place_pick_done));
-       engineer.pick(true);
-}
+       signal_grab_pointer.emit();
+       placing = true;
 
-void ControlPanel::place_pick_done(Track *track, unsigned ep)
-{
-       pick_conn.disconnect();
-       train.place(TrackIter(track, ep).block_iter());
+       Layout3D &layout3d = engineer.get_layout_3d();
+       unsigned n_vehs = train.get_n_vehicles();
+       for(unsigned i=0; i<n_vehs; ++i)
+               ghosts.push_back(new PlacementGhost(layout3d, train.get_vehicle(i).get_type()));
 }
 
 void ControlPanel::take_clicked()
@@ -75,11 +77,64 @@ void ControlPanel::take_clicked()
 
 void ControlPanel::view_clicked()
 {
-       GLtk::Container *root = parent;
-       while(root->get_parent())
-               root = root->get_parent();
-
        TrainView *dlg = new TrainView(engineer, train);
-       root->add(*dlg);
+       find_ancestor<GLtk::Root>()->add(*dlg);
        dlg->autosize();
 }
+
+void ControlPanel::button_press(int x, int y, unsigned btn)
+{
+       Panel::button_press(x, y, btn);
+
+       if(placing)
+       {
+               signal_ungrab_pointer.emit();
+               placing = false;
+
+               for(vector<PlacementGhost *>::iterator i=ghosts.begin(); i!=ghosts.end(); ++i)
+                       delete *i;
+               ghosts.clear();
+
+               if(btn==1 && place_location)
+                       train.place(place_location);
+       }
+}
+
+void ControlPanel::pointer_motion(int x, int y)
+{
+       Panel::pointer_motion(x, y);
+
+       if(placing)
+       {
+               int rx = x;
+               int ry = y;
+               map_coords_to_ancestor(rx, ry, *find_ancestor<GLtk::Root>());
+               Ray ray = engineer.get_main_view().create_ray(rx, ry);
+               Vector ground = ray.get_start()-ray.get_direction()*ray.get_start().z/ray.get_direction().z;
+               Track *track = engineer.get_layout().pick<Track>(ray);
+               if(track)
+               {
+                       const vector<Block::Endpoint> &eps = track->get_block().get_endpoints();
+                       int closest_ep = -1;
+                       float closest_dist = -1;
+                       for(unsigned i=0; i<eps.size(); ++i)
+                       {
+                               Snap sn = eps[i].track->get_snap_node(eps[i].track_ep);
+                               float d = (sn.position-ground).norm();
+                               if(d<closest_dist || closest_dist<0)
+                               {
+                                       closest_ep = i;
+                                       closest_dist = d;
+                               }
+                       }
+
+                       if(closest_ep>=0)
+                       {
+                               place_location = BlockIter(&track->get_block(), closest_ep);
+                               ghosts.back()->place(place_location.track_iter());
+                               for(unsigned i=ghosts.size()-1; i--; )
+                                       ghosts[i]->place_before(*ghosts[i+1]);
+                       }
+               }
+       }
+}