*/
#include <cmath>
-#include <msp/gltk/button.h>
#include <msp/strings/formatter.h>
#include "libmarklin/timetable.h"
#include "libmarklin/vehicletype.h"
#include "timetabledialog.h"
#include "trainpanel.h"
#include "trainproperties.h"
+#include "trainview.h"
using namespace std;
using namespace Msp;
Widget(r),
Panel(r),
engineer(e),
- train(t)
+ train(t),
+ expanded(false)
{
- set_size(200, 175);
+ set_size(200, 65);
train.signal_control_changed.connect(sigc::mem_fun(this, &TrainPanel::train_control_changed));
- add(*(lbl_addr=new GLtk::Label(res, format("%2d", train.get_address()))));
+ add(*(pnl_basic = new GLtk::Panel(res)));
+ pnl_basic->set_style("group");
+ pnl_basic->set_geometry(GLtk::Geometry(0, geom.h-58, geom.w, 45));
+
+ pnl_basic->add(*(lbl_addr = new GLtk::Label(res, format("%2d", train.get_address()))));
lbl_addr->set_style("digital");
- lbl_addr->set_geometry(GLtk::Geometry(10, geom.h-30, 35, 20));
+ lbl_addr->set_geometry(GLtk::Geometry(10, 28, 35, 20));
- add(*(lbl_name=new GLtk::Label(res, train.get_name())));
+ pnl_basic->add(*(lbl_name = new GLtk::Label(res, train.get_name())));
lbl_name->set_style("digital");
- lbl_name->set_geometry(GLtk::Geometry(50, geom.h-30, geom.w-55, 20));
+ lbl_name->set_geometry(GLtk::Geometry(50, 28, geom.w-77, 20));
train.signal_name_changed.connect(sigc::mem_fun(lbl_name, &GLtk::Label::set_text));
- add(*(lbl_speed=new GLtk::Label(res, " 0")));
+ pnl_basic->add(*(lbl_speed = new GLtk::Label(res, " 0")));
lbl_speed->set_style("digital");
- lbl_speed->set_geometry(GLtk::Geometry(10, geom.h-55, 35, 20));
+ lbl_speed->set_geometry(GLtk::Geometry(10, 3, 35, 20));
- add(*(sld_speed=new GLtk::HSlider(res)));
- sld_speed->set_geometry(GLtk::Geometry(50, geom.h-50, geom.w-80, 10));
+ pnl_basic->add(*(sld_speed = new GLtk::HSlider(res)));
+ sld_speed->set_geometry(GLtk::Geometry(50, 8, geom.w-80, 10));
sld_speed->set_range(0, 200);
sld_speed->set_step(5);
sld_speed->signal_value_changed.connect(sigc::mem_fun(this, &TrainPanel::speed_slider_changed));
- add(*(tgl_forward=new GLtk::Toggle(res)));
+ pnl_basic->add(*(tgl_forward = new GLtk::Toggle(res)));
tgl_forward->set_text("Fwd");
- tgl_forward->set_geometry(GLtk::Geometry(geom.w-30, geom.h-58, 20, 27));
+ tgl_forward->set_geometry(GLtk::Geometry(geom.w-30, 0, 20, 27));
tgl_forward->set_value(true);
tgl_forward->signal_toggled.connect(sigc::mem_fun(this, &TrainPanel::forward_toggled));
+ pnl_basic->add(*(btn_expand = new GLtk::Button(res)));
+ btn_expand->set_style("arrow_down");
+ btn_expand->set_geometry(GLtk::Geometry(geom.w-22, 28, 12, 20));
+ btn_expand->signal_clicked.connect(sigc::mem_fun(this, &TrainPanel::expand_clicked));
+
+ add(*(pnl_extra = new GLtk::Panel(res)));
+ pnl_extra->set_style("group");
+ pnl_extra->set_geometry(GLtk::Geometry(0, 10, geom.w, 135));
+ pnl_extra->set_visible(false);
+
const Route *route = train.get_route();
- add(*(lbl_route=new GLtk::Label(res, (route ? route->get_name() : "Free run"))));
+ pnl_extra->add(*(lbl_route = new GLtk::Label(res, (route ? route->get_name() : "Free run"))));
lbl_route->set_style("digital");
- lbl_route->set_geometry(GLtk::Geometry(10, 65, geom.w-20, 20));
+ lbl_route->set_geometry(GLtk::Geometry(10, 85, geom.w-20, 20));
train.signal_route_changed.connect(sigc::mem_fun(this, &TrainPanel::train_route_changed));
- add(*(lbl_status=new GLtk::Label(res, train.get_status())));
+ pnl_extra->add(*(lbl_status = new GLtk::Label(res, train.get_status())));
lbl_status->set_style("digital");
- lbl_status->set_geometry(GLtk::Geometry(10, 40, geom.w-20, 20));
+ lbl_status->set_geometry(GLtk::Geometry(10, 60, geom.w-20, 20));
train.signal_status_changed.connect(sigc::mem_fun(this, &TrainPanel::train_status_changed));
const map<unsigned, string> &funcs = train.get_locomotive_type().get_functions();
string fname = i->second;
fname[0] = toupper(fname[0]);
GLtk::Toggle *tgl;
- add(*(tgl=new GLtk::Toggle(res)));
+ pnl_extra->add(*(tgl = new GLtk::Toggle(res)));
tgl->set_text(fname);
- tgl->set_geometry(GLtk::Geometry(x, geom.h-87, 36, 27));
+ tgl->set_geometry(GLtk::Geometry(x, 108, 36, 27));
tgl->set_value(train.get_function(i->first));
tgl->signal_toggled.connect(sigc::bind(sigc::mem_fun(this, &TrainPanel::func_toggled), i->first));
GLtk::Button *btn;
- add(*(btn=new GLtk::Button(res, "Edit")));
- btn->set_geometry(GLtk::Geometry(geom.w-46, 10, 36, 25));
+ pnl_extra->add(*(btn = new GLtk::Button(res, "Edit")));
+ btn->set_geometry(GLtk::Geometry(10, 30, 36, 25));
btn->signal_clicked.connect(sigc::mem_fun(this, &TrainPanel::edit_clicked));
- add(*(btn=new GLtk::Button(res, "Place")));
- btn->set_geometry(GLtk::Geometry(geom.w-82, 10, 36, 25));
+ pnl_extra->add(*(btn = new GLtk::Button(res, "Place")));
+ btn->set_geometry(GLtk::Geometry(10, 0, 36, 25));
btn->signal_clicked.connect(sigc::mem_fun(this, &TrainPanel::place_clicked));
- add(*(btn=new GLtk::Button(res, "GoTo")));
- btn->set_geometry(GLtk::Geometry(geom.w-118, 10, 36, 25));
+ pnl_extra->add(*(btn = new GLtk::Button(res, "Take")));
+ btn->set_geometry(GLtk::Geometry(46, 0, 36, 25));
+ btn->signal_clicked.connect(sigc::mem_fun(this, &TrainPanel::take_clicked));
+
+ pnl_extra->add(*(btn = new GLtk::Button(res, "GoTo")));
+ btn->set_geometry(GLtk::Geometry(100, 0, 36, 25));
btn->signal_clicked.connect(sigc::mem_fun(this, &TrainPanel::goto_clicked));
- add(*(btn=new GLtk::Button(res, "Route")));
- btn->set_geometry(GLtk::Geometry(geom.w-154, 10, 36, 25));
+ pnl_extra->add(*(btn = new GLtk::Button(res, "Route")));
+ btn->set_geometry(GLtk::Geometry(100, 30, 36, 25));
btn->signal_clicked.connect(sigc::mem_fun(this, &TrainPanel::route_clicked));
- add(*(btn=new GLtk::Button(res, "TTbl")));
- btn->set_geometry(GLtk::Geometry(geom.w-190, 10, 36, 25));
+ pnl_extra->add(*(btn = new GLtk::Button(res, "TTbl")));
+ btn->set_geometry(GLtk::Geometry(46, 30, 36, 25));
btn->signal_clicked.connect(sigc::mem_fun(this, &TrainPanel::timetable_clicked));
+
+ pnl_extra->add(*(btn = new GLtk::Button(res, "View")));
+ btn->set_geometry(GLtk::Geometry(geom.w-46, 30, 36, 25));
+ btn->signal_clicked.connect(sigc::mem_fun(this, &TrainPanel::view_clicked));
+}
+
+void TrainPanel::expand(bool e)
+{
+ expanded = e;
+ pnl_extra->set_visible(expanded);
+ if(expanded)
+ {
+ set_size(geom.w, 205);
+ btn_expand->set_style("arrow_up");
+ }
+ else
+ {
+ set_size(geom.w, 65);
+ btn_expand->set_style("arrow_down");
+ }
+ pnl_basic->set_geometry(GLtk::Geometry(0, geom.h-58, geom.w, 45));
+ engineer.rearrange_panels();
}
void TrainPanel::train_control_changed(const string &control, float value)
pick_conn = engineer.signal_pick_done.connect(sigc::mem_fun(this, &TrainPanel::place));
}
+void TrainPanel::take_clicked()
+{
+ train.unplace();
+}
+
void TrainPanel::edit_clicked()
{
TrainProperties *dialog = new TrainProperties(engineer, res, &train);
engineer.get_root().add(*dialog);
dialog->set_position(geom.x+geom.w, geom.y+geom.h-dialog->get_geometry().h);
- dialog->set_visible(true);
}
void TrainPanel::route_clicked()
RouteSelect *dialog = new RouteSelect(engineer, res, train);
engineer.get_root().add(*dialog);
dialog->set_position(geom.x+geom.w, geom.y+geom.h-dialog->get_geometry().h);
- dialog->set_visible(true);
}
void TrainPanel::goto_clicked()
dialog->set_position(geom.x+geom.w, geom.y+geom.h-dialog->get_geometry().h);
}
+void TrainPanel::view_clicked()
+{
+ TrainView *dialog = new TrainView(engineer, train);
+ engineer.get_root().add(*dialog);
+ dialog->set_position(geom.x+geom.w, geom.y+geom.h-dialog->get_geometry().h);
+}
+
+void TrainPanel::expand_clicked()
+{
+ expand(!expanded);
+}
+
void TrainPanel::speed_slider_changed(double value)
{
float speed = value/3.6*engineer.get_layout().get_catalogue().get_scale();
--- /dev/null
+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2010 Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#include <msp/gl/tests.h>
+#include <msp/gltk/button.h>
+#include <msp/gltk/image.h>
+#include "libmarklin/vehicle.h"
+#include "libmarklin/vehicletype.h"
+#include "engineer.h"
+#include "trainview.h"
+
+using namespace Msp;
+using namespace Marklin;
+
+TrainView::TrainView(Engineer &e, const Train &t):
+ GLtk::Widget(e.get_ui_resources()),
+ GLtk::Panel(e.get_ui_resources()),
+ engineer(e),
+ train(t),
+ mode(SIDE),
+ pipeline(280, 280, false),
+ stale(false)
+{
+ set_size(300, 330);
+
+ tex.set_min_filter(GL::LINEAR);
+ tex.storage(GL::RGB, 280, 280, 0);
+ tex.image(0, GL::RGB, GL::UNSIGNED_BYTE, 0);
+ fbo.attach(GL::COLOR_ATTACHMENT0, tex, 0);
+ depth.storage(GL::DEPTH_COMPONENT, 280, 280);
+ fbo.attach(GL::DEPTH_ATTACHMENT, depth);
+
+ camera.set_up_direction(GL::Vector3(0, 0, 1));
+ camera.set_depth_clip(0.01, 10);
+ camera.set_aspect(1);
+ pipeline.set_camera(&camera);
+
+ pipeline.add_renderable(engineer.get_layout_3d().get_scene());
+
+ GL::PipelinePass *pass = &pipeline.add_pass(0);
+ pass->depth_test = &GL::DepthTest::lequal();
+ pass->lighting = &engineer.get_lighting();
+
+ GLtk::Image *image;
+ add(*(image = new GLtk::Image(res, &tex)));
+ image->set_geometry(GLtk::Geometry(10, 40, geom.w-20, geom.h-50));
+
+ GLtk::Button *btn;
+
+ add(*(btn = new GLtk::Button(res, "Roof")));
+ btn->set_geometry(GLtk::Geometry(10, 10, 36, 25));
+ btn->signal_clicked.connect(sigc::bind(sigc::mem_fun(this, &TrainView::set_mode), ROOF));
+
+ add(*(btn = new GLtk::Button(res, "Side")));
+ btn->set_geometry(GLtk::Geometry(46, 10, 36, 25));
+ btn->signal_clicked.connect(sigc::bind(sigc::mem_fun(this, &TrainView::set_mode), SIDE));
+
+ add(*(btn = new GLtk::Button(res, "Head")));
+ btn->set_geometry(GLtk::Geometry(82, 10, 36, 25));
+ btn->signal_clicked.connect(sigc::bind(sigc::mem_fun(this, &TrainView::set_mode), HEAD));
+
+ add(*(btn = new GLtk::Button(res, "Close")));
+ btn->set_geometry(GLtk::Geometry(geom.w-46, 10, 36, 25));
+ btn->signal_clicked.connect(sigc::mem_fun(this, &TrainView::close_clicked));
+
+ engineer.add_train_view(*this);
+}
+
+TrainView::~TrainView()
+{
+ engineer.remove_train_view(*this);
+}
+
+void TrainView::set_mode(Mode m)
+{
+ mode = m;
+}
+
+void TrainView::prepare()
+{
+ const Vehicle &veh = train.get_vehicle(0);
+ const Point &pos = veh.get_position();
+ float angle = veh.get_direction();
+ float c = cos(angle);
+ float s = sin(angle);
+ float l = veh.get_type().get_length();
+
+ switch(mode)
+ {
+ case ROOF:
+ camera.set_position(GL::Vector3(pos.x-l*c, pos.y-l*s, pos.z+0.07));
+ camera.set_look_direction(GL::Vector3(c, s, -0.2));
+ break;
+ case SIDE:
+ camera.set_position(GL::Vector3(pos.x-l*0.8*c+0.05*s, pos.y-l*0.8*s-0.05*c, pos.z+0.03));
+ camera.set_look_direction(GL::Vector3(c-0.2*s, s+0.2*c, 0));
+ break;
+ case HEAD:
+ camera.set_position(GL::Vector3(pos.x+l*0.55*c, pos.y+l*0.55*s, pos.z+0.03));
+ camera.set_look_direction(GL::Vector3(c, s, 0));
+ break;
+ }
+
+ GL::Bind _bind_fbo(fbo);
+ fbo.clear(GL::COLOR_BUFFER_BIT|GL::DEPTH_BUFFER_BIT);
+ pipeline.render_all();
+}
+
+void TrainView::button_release(int x, int y, unsigned btn)
+{
+ GLtk::Panel::button_release(x, y, btn);
+ if(stale)
+ delete this;
+}
+
+void TrainView::close_clicked()
+{
+ stale = true;
+}