]> git.tdb.fi Git - r2c2.git/blob - source/libr2c2/vehicletype.cpp
Allow rotating the body object of a vehicle
[r2c2.git] / source / libr2c2 / vehicletype.cpp
1 #include <msp/core/maputils.h>
2 #include <msp/strings/format.h>
3 #include "vehicletype.h"
4
5 using namespace std;
6 using namespace Msp;
7
8 namespace R2C2 {
9
10 VehicleType::VehicleType(const ArticleNumber &an):
11         art_nr(an),
12         locomotive(false),
13         swap_direction(false),
14         length(0),
15         width(0),
16         height(0),
17         rotate_object(false)
18 { }
19
20 unsigned VehicleType::get_max_function() const
21 {
22         if(functions.empty())
23                 return 0;
24         return (--functions.end())->first;
25 }
26
27 const VehicleType::Axle &VehicleType::get_fixed_axle(unsigned i) const
28 {
29         if(i>=axles.size())
30                 throw out_of_range("VehicleType::get_fixed_axle");
31         return axles[i];
32 }
33
34 const VehicleType::Bogie &VehicleType::get_bogie(unsigned i) const
35 {
36         if(i>=bogies.size())
37                 throw out_of_range("VehicleType::get_bogie");
38         return bogies[i];
39 }
40
41 const VehicleType::Axle &VehicleType::get_bogie_axle(unsigned i, unsigned j) const
42 {
43         if(i>=bogies.size())
44                 throw out_of_range("VehicleType::get_bogie_axle");
45         if(j>=bogies[i].axles.size())
46                 throw out_of_range("VehicleType::get_bogie_axle");
47         return bogies[i].axles[j];
48 }
49
50 const VehicleType::Rod &VehicleType::get_rod(unsigned i) const
51 {
52         if(i>=rods.size())
53                 throw out_of_range("VehicleType::get_rod");
54         return rods[i];
55 }
56
57 float VehicleType::get_front_axle_offset() const
58 {
59         float front = length/2;
60         if(!axles.empty())
61                 front = axles.front().position;
62         if(!bogies.empty())
63         {
64                 const Bogie &bogie = bogies.front();
65                 front = max(front, bogie.position+bogie.axles.front().position);
66         }
67         return front;
68 }
69
70 float VehicleType::get_back_axle_offset() const
71 {
72         float back = -length/2;
73         if(!axles.empty())
74                 back = axles.back().position;
75         if(!bogies.empty())
76         {
77                 const Bogie &bogie = bogies.back();
78                 back = min(back, bogie.position+bogie.axles.back().position);
79         }
80         return back;
81 }
82
83
84 VehicleType::Axle::Axle():
85         position(0),
86         wheel_dia(0),
87         powered(false)
88 { }
89
90
91 VehicleType::Bogie::Bogie():
92         position(0),
93         rotate_object(false)
94 { }
95
96
97 VehicleType::Rod::Rod():
98         pivot(BODY),
99         pivot_index(0),
100         pivot_index2(0),
101         limit(ROTATE),
102         connect_index(-1),
103         mirror_object(false)
104 { }
105
106
107 VehicleType::Loader::Loader(VehicleType &vt):
108         DataFile::ObjectLoader<VehicleType>(vt)
109 {
110         add("axle",       &Loader::axle);
111         add("bogie",      &Loader::bogie);
112         add("function",   &Loader::function);
113         add("height",     &Loader::height);
114         add("length",     &Loader::length);
115         add("locomotive", &VehicleType::locomotive);
116         add("name",       &VehicleType::name);
117         add("object",     &VehicleType::object);
118         add("rod",        &Loader::rod);
119         add("rotate_object", &VehicleType::rotate_object);
120         add("swap_direction", &VehicleType::swap_direction);
121         add("width",      &Loader::width);
122 }
123
124 void VehicleType::Loader::axle()
125 {
126         Axle axl;
127         load_sub(axl);
128         obj.axles.push_back(axl);
129 }
130
131 void VehicleType::Loader::bogie()
132 {
133         Bogie bog;
134         load_sub(bog);
135         obj.bogies.push_back(bog);
136 }
137
138 void VehicleType::Loader::function(unsigned i, const string &f)
139 {
140         obj.functions[i] = f;
141 }
142
143 void VehicleType::Loader::height(float h)
144 {
145         obj.height = h/1000;
146 }
147
148 void VehicleType::Loader::length(float l)
149 {
150         obj.length = l/1000;
151 }
152
153 void VehicleType::Loader::rod()
154 {
155         Rod rd;
156         Rod::Loader ldr(rd, rod_tags);
157         load_sub_with(ldr);
158         obj.rods.push_back(rd);
159         if(!ldr.get_tag().empty())
160                 rod_tags[ldr.get_tag()] = obj.rods.size()-1;
161         rod_tags["previous"] = obj.rods.size()-1;
162 }
163
164 void VehicleType::Loader::width(float w)
165 {
166         obj.width = w/1000;
167 }
168
169
170 VehicleType::Axle::Loader::Loader(Axle &a):
171         DataFile::ObjectLoader<Axle>(a)
172 {
173         add("object",         &Axle::object);
174         add("position",       &Loader::position);
175         add("powered",        &Axle::powered);
176         add("wheel_diameter", &Loader::wheel_diameter);
177 }
178
179 void VehicleType::Axle::Loader::position(float p)
180 {
181         obj.position = p/1000;
182 }
183
184 void VehicleType::Axle::Loader::wheel_diameter(float d)
185 {
186         obj.wheel_dia = d/1000;
187 }
188
189
190 VehicleType::Bogie::Loader::Loader(Bogie &b):
191         DataFile::ObjectLoader<Bogie>(b)
192 {
193         add("axle",          &Loader::axle);
194         add("object",        &Bogie::object);
195         add("position",      &Loader::position);
196         add("rotate_object", &Bogie::rotate_object);
197 }
198
199 void VehicleType::Bogie::Loader::axle()
200 {
201         Axle axl;
202         load_sub(axl);
203         obj.axles.push_back(axl);
204 }
205
206 void VehicleType::Bogie::Loader::position(float p)
207 {
208         obj.position = p/1000;
209 }
210
211
212 VehicleType::Rod::Loader::Loader(Rod &r, const map<string, unsigned> &t):
213         DataFile::ObjectLoader<Rod>(r),
214         tags(t)
215 {
216         add("connect",       &Loader::connect);
217         add("limit",         &Rod::limit);
218         add("mirror_object", &Rod::mirror_object);
219         add("object",        &Rod::object);
220         add("pivot_body",    &Loader::pivot_body);
221         add("pivot_axle",    &Loader::pivot_axle);
222         add("pivot_axle",    &Loader::pivot_bogie_axle);
223         add("pivot_rod",     &Loader::pivot_rod);
224         add("position",      &Loader::position);
225         add("tag",           &Loader::set_tag);
226 }
227
228 void VehicleType::Rod::Loader::connect(const string &t, float px, float pz, float ox, float oz)
229 {
230         obj.connect_index = get_item(tags, t);
231         obj.connect_point = Vector(px/1000, 0, pz/1000);
232         obj.connect_offset = Vector(ox/1000, 0, oz/1000);
233 }
234
235 void VehicleType::Rod::Loader::pivot_body()
236 {
237         obj.pivot = BODY;
238 }
239
240 void VehicleType::Rod::Loader::pivot_axle(unsigned i)
241 {
242         obj.pivot = AXLE;
243         obj.pivot_index = i;
244 }
245
246 void VehicleType::Rod::Loader::pivot_bogie_axle(unsigned i, unsigned j)
247 {
248         obj.pivot = BOGIE_AXLE;
249         obj.pivot_index = i;
250         obj.pivot_index2 = j;
251 }
252
253 void VehicleType::Rod::Loader::pivot_rod(const string &t)
254 {
255         obj.pivot_index = get_item(tags, t);
256         obj.pivot = ROD;
257 }
258
259 void VehicleType::Rod::Loader::position(float x, float y, float z)
260 {
261         obj.pivot_point = Vector(x/1000, y/1000, z/1000);
262 }
263
264 void VehicleType::Rod::Loader::set_tag(const string &t)
265 {
266         tag = t;
267 }
268
269
270 void operator>>(const LexicalConverter &c, VehicleType::Rod::Limit &l)
271 {
272         const string &s = c.get();
273         if(s=="FIXED")
274                 l = VehicleType::Rod::FIXED;
275         else if(s=="ROTATE")
276                 l = VehicleType::Rod::ROTATE;
277         else if(s=="SLIDE_X")
278                 l = VehicleType::Rod::SLIDE_X;
279         else
280                 throw lexical_error(format("conversion of '%s' to Rod::Limit", s));
281 }
282
283 } // namespace R2C2