]> git.tdb.fi Git - r2c2.git/blob - source/designer/selectionwrap.cpp
Don't crash if a train has no router
[r2c2.git] / source / designer / selectionwrap.cpp
1 #include <msp/gl/matrix.h>
2 #include <msp/gl/meshbuilder.h>
3 #include <msp/gl/renderer.h>
4 #include "selection.h"
5 #include "selectionwrap.h"
6
7 using namespace std;
8 using namespace Msp;
9 using namespace R2C2;
10
11 SelectionWrap::SelectionWrap(Selection &s):
12         selection(s)
13 {
14         selection.signal_changed.connect(sigc::mem_fun(this, &SelectionWrap::selection_changed));
15 }
16
17 SelectionWrap::~SelectionWrap()
18 {
19         for(map<const ObjectType *, GL::Mesh *>::iterator i=meshes.begin(); i!=meshes.end(); ++i)
20                 delete i->second;
21         for(map<const Object *, GL::Mesh *>::iterator i=transient_meshes.begin(); i!=transient_meshes.end(); ++i)
22                 delete i->second;
23 }
24
25 void SelectionWrap::render(GL::Renderer &renderer, const GL::Tag &) const
26 {
27         for(list<Wrap>::const_iterator i=wraps.begin(); i!=wraps.end(); ++i)
28         {
29                 GL::MatrixStack::Push push(renderer.matrix_stack());
30                 const Vector &pos = i->object->get_position();
31                 renderer.matrix_stack() *= GL::Matrix::translation(pos+GL::Vector3(0, 0, 0.001));
32                 renderer.matrix_stack() *= GL::Matrix::rotation(i->object->get_rotation(), 0, 0, 1);
33                 i->mesh->draw(renderer);
34         }
35 }
36
37 void SelectionWrap::selection_changed()
38 {
39         wraps.clear();
40         const set<Object *> &objects = selection.get_objects();
41         for(set<Object *>::iterator i=objects.begin(); i!=objects.end(); ++i)
42         {
43                 Wrap wrap;
44                 wrap.object = *i;
45                 wrap.mesh = &get_mesh(**i);
46                 wraps.push_back(wrap);
47         }
48
49         set<const Object *> cobjects(objects.begin(), objects.end());
50         for(map<const Object *, GL::Mesh *>::iterator i=transient_meshes.begin(); i!=transient_meshes.end(); )
51         {
52                 if(!cobjects.count(i->first))
53                 {
54                         delete i->second;
55                         transient_meshes.erase(i++);
56                 }
57                 else
58                         ++i;
59         }
60 }
61
62 const GL::Mesh &SelectionWrap::get_mesh(const Object &obj)
63 {
64         map<const Object *, GL::Mesh *>::iterator i = transient_meshes.find(&obj);
65         if(i!=transient_meshes.end())
66                 return *i->second;
67
68         const ObjectType &type = obj.get_type();
69         map<const ObjectType *, GL::Mesh *>::iterator j = meshes.find(&type);
70         if(j!=meshes.end())
71                 return *j->second;
72
73         GL::Mesh *mesh = new GL::Mesh((GL::COLOR4_UBYTE, GL::VERTEX2));
74         GL::MeshBuilder bld(*mesh);
75         bld.color(0.0f, 1.0f, 0.0f, 1.0f);
76
77         const Shape *shape = obj.get_shape();
78         if(!shape)
79                 throw logic_error("No shape");
80         
81         Geometry::BoundingBox<float, 3> bbox = shape->get_axis_aligned_bounding_box();
82         const Vector &min_pt = bbox.get_minimum_point();
83         const Vector &max_pt = bbox.get_maximum_point();
84
85         bld.begin(GL::LINE_LOOP);
86         bld.vertex(min_pt.x-0.005, min_pt.y-0.005);
87         bld.vertex(max_pt.x+0.005, min_pt.y-0.005);
88         bld.vertex(max_pt.x+0.005, max_pt.y+0.005);
89         bld.vertex(min_pt.x-0.005, max_pt.y+0.005);
90         bld.end();
91
92         if(shape!=type.get_shape())
93                 transient_meshes[&obj] = mesh;
94         else
95                 meshes[&type] = mesh;
96
97         return *mesh;
98 }