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