]> git.tdb.fi Git - r2c2.git/blob - engineer/routerpanel.cpp
Don't crash if a train has no router
[r2c2.git] / engineer / routerpanel.cpp
1 #include <msp/core/maputils.h>
2 #include <msp/core/raii.h>
3 #include <msp/gltk/button.h>
4 #include <msp/gltk/column.h>
5 #include "libr2c2/layout.h"
6 #include "libr2c2/route.h"
7 #include "libr2c2/trainrouter.h"
8 #include "engineer.h"
9 #include "routerpanel.h"
10
11 using namespace std;
12 using namespace Msp;
13 using namespace R2C2;
14
15 string route_name(const Route *const &route)
16 {
17         return route ? route->get_name() : "(none)";
18 }
19
20 RouterPanel::RouterPanel(Engineer &e, Train &t):
21         engineer(e),
22         train(t),
23         routes(&route_name),
24         updating(false),
25         goto_pick(false),
26         goto_target(0),
27         goto_highlight(0)
28 {
29         Loader::WidgetMap widgets;
30         DataFile::load(*this, "data/routerpanel.ui", widgets);
31
32         lbl_route = dynamic_cast<GLtk::Label *>(get_item(widgets, "lbl_route"));
33         drp_routes = dynamic_cast<GLtk::Dropdown *>(get_item(widgets, "drp_routes"));
34         drp_routes->set_data(routes);
35         drp_routes->signal_item_selected.connect(sigc::mem_fun(this, &RouterPanel::route_selected));
36
37         dynamic_cast<GLtk::Button *>(get_item(widgets, "btn_goto"))->signal_clicked.connect(sigc::mem_fun(this, &RouterPanel::goto_clicked));
38
39         routes.append(0);
40         const set<Route *> &lroutes = train.get_layout().get_all<Route>();
41         for(set<Route *>::const_iterator i=lroutes.begin(); i!=lroutes.end(); ++i)
42                 if(!(*i)->is_temporary())
43                         routes.append(*i);
44
45         TrainRouter *router = train.get_ai_of_type<TrainRouter>();
46         if(!router)
47                 router = new TrainRouter(train);
48         update_route(router->get_route());
49
50         train.signal_ai_event.connect(sigc::mem_fun(this, &RouterPanel::ai_event));
51 }
52
53 void RouterPanel::ai_event(TrainAI &, const TrainAI::Message &msg)
54 {
55         if(msg.type=="route-changed")
56                 update_route(msg.value.value<const Route *>());
57 }
58
59 void RouterPanel::update_route(const Route *route)
60 {
61         SetFlag setf(updating);
62         if(route)
63                 lbl_route->set_text(route->get_name());
64         else
65                 lbl_route->set_text("Free run");
66         drp_routes->set_selected_index(routes.find(route));
67 }
68
69 void RouterPanel::route_selected(unsigned index)
70 {
71         if(!updating)
72         {
73                 const Route *route = routes.get(index);
74                 train.ai_message(TrainAI::Message("set-route", route));
75         }
76 }
77
78 void RouterPanel::goto_clicked()
79 {
80         goto_pick = true;
81         goto_target = 0;
82         signal_grab_pointer.emit();
83 }
84
85 void RouterPanel::button_press(int x, int y, unsigned btn)
86 {
87         Panel::button_press(x, y, btn);
88
89         if(goto_pick)
90         {
91                 signal_ungrab_pointer.emit();
92                 goto_pick = false;
93
94                 delete goto_highlight;
95                 goto_highlight = 0;
96
97                 if(goto_target && btn==1)
98                         train.ai_message(TrainAI::Message("set-destination-block", goto_target));
99         }
100 }
101
102 void RouterPanel::pointer_motion(int x, int y)
103 {
104         Panel::pointer_motion(x, y);
105         
106         if(goto_pick)
107         {
108                 int rx = x;
109                 int ry = y;
110                 map_coords_to_ancestor(rx, ry, *find_ancestor<GLtk::Root>());
111                 Ray ray = engineer.get_main_view().create_ray(rx, ry);
112                 Track *track = engineer.get_layout().pick<Track>(ray);
113                 if(track && &track->get_block()!=goto_target)
114                 {
115                         goto_target = &track->get_block();
116                         delete goto_highlight;
117                         goto_highlight = new TrackChain3D(engineer.get_layout_3d(), *goto_target);
118                         goto_highlight->set_color(GL::Color(0.7));
119                         goto_highlight->set_layer(2);
120                 }
121         }
122 }