-/* $Id$
-
-This file is part of R²C²
-Copyright © 2010 Mikkosoft Productions, Mikko Rasa
-Distributed under the GPL
-*/
-
+#include <msp/core/maputils.h>
+#include <msp/geometry/box.h>
+#include <msp/geometry/transformedshape.h>
+#include <msp/strings/format.h>
#include "vehicletype.h"
using namespace std;
namespace R2C2 {
VehicleType::VehicleType(const ArticleNumber &an):
- art_nr(an),
+ ObjectType(an),
locomotive(false),
+ swap_direction(false),
length(0),
width(0),
- height(0)
+ height(0),
+ rotate_object(false)
{ }
unsigned VehicleType::get_max_function() const
return (--functions.end())->first;
}
+const VehicleType::Axle &VehicleType::get_axle(unsigned i) const
+{
+ if(i>=axles.size())
+ throw out_of_range("VehicleType::get_axle");
+ return axles[i];
+}
+
+const VehicleType::Axle &VehicleType::get_fixed_axle(unsigned i) const
+{
+ if(i>=fixed_axles.size())
+ throw out_of_range("VehicleType::get_fixed_axle");
+ return *fixed_axles[i];
+}
+
+const VehicleType::Bogie &VehicleType::get_bogie(unsigned i) const
+{
+ if(i>=bogies.size())
+ throw out_of_range("VehicleType::get_bogie");
+ return bogies[i];
+}
+
+const VehicleType::Axle &VehicleType::get_bogie_axle(unsigned i, unsigned j) const
+{
+ if(i>=bogies.size())
+ throw out_of_range("VehicleType::get_bogie_axle");
+ if(j>=bogies[i].axles.size())
+ throw out_of_range("VehicleType::get_bogie_axle");
+ return *bogies[i].axles[j];
+}
+
+const VehicleType::Rod &VehicleType::get_rod(unsigned i) const
+{
+ if(i>=rods.size())
+ throw out_of_range("VehicleType::get_rod");
+ return rods[i];
+}
+
float VehicleType::get_front_axle_offset() const
{
- float front = length/2;
if(!axles.empty())
- front = axles.front().position;
- if(!bogies.empty())
- {
- const Bogie &bogie = bogies.front();
- front = max(front, bogie.position+bogie.axles.front().position);
- }
- return front;
+ return axles.front().position;
+ return length/2;
}
float VehicleType::get_back_axle_offset() const
{
- float back = -length/2;
if(!axles.empty())
- back = axles.back().position;
- if(!bogies.empty())
- {
- const Bogie &bogie = bogies.back();
- back = min(back, bogie.position+bogie.axles.back().position);
- }
- return back;
+ return axles.back().position;
+ return -length/2;
}
VehicleType::Axle::Axle():
+ index(0),
+ bogie(0),
+ local_position(0),
position(0),
wheel_dia(0),
powered(false)
{ }
+VehicleType::Rod::Rod():
+ pivot(BODY),
+ pivot_index(0),
+ pivot_index2(0),
+ limit(ROTATE),
+ connect_index(-1),
+ mirror_object(false)
+{ }
+
+
VehicleType::Loader::Loader(VehicleType &vt):
- DataFile::ObjectLoader<VehicleType>(vt)
+ DataFile::DerivedObjectLoader<VehicleType, ObjectType::Loader>(vt)
{
add("axle", &Loader::axle);
add("bogie", &Loader::bogie);
add("length", &Loader::length);
add("locomotive", &VehicleType::locomotive);
add("object", &VehicleType::object);
- add("name", &VehicleType::name);
+ add("rod", &Loader::rod);
+ add("rotate_object", &VehicleType::rotate_object);
+ add("swap_direction", &VehicleType::swap_direction);
add("width", &Loader::width);
}
+void VehicleType::Loader::finish()
+{
+ for(unsigned i=0; i<obj.bogies.size(); ++i)
+ {
+ obj.bogies[i].index = i;
+ for(unsigned j=0; j<obj.bogies[i].axles.size(); ++j)
+ {
+ obj.bogies[i].axles[j] = &obj.axles[obj.bogies[i].first_axle+j];
+ obj.bogies[i].axles[j]->bogie = &obj.bogies[i];
+ obj.bogies[i].axles[j]->position += obj.bogies[i].position;
+ }
+ }
+
+ for(unsigned i=0; i<obj.axles.size(); ++i)
+ {
+ obj.axles[i].index = i;
+ if(!obj.axles[i].bogie)
+ obj.fixed_axles.push_back(&obj.axles[i]);
+ }
+
+ obj.shape = new Geometry::TransformedShape<float, 3>(
+ Geometry::Box<float>(obj.length, obj.width, obj.height),
+ Transform::translation(Vector(0, 0, obj.height/2)));
+}
+
void VehicleType::Loader::axle()
{
Axle axl;
void VehicleType::Loader::bogie()
{
Bogie bog;
- load_sub(bog);
+ Bogie::Loader ldr(obj, bog);
+ load_sub_with(ldr);
obj.bogies.push_back(bog);
}
obj.length = l/1000;
}
+void VehicleType::Loader::rod()
+{
+ Rod rd;
+ Rod::Loader ldr(rd, rod_tags);
+ load_sub_with(ldr);
+ obj.rods.push_back(rd);
+ if(!ldr.get_tag().empty())
+ rod_tags[ldr.get_tag()] = obj.rods.size()-1;
+ rod_tags["previous"] = obj.rods.size()-1;
+}
+
void VehicleType::Loader::width(float w)
{
obj.width = w/1000;
void VehicleType::Axle::Loader::position(float p)
{
- obj.position = p/1000;
+ obj.local_position = p/1000;
+ obj.position = obj.local_position;
}
void VehicleType::Axle::Loader::wheel_diameter(float d)
}
-VehicleType::Bogie::Loader::Loader(Bogie &b):
- DataFile::ObjectLoader<Bogie>(b)
+VehicleType::Bogie::Loader::Loader(VehicleType &t, Bogie &b):
+ DataFile::ObjectLoader<Bogie>(b),
+ parent(t)
{
add("axle", &Loader::axle);
add("object", &Bogie::object);
{
Axle axl;
load_sub(axl);
- obj.axles.push_back(axl);
+ if(obj.axles.empty())
+ obj.first_axle = parent.axles.size();
+ parent.axles.push_back(axl);
+ // Actual pointers will be filled after everything is loaded
+ obj.axles.push_back(0);
}
void VehicleType::Bogie::Loader::position(float p)
obj.position = p/1000;
}
+
+VehicleType::Rod::Loader::Loader(Rod &r, const map<string, unsigned> &t):
+ DataFile::ObjectLoader<Rod>(r),
+ tags(t)
+{
+ add("connect", &Loader::connect);
+ add("limit", &Rod::limit);
+ add("mirror_object", &Rod::mirror_object);
+ add("object", &Rod::object);
+ add("pivot_body", &Loader::pivot_body);
+ add("pivot_axle", &Loader::pivot_axle);
+ add("pivot_axle", &Loader::pivot_bogie_axle);
+ add("pivot_rod", &Loader::pivot_rod);
+ add("position", &Loader::position);
+ add("tag", &Loader::set_tag);
+}
+
+void VehicleType::Rod::Loader::connect(const string &t, float px, float pz, float ox, float oz)
+{
+ obj.connect_index = get_item(tags, t);
+ obj.connect_point = Vector(px/1000, 0, pz/1000);
+ obj.connect_offset = Vector(ox/1000, 0, oz/1000);
+}
+
+void VehicleType::Rod::Loader::pivot_body()
+{
+ obj.pivot = BODY;
+}
+
+void VehicleType::Rod::Loader::pivot_axle(unsigned i)
+{
+ obj.pivot = AXLE;
+ obj.pivot_index = i;
+}
+
+void VehicleType::Rod::Loader::pivot_bogie_axle(unsigned i, unsigned j)
+{
+ obj.pivot = BOGIE_AXLE;
+ obj.pivot_index = i;
+ obj.pivot_index2 = j;
+}
+
+void VehicleType::Rod::Loader::pivot_rod(const string &t)
+{
+ obj.pivot_index = get_item(tags, t);
+ obj.pivot = ROD;
+}
+
+void VehicleType::Rod::Loader::position(float x, float y, float z)
+{
+ obj.pivot_point = Vector(x/1000, y/1000, z/1000);
+}
+
+void VehicleType::Rod::Loader::set_tag(const string &t)
+{
+ tag = t;
+}
+
+
+void operator>>(const LexicalConverter &c, VehicleType::Rod::Limit &l)
+{
+ const string &s = c.get();
+ if(s=="FIXED")
+ l = VehicleType::Rod::FIXED;
+ else if(s=="ROTATE")
+ l = VehicleType::Rod::ROTATE;
+ else if(s=="SLIDE_X")
+ l = VehicleType::Rod::SLIDE_X;
+ else
+ throw lexical_error(format("conversion of '%s' to Rod::Limit", s));
+}
+
} // namespace R2C2