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