Rigs of Rods 2023.09
Soft-body Physics Simulation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
RigDef_Serializer.cpp
Go to the documentation of this file.
1/*
2 This source file is part of Rigs of Rods
3 Copyright 2005-2012 Pierre-Michel Ricordel
4 Copyright 2007-2012 Thomas Fischer
5 Copyright 2013-2020 Petr Ohlidal
6
7 For more information, see http://www.rigsofrods.org/
8
9 Rigs of Rods is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 3, as
11 published by the Free Software Foundation.
12
13 Rigs of Rods is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Rigs of Rods. If not, see <http://www.gnu.org/licenses/>.
20*/
21
25
26#include "RigDef_Serializer.h"
27
28#include "Actor.h"
29#include "GUIManager.h"
30#include "RigDef_File.h"
31
32#include <fstream>
33#include <OgreStringConverter.h>
34#include <iomanip>
35#include <unordered_map>
36
37using namespace RoR;
38using namespace RigDef;
39using namespace std;
40
42 m_rig_def(def_file),
43 m_node_id_width(5),
44 m_inertia_function_width(10),
45 m_bool_width(5), // strlen("false") == 5
46 m_command_key_width(2),
47 m_float_width(10)
48{}
49
51{
52 // Write banner
54 << "; ---------------------------------------------------------------------------- ;" << endl
55 << "; Project: Rigs of Rods (http://www.rigsofrods.org) ;" << endl
56 << "; File format: https://docs.rigsofrods.org/vehicle-creation/fileformat-truck ;" << endl
57 << "; ---------------------------------------------------------------------------- ;" << endl
58 << endl;
59
60 // Write name
61 m_stream << m_rig_def->name << endl << endl;
62
63 // Select source
64 Document::Module* source_module = m_rig_def->root_module.get();
65
66 // Write individual elements
67
68 // About
69 ProcessDescription(source_module);
70 ProcessAuthors(source_module);
71 ProcessFileinfo(source_module);
72 ProcessGuid(source_module);
73 WriteFlags();
74
75 // Modules (aka 'sectionconfig')
76 this->SerializeModule(m_rig_def->root_module);
77 for (auto module_itor: m_rig_def->user_modules)
78 {
79 this->SerializeModule(module_itor.second);
80 }
81
82 // Finalize
83 m_stream << "end" << endl;
84}
85
86void Serializer::SerializeModule(std::shared_ptr<RigDef::Document::Module> m)
87{
88 RigDef::Document::Module* source_module = m.get();
89
90 if (m->name != RigDef::ROOT_MODULE_NAME)
91 {
92 m_stream << "section -1 " << m->name << endl;
93 }
94
96 ProcessGlobals(source_module);
97
98 // Structure
99 ProcessNodes(source_module);
100 ProcessBeams(source_module);
101 ProcessCameras(source_module);
102 ProcessShocks(source_module);
103 ProcessShocks2(source_module);
104 ProcessHydros(source_module);
105 ProcessCommands2(source_module);
106 ProcessSlideNodes(source_module);
107 ProcessTies(source_module);
108 ProcessRopes(source_module);
109 ProcessFixes(source_module);
110
111 // Wheels
112 ProcessMeshWheels(source_module);
113 ProcessMeshWheels2(source_module);
114 ProcessWheels(source_module);
115 ProcessWheels2(source_module);
116 ProcessFlexBodyWheels(source_module);
117
118 // Driving
119 ProcessEngine(source_module);
120 ProcessEngoption(source_module);
121 ProcessBrakes(source_module);
122 ProcessAntiLockBrakes(source_module);
123 ProcessTractionControl(source_module);
124 ProcessTorqueCurve(source_module);
125 ProcessCruiseControl(source_module);
126 ProcessSpeedLimiter(source_module);
127 ProcessAxles(source_module);
128 ProcessTransferCase(source_module);
129 ProcessInterAxles(source_module);
130
131 // Features
132 ProcessCinecam(source_module);
133 ProcessAnimators(source_module);
134 ProcessContacters(source_module);
135 ProcessTriggers(source_module);
136 ProcessLockgroups(source_module);
137 ProcessHooks(source_module);
138 ProcessRailGroups(source_module);
139 ProcessRopables(source_module);
140 ProcessParticles(source_module);
141 ProcessCollisionBoxes(source_module);
142 // TODO: detacher_group
143 ProcessFlares2(source_module);
144 ProcessMaterialFlareBindings(source_module);
145 ProcessPropsAndAnimations(source_module);
146 ProcessSubmesh(source_module);
147 ProcessSubmeshGroundmodel(source_module);
148 ProcessExhausts(source_module);
149 ProcessGuiSettings(source_module);
150 ProcessSetSkeletonSettings(source_module);
151 ProcessVideocamera(source_module);
152 ProcessExtCamera(source_module);
153 ProcessSoundsources(source_module);
154 ProcessSoundsources2(source_module);
155 ProcessCustomDashboardInputs(source_module);
156
157 // Aerial
158 ProcessWings(source_module);
159 ProcessAirbrakes(source_module);
160 ProcessTurboprops(source_module);
161 ProcessFusedrag(source_module);
162 ProcessPistonprops(source_module);
163 ProcessTurbojets(source_module);
164
165 // Marine
166 ProcessScrewprops(source_module);
167
168 if (m->name != RigDef::ROOT_MODULE_NAME)
169 {
170 m_stream << "endsection" << endl;
171 }
172}
173
175{
176 if (module->pistonprops.empty())
177 {
178 return;
179 }
180 m_stream << "pistonprops" << endl;
181 auto end_itor = module->pistonprops.end();
182 for (auto itor = module->pistonprops.begin(); itor != end_itor; ++itor)
183 {
184 this->ExportDocComment(module, Keyword::PISTONPROPS, std::distance(module->pistonprops.begin(), itor));
185
186 auto & def = *itor;
187
188 m_stream << m_dataline_indentstr << setw(m_node_id_width) << def.reference_node.Str()
189 << ", " << setw(m_node_id_width) << def.axis_node.Str()
190 << ", " << setw(m_node_id_width) << def.blade_tip_nodes[0].Str()
191 << ", " << setw(m_node_id_width) << def.blade_tip_nodes[1].Str()
192 << ", " << setw(m_node_id_width) << def.blade_tip_nodes[2].Str()
193 << ", " << setw(m_node_id_width) << def.blade_tip_nodes[3].Str()
194 << ", " << setw(m_node_id_width) << (def.couple_node.IsValidAnyState() ? def.couple_node.Str() : "-1")
195 << ", " << setw(m_float_width) << def.turbine_power_kW
196 << ", " << setw(m_float_width) << def.pitch
197 << ", " << def.airfoil
198 << endl;
199 }
200 m_stream << endl; // Empty line
201}
202
204{
205 if (module->turbojets.empty())
206 {
207 return;
208 }
209 m_stream << "turbojets" << endl;
210 auto end_itor = module->turbojets.end();
211 for (auto itor = module->turbojets.begin(); itor != end_itor; ++itor)
212 {
213 this->ExportDocComment(module, Keyword::TURBOJETS, std::distance(module->turbojets.begin(), itor));
214
215 auto & def = *itor;
216
217 m_stream << m_dataline_indentstr << setw(m_node_id_width) << def.front_node.Str()
218 << ", " << setw(m_node_id_width) << def.back_node.Str()
219 << ", " << setw(m_node_id_width) << def.side_node.Str()
220 << ", " << setw(2) << def.is_reversable
221 << ", " << setw(m_float_width) << def.dry_thrust
222 << ", " << setw(m_float_width) << def.wet_thrust
223 << ", " << setw(m_float_width) << def.front_diameter
224 << ", " << setw(m_float_width) << def.back_diameter
225 << ", " << setw(m_float_width) << def.nozzle_length
226 << endl;
227 }
228 m_stream << endl; // Empty line
229}
230
232{
233 if (module->screwprops.empty())
234 {
235 return;
236 }
237 m_stream << "screwprops" << endl;
238 auto end_itor = module->screwprops.end();
239 for (auto itor = module->screwprops.begin(); itor != end_itor; ++itor)
240 {
241 this->ExportDocComment(module, Keyword::SCREWPROPS, std::distance(module->screwprops.begin(), itor));
242
243 auto & def = *itor;
244
245 m_stream << m_dataline_indentstr << setw(m_node_id_width) << def.prop_node.Str()
246 << ", " << setw(m_node_id_width) << def.back_node.Str()
247 << ", " << setw(m_node_id_width) << def.top_node.Str()
248 << ", " << setw(m_float_width) << def.power
249 << endl;
250 }
251 m_stream << endl; // Empty line
252}
253
255{
256 m_stream << "fusedrag" << endl;
257 for (RigDef::Fusedrag& def: module->fusedrag)
258 {
259 m_stream << m_dataline_indentstr
260 << setw(m_node_id_width) << def.front_node.Str() << ", "
261 << setw(m_node_id_width) << def.rear_node.Str() << ", ";
262 if (def.autocalc)
263 {
264 m_stream << "autocalc, " << setw(m_float_width) << def.area_coefficient;
265 }
266 else
267 {
268 m_stream << setw(m_float_width) << def.approximate_width;
269 }
270 m_stream << ", " << def.airfoil_name
271 << endl;
272 }
273
274 m_stream << endl; // Empty line
275}
276
278{
279 if (module->turboprops2.empty())
280 {
281 return;
282 }
283 m_stream << "turboprops" << endl;
284 auto end_itor = module->turboprops2.end();
285 for (auto itor = module->turboprops2.begin(); itor != end_itor; ++itor)
286 {
287 this->ExportDocComment(module, Keyword::TURBOPROPS, std::distance(module->turboprops2.begin(), itor));
288
289 RigDef::Turboprop2 & def = *itor;
290
292 << ", " << setw(m_node_id_width) << def.axis_node.Str()
293 << ", " << setw(m_node_id_width) << def.blade_tip_nodes[0].Str()
294 << ", " << setw(m_node_id_width) << def.blade_tip_nodes[1].Str()
295 << ", " << setw(m_node_id_width) << def.blade_tip_nodes[2].Str()
296 << ", " << setw(m_node_id_width) << def.blade_tip_nodes[3].Str()
297 << ", " << setw(m_float_width) << def.turbine_power_kW
298 << ", " << def.airfoil
299 << endl;
300 }
301 m_stream << endl; // Empty line
302}
303
305{
306 if (module->airbrakes.empty())
307 {
308 return;
309 }
310 m_stream << "airbrakes" << endl;
311 auto end_itor = module->airbrakes.end();
312 for (auto itor = module->airbrakes.begin(); itor != end_itor; ++itor)
313 {
314 this->ExportDocComment(module, Keyword::AIRBRAKES, std::distance(module->airbrakes.begin(), itor));
315
316 RigDef::Airbrake & def = *itor;
317
319 << ", " << setw(m_node_id_width) << def.x_axis_node.Str()
320 << ", " << setw(m_node_id_width) << def.y_axis_node.Str()
321 << ", " << setw(m_node_id_width) << (def.aditional_node.IsValidAnyState() ? def.aditional_node.Str() : "-1")
322 << ", " << setw(m_float_width) << def.offset.x
323 << ", " << setw(m_float_width) << def.offset.y
324 << ", " << setw(m_float_width) << def.offset.z
325 << ", " << setw(m_float_width) << def.width
326 << ", " << setw(m_float_width) << def.height
327 << ", " << setw(m_float_width) << def.max_inclination_angle
328 << ", " << setw(m_float_width) << def.texcoord_x1
329 << ", " << setw(m_float_width) << def.texcoord_y1
330 << ", " << setw(m_float_width) << def.texcoord_x2
331 << ", " << setw(m_float_width) << def.texcoord_y2
332 << ", " << setw(m_float_width) << def.lift_coefficient
333 << endl;
334 }
335 m_stream << endl; // Empty line
336}
337
339{
340 if (module->wings.empty())
341 {
342 return;
343 }
344 m_stream << "wings" << endl;
345 auto end_itor = module->wings.end();
346 for (auto itor = module->wings.begin(); itor != end_itor; ++itor)
347 {
348 this->ExportDocComment(module, Keyword::WINGS, std::distance(module->wings.begin(), itor));
349
350 RigDef::Wing & def = *itor;
351
353 << ", " << setw(m_node_id_width) << def.nodes[1].Str()
354 << ", " << setw(m_node_id_width) << def.nodes[2].Str()
355 << ", " << setw(m_node_id_width) << def.nodes[3].Str()
356 << ", " << setw(m_node_id_width) << def.nodes[4].Str()
357 << ", " << setw(m_node_id_width) << def.nodes[5].Str()
358 << ", " << setw(m_node_id_width) << def.nodes[6].Str()
359 << ", " << setw(m_node_id_width) << def.nodes[7].Str()
360 << ", " << setw(m_float_width) << def.tex_coords[0]
361 << ", " << setw(m_float_width) << def.tex_coords[1]
362 << ", " << setw(m_float_width) << def.tex_coords[2]
363 << ", " << setw(m_float_width) << def.tex_coords[3]
364 << ", " << setw(m_float_width) << def.tex_coords[4]
365 << ", " << setw(m_float_width) << def.tex_coords[5]
366 << ", " << setw(m_float_width) << def.tex_coords[6]
367 << ", " << setw(m_float_width) << def.tex_coords[7]
368 << ", " << (char)def.control_surface
369 << ", " << setw(m_float_width) << def.chord_point
370 << ", " << setw(m_float_width) << def.min_deflection
371 << ", " << setw(m_float_width) << def.max_deflection
372 << ", " << def.airfoil
373 << ", " << def.efficacy_coef
374 << endl;
375 }
376 m_stream << endl; // Empty line
377}
378
380{
381 if (module->soundsources.empty())
382 {
383 return;
384 }
385 m_stream << "soundsources" << endl;
386 auto end_itor = module->soundsources.end();
387 for (auto itor = module->soundsources.begin(); itor != end_itor; ++itor)
388 {
389 this->ExportDocComment(module, Keyword::SOUNDSOURCES, std::distance(module->soundsources.begin(), itor));
390
391 RigDef::SoundSource & def = *itor;
392
393 m_stream << m_dataline_indentstr << setw(m_node_id_width) << def.node.Str() << ", " << def.sound_script_name
394 << endl;
395 }
396 m_stream << endl; // Empty line
397}
398
400{
401 if (module->soundsources2.empty())
402 {
403 return;
404 }
405 m_stream << "soundsources2" << endl;
406 auto end_itor = module->soundsources2.end();
407 for (auto itor = module->soundsources2.begin(); itor != end_itor; ++itor)
408 {
409 this->ExportDocComment(module, Keyword::SOUNDSOURCES2, std::distance(module->soundsources2.begin(), itor));
410
411 RigDef::SoundSource2 & def = *itor;
412
414 << ", " << setw(2) << def.mode
415 << ", " << def.sound_script_name
416 << endl;
417 }
418 m_stream << endl; // Empty line
419}
420
422{
423 if (module->customdashboardinputs.empty())
424 {
425 return;
426 }
427
428 m_stream << "customdashboardinputs" << endl;
429 auto end_itor = module->customdashboardinputs.end();
430 for (auto itor = module->customdashboardinputs.begin(); itor != end_itor; ++itor)
431 {
432 this->ExportDocComment(module, Keyword::CUSTOMDASHBOARDINPUTS, std::distance(module->customdashboardinputs.begin(), itor));
433
434 CustomDashboardInput& dash_val = *itor;
435
436 m_stream << dash_val.name << " ";
437 switch (dash_val.data_type)
438 {
439 case DC_BOOL:
440 m_stream << "bool";
441 break;
442 case DC_FLOAT:
443 m_stream << "float";
444 break;
445 case DC_INT:
446 m_stream << "int";
447 break;
448 case DC_CHAR:
449 m_stream << "string";
450 break;
451 }
452
453 m_stream << endl;
454 }
455 m_stream << endl; // Empty line
456}
457
459{
460 if (module->extcamera.size() == 0)
461 {
462 return;
463 }
464 RigDef::ExtCamera* def = &module->extcamera[0];
465 m_stream << "extcamera ";
466
467 switch (def->mode)
468 {
469 case ExtCameraMode::NODE:
470 m_stream << "node " << def->node.Str();
471 break;
472 case ExtCameraMode::CINECAM:
473 m_stream << "cinecam";
474 break;
475 case ExtCameraMode::CLASSIC:
476 default:
477 m_stream << "classic";
478 break;
479 }
480 m_stream << "\n\n";
481}
482
484{
485 if (module->videocameras.empty())
486 {
487 return;
488 }
489 m_stream << "videocamera" << endl;
490 auto end_itor = module->videocameras.end();
491 for (auto itor = module->videocameras.begin(); itor != end_itor; ++itor)
492 {
493 this->ExportDocComment(module, Keyword::VIDEOCAMERA, std::distance(module->videocameras.begin(), itor));
494
495 RigDef::VideoCamera & def = *itor;
496
498 << ", " << setw(m_node_id_width) << def.left_node.Str()
499 << ", " << setw(m_node_id_width) << def.bottom_node.Str()
500 << ", " << setw(m_node_id_width) << (def.alt_reference_node.IsValidAnyState() ? def.alt_reference_node.Str() : "-1")
501 << ", " << setw(m_node_id_width) << (def.alt_orientation_node.IsValidAnyState() ? def.alt_orientation_node.Str() : "-1")
502 << ", " << setw(m_float_width) << def.offset.x
503 << ", " << setw(m_float_width) << def.offset.y
504 << ", " << setw(m_float_width) << def.offset.z
505 << ", " << setw(m_float_width) << def.rotation.x
506 << ", " << setw(m_float_width) << def.rotation.y
507 << ", " << setw(m_float_width) << def.rotation.z
508 << ", " << setw(m_float_width) << def.field_of_view
509 << ", " << setw(4) << def.texture_width
510 << ", " << setw(4) << def.texture_height
511 << ", " << setw(m_float_width) << def.min_clip_distance
512 << ", " << setw(m_float_width) << def.max_clip_distance
513 << ", " << setw(3) << def.camera_role
514 << ", " << setw(3) << def.camera_mode
515 << ", " << def.material_name;
516 if (!def.camera_name.empty())
517 {
518 m_stream << ", " << def.camera_name;
519 }
520
521 m_stream << endl;
522 }
523 m_stream << endl; // Empty line
524}
525
527{
528 if (module->set_skeleton_settings.empty())
529 {
530 return;
531 }
532
533 RigDef::SkeletonSettings& def = module->set_skeleton_settings[module->set_skeleton_settings.size() - 1];
534 m_stream << "set_skeleton_settings " << def.visibility_range_meters << ", " << def.beam_thickness_meters << "\n\n";
535}
536
538{
539 if (module->guisettings.empty())
540 {
541 return;
542 }
543 m_stream << "guisettings" << endl;
544 for (GuiSettings& gs: module->guisettings)
545 {
546 m_stream << m_dataline_indentstr << gs.key << " " << gs.value
547 << endl;
548 }
549 m_stream << endl; // Empty line
550}
551
553{
554 if (module->exhausts.empty())
555 {
556 return;
557 }
558 m_stream << "exhausts" << endl;
559 auto end_itor = module->exhausts.end();
560 for (auto itor = module->exhausts.begin(); itor != end_itor; ++itor)
561 {
562 this->ExportDocComment(module, Keyword::EXHAUSTS, std::distance(module->exhausts.begin(), itor));
563
564 RigDef::Exhaust & def = *itor;
565
567 << ", " << setw(m_node_id_width) << def.direction_node.Str()
568 << ", " << def.particle_name
569 << endl;
570 }
571 m_stream << endl; // Empty line
572}
573
575{
576 if (module->submesh_groundmodel.empty())
577 {
578 return;
579 }
580
581 m_stream << "submesh_groundmodel " << module->submesh_groundmodel.back() << endl << endl; // Empty line
582}
583
585{
586 for (RigDef::Submesh & def: module->submeshes)
587 {
588 m_stream << "submesh" << endl;
589
590 if (def.texcoords.size() > 0)
591 {
592 m_stream << "texcoords" << endl;
593 auto texcoord_end = def.texcoords.end();
594 for (auto texcoord_itor = def.texcoords.begin(); texcoord_itor != texcoord_end; ++texcoord_itor)
595 {
596 m_stream << m_dataline_indentstr << setw(m_node_id_width) << texcoord_itor->node.Str() << ", " << texcoord_itor->u << ", " << texcoord_itor->v << endl;
597 }
598 }
599 if (def.cab_triangles.size() > 0)
600 {
601 m_stream << "cab" << endl;
602 auto cab_end = def.cab_triangles.end();
603 for (auto cab_itor = def.cab_triangles.begin(); cab_itor != cab_end; ++cab_itor)
604 {
605 m_stream << m_dataline_indentstr << setw(m_node_id_width) << cab_itor->nodes[0].Str()
606 << ", " << setw(m_node_id_width) << cab_itor->nodes[1].Str()
607 << ", " << setw(m_node_id_width) << cab_itor->nodes[2].Str()
608 << ", n";
609
610 // Options
611 if (BITMASK_IS_1(cab_itor->options, Cab::OPTION_c_CONTACT )) m_stream << (char)CabOption::c_CONTACT;
612 if (BITMASK_IS_1(cab_itor->options, Cab::OPTION_b_BUOYANT )) m_stream << (char)CabOption::b_BUOYANT;
620 m_stream << endl;
621 }
622 }
623 if (def.backmesh)
624 {
625 m_stream << "backmesh" << endl;
626 }
627 m_stream << endl; // Empty line
628 }
629}
630
631inline void PropAnimFlag(std::stringstream& out, int flags, bool& join, unsigned int mask, const char* name, char joiner = '|')
632{
633 if (flags & mask)
634 {
635 if (join)
636 {
637 out << joiner;
638 }
639 out << name;
640 join = true;
641 }
642}
643
645{
646 m_stream << "\tadd_animation "
647 << setw(m_float_width) << anim.ratio << ", "
648 << setw(m_float_width) << anim.lower_limit << ", "
649 << setw(m_float_width) << anim.upper_limit << ", "
650 << "source: ";
651
652 // Source flags
653 bool join = false;
654 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_AIRSPEED , "airspeed");
656 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_ALTIMETER_100K , "altimeter100k");
657 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_ALTIMETER_10K , "altimeter10k");
658 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_ALTIMETER_1K , "altimeter1k");
660 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_FLAP , "flap");
661 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_AIR_BRAKE , "airbrake");
662 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_ROLL , "roll");
663 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_PITCH , "pitch");
664 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_BRAKES , "brakes");
665 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_ACCEL , "accel");
666 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_CLUTCH , "clutch");
667 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_SPEEDO , "speedo");
668 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_TACHO , "tacho");
669 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_TURBO , "turbo");
670 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_PARKING , "parking");
674 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_SHIFTERLIN , "shifterlin");
675 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_TORQUE , "torque");
676 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_HEADING , "heading");
677 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_DIFFLOCK , "difflock");
678 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_BOAT_RUDDER , "rudderboat");
679 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_BOAT_THROTTLE , "throttleboat");
680 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_STEERING_WHEEL , "steeringwheel");
681 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_AILERON , "aileron");
682 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_ELEVATOR , "elevator");
683 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_AIR_RUDDER , "rudderair");
684 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_PERMANENT , "permanent");
685 PropAnimFlag(m_stream, anim.source, join, Animation::SOURCE_EVENT , "event");
686
687 m_stream << ", mode: ";
688 join = false;
689 PropAnimFlag(m_stream, anim.mode, join, Animation::MODE_ROTATION_X , "x-rotation");
690 PropAnimFlag(m_stream, anim.mode, join, Animation::MODE_ROTATION_Y , "y-rotation");
691 PropAnimFlag(m_stream, anim.mode, join, Animation::MODE_ROTATION_Z , "z-rotation");
692 PropAnimFlag(m_stream, anim.mode, join, Animation::MODE_OFFSET_X , "x-offset");
693 PropAnimFlag(m_stream, anim.mode, join, Animation::MODE_OFFSET_Y , "y-offset");
694 PropAnimFlag(m_stream, anim.mode, join, Animation::MODE_OFFSET_Z , "z-offset");
695
696 // Solo flags
697 PropAnimFlag(m_stream, anim.mode, join, Animation::MODE_AUTO_ANIMATE, " autoanimate", ',');
698 PropAnimFlag(m_stream, anim.mode, join, Animation::MODE_NO_FLIP , " noflip" , ',');
699 PropAnimFlag(m_stream, anim.mode, join, Animation::MODE_BOUNCE , " bounce" , ',');
700 PropAnimFlag(m_stream, anim.mode, join, Animation::MODE_EVENT_LOCK , " eventlock" , ',');
701
703 {
704 m_stream << ", event: " << anim.event_name;
705 }
706 m_stream << endl;
707}
708
710{
711 if (module->flexbodies.empty())
712 {
713 return;
714 }
715 m_stream << "flexbodies" << endl;
716 auto end_itor = module->flexbodies.end();
717 for (auto itor = module->flexbodies.begin(); itor != end_itor; ++itor)
718 {
719 this->ExportDocComment(module, Keyword::FLEXBODIES, std::distance(module->flexbodies.begin(), itor));
720
721 RigDef::Flexbody* def = &*itor;
722
723 // Prop-like line
725 << ", " << setw(m_node_id_width) << def->x_axis_node.Str()
726 << ", " << setw(m_node_id_width) << def->y_axis_node.Str()
727 << ", " << setw(m_float_width) << def->offset.x
728 << ", " << setw(m_float_width) << def->offset.y
729 << ", " << setw(m_float_width) << def->offset.z
730 << ", " << setw(m_float_width) << def->rotation.x
731 << ", " << setw(m_float_width) << def->rotation.y
732 << ", " << setw(m_float_width) << def->rotation.z
733 << ", " << def->mesh_name
734 << endl;
735
736 // Forset line
737 m_stream << m_dataline_indentstr << "forset ";
738 auto forset_end = def->node_list.end();
739 auto forset_itor = def->node_list.begin();
740 bool first = true;
741 for (; forset_itor != forset_end; ++forset_itor)
742 {
743 if (!first)
744 {
745 m_stream << ", ";
746 }
747 m_stream << forset_itor->Str();
748 first = false;
749 }
751 << endl;
752
753 // Animations
754 auto anim_end = def->animations.end();
755 for (auto anim_itor = def->animations.begin(); anim_itor != anim_end; ++anim_itor)
756 {
758 }
759 }
760 m_stream << endl; // Empty line
761}
762
764{
765 if (module->props.empty())
766 {
767 return;
768 }
769 m_stream << "props" << endl;
770 auto end_itor = module->props.end();
771 for (auto itor = module->props.begin(); itor != end_itor; ++itor)
772 {
773 this->ExportDocComment(module, Keyword::PROPS, std::distance(module->props.begin(), itor));
774
775 RigDef::Prop & def = *itor;
776
777 m_stream << "\t" << setw(m_node_id_width) << def.reference_node.Str()
778 << ", " << setw(m_node_id_width) << def.x_axis_node.Str()
779 << ", " << setw(m_node_id_width) << def.y_axis_node.Str()
780 << ", " << setw(m_float_width) << def.offset.x
781 << ", " << setw(m_float_width) << def.offset.y
782 << ", " << setw(m_float_width) << def.offset.z
783 << ", " << setw(m_float_width) << def.rotation.x
784 << ", " << setw(m_float_width) << def.rotation.y
785 << ", " << setw(m_float_width) << def.rotation.z
786 << ", " << def.mesh_name;
787
788 // Special props
789 if (def.special == SpecialProp::BEACON)
790 {
793 << ", " << def.special_prop_beacon.color.r
794 << ", " << def.special_prop_beacon.color.g
795 << ", " << def.special_prop_beacon.color.b;
796 }
798 {
799 m_stream << ", " << def.special_prop_dashboard.mesh_name; // The steering wheel mesh
801 {
803 << ", " << def.special_prop_dashboard.offset.x
804 << ", " << def.special_prop_dashboard.offset.y
805 << ", " << def.special_prop_dashboard.offset.z
807 }
808 }
809
810 m_stream << endl;
811
812 // Animations
813 auto anim_end = def.animations.end();
814 for (auto anim_itor = def.animations.begin(); anim_itor != anim_end; ++anim_itor)
815 {
817 }
818 }
819 m_stream << endl; // Empty line
820}
821
823{
824 if (module->materialflarebindings.empty())
825 {
826 return;
827 }
828 m_stream << "materialflarebindings" << endl;
829 auto end_itor = module->materialflarebindings.end();
830 for (auto itor = module->materialflarebindings.begin(); itor != end_itor; ++itor)
831 {
832 RigDef::MaterialFlareBinding & def = *itor;
834 << endl;
835 }
836 m_stream << endl; // Empty line
837}
838
840{
841 if (module->flares2.empty())
842 {
843 return;
844 }
845 m_stream << "flares2" << endl;
846 auto end_itor = module->flares2.end();
847 for (auto itor = module->flares2.begin(); itor != end_itor; ++itor)
848 {
849 this->ExportDocComment(module, Keyword::FLARES2, std::distance(module->flares2.begin(), itor));
850
851 RigDef::Flare2 & def = *itor;
852
854 << ", " << setw(m_node_id_width) << def.node_axis_x.Str()
855 << ", " << setw(m_node_id_width) << def.node_axis_y.Str()
856 << ", " << setw(m_float_width) << def.offset.x
857 << ", " << setw(m_float_width) << def.offset.y
858 << ", " << setw(m_float_width) << def.offset.z
859 << ", " << (char)def.type
860 << ", " << setw(2) << def.control_number
861 << ", " << setw(4) << def.blink_delay_milis
862 << ", " << setw(m_float_width) << def.size
863 << ", " << def.material_name
864 << endl;
865 }
866 m_stream << endl; // Empty line
867}
868
870{
871 if (module->managedmaterials.empty())
872 {
873 return;
874 }
875
876 // Calc column widths
877 size_t name_w = 0, type_w = 0, tex1_w = 0, tex2_w = 1, tex3_w = 1; // Handle space for '-' empty tex marker
878 for (ManagedMaterial& mm: module->managedmaterials)
879 {
880 name_w = std::max(name_w, mm.name.length());
881 type_w = std::max(type_w, strlen(RigDef::ManagedMaterial::TypeToStr(mm.type)));
882 tex1_w = std::max(tex1_w, mm.diffuse_map.size());
883 tex2_w = std::max(tex2_w, mm.damaged_diffuse_map.length());
884 tex3_w = std::max(tex3_w, mm.specular_map.length());
885 }
886
887 m_stream << "managedmaterials" << std::left << endl; // Set left alignment. WARNING - PERSISTENT!
888 bool first = true;
889 ManagedMaterialsOptions mm_options;
890 for (ManagedMaterial& def: module->managedmaterials)
891 {
892 if (first || (mm_options.double_sided != def.options.double_sided))
893 {
894 mm_options.double_sided = def.options.double_sided;
895 m_stream << "set_managedmaterials_options " << (int) mm_options.double_sided
896 << endl;
897 }
898
899 m_stream << m_dataline_indentstr
900 << setw(name_w) << def.name << " "
901 << setw(type_w) << RigDef::ManagedMaterial::TypeToStr(def.type) << " "
902 << setw(tex1_w) << def.diffuse_map << " ";
903
904 // Damage diffuse map - empty column if not applicable
906 {
907 m_stream << setw(tex2_w) << (def.damaged_diffuse_map.empty() ? "-" : def.damaged_diffuse_map) << " ";
908 }
909 else
910 {
911 m_stream << setw(tex2_w) << "" << " ";
912 }
913
914 m_stream << setw(tex3_w) << (def.specular_map.empty() ? "-" : def.specular_map);
915
916 first = false;
917 m_stream
918 << endl;
919 }
920 m_stream << std::right; // Reset to default alignment
921 m_stream << endl; // Empty line
922}
923
925{
926 if (module->collisionboxes.empty())
927 {
928 return;
929 }
930 m_stream << "collisionboxes" << endl;
931 auto end_itor = module->collisionboxes.end();
932 for (auto itor = module->collisionboxes.begin(); itor != end_itor; ++itor)
933 {
934 this->ExportDocComment(module, Keyword::COLLISIONBOXES, std::distance(module->collisionboxes.begin(), itor));
935
936 RigDef::CollisionBox & def = *itor;
937
938 auto nodes_end = def.nodes.end();
939 auto node_itor = def.nodes.begin();
940 m_stream << node_itor->Str();
941 ++node_itor;
942 for (; node_itor != nodes_end; ++node_itor)
943 {
944 m_stream << ", " << node_itor->Str();
945 }
946
947 m_stream << endl;
948 }
949 m_stream << endl; // Empty line
950}
951
953{
954 if (module->axles.empty())
955 {
956 return;
957 }
958 m_stream << "axles" << endl;
959 auto end_itor = module->axles.end();
960 for (auto itor = module->axles.begin(); itor != end_itor; ++itor)
961 {
962 this->ExportDocComment(module, Keyword::AXLES, std::distance(module->axles.begin(), itor));
963
964 RigDef::Axle & def = *itor;
965
967 << "w1(" << def.wheels[0][0].Str() << " " << def.wheels[0][1].Str() << "), "
968 << "w2(" << def.wheels[1][0].Str() << " " << def.wheels[1][1].Str() << ")";
969 if (! def.options.empty())
970 {
971 m_stream << ", d(";
972 auto end = def.options.end();
973 for (auto itor = def.options.begin(); itor != end; ++itor)
974 {
975 m_stream << (char)*itor;
976 }
977 m_stream << ")";
978 }
979 m_stream << endl;
980 }
981 m_stream << endl; // Empty line
982}
983
985{
986 if (module->interaxles.empty())
987 {
988 return;
989 }
990 m_stream << "interaxles" << endl;
991 auto end_itor = module->interaxles.end();
992 for (auto itor = module->interaxles.begin(); itor != end_itor; ++itor)
993 {
994 this->ExportDocComment(module, Keyword::INTERAXLES, std::distance(module->interaxles.begin(), itor));
995
996 RigDef::InterAxle & def = *itor;
997
999 << def.a1 << ", "
1000 << def.a2;
1001 if (! def.options.empty())
1002 {
1003 m_stream << ", d(";
1004 auto end = def.options.end();
1005 for (auto itor = def.options.begin(); itor != end; ++itor)
1006 {
1007 m_stream << (char)*itor;
1008 }
1009 m_stream << ")";
1010 }
1011 m_stream << endl;
1012 }
1013 m_stream << endl; // Empty line
1014}
1015
1017{
1018 if (module->transfercase.size() == 0)
1019 {
1020 return;
1021 }
1022 TransferCase& def = module->transfercase[module->transfercase.size() - 1];
1023
1024 m_stream << "transfercase\t"
1025 << def.a1 << ", "
1026 << def.a2 << ", "
1027 << def.has_2wd << ", "
1028 << def.has_2wd_lo;
1029 for (float gear_ratio : def.gear_ratios)
1030 {
1031 m_stream << ", " << gear_ratio;
1032 }
1033 m_stream << endl << endl;
1034}
1035
1037{
1038 if (module->cruisecontrol.size() == 0)
1039 {
1040 return;
1041 }
1042
1043 RigDef::CruiseControl& cruisecontrol = module->cruisecontrol[module->cruisecontrol.size() - 1];
1044
1045 m_stream << "cruisecontrol "
1046 << cruisecontrol.min_speed << ", "
1047 << (int) cruisecontrol.autobrake
1048 << endl << endl;
1049
1050}
1051
1053{
1054 if (module->speedlimiter.size() == 0)
1055 {
1056 return;
1057 }
1058 m_stream << "speedlimiter "
1059 << module->speedlimiter[module->speedlimiter.size() - 1].max_speed
1060 << endl << endl;
1061}
1062
1064{
1065 if (module->torquecurve.size() == 0)
1066 {
1067 return;
1068 }
1069 m_stream << "torquecurve" << endl;
1070 if (module->torquecurve[0].predefined_func_name.empty())
1071 {
1072 auto itor_end = module->torquecurve[0].samples.end();
1073 auto itor = module->torquecurve[0].samples.begin();
1074 for (; itor != itor_end; ++itor)
1075 {
1076 m_stream << m_dataline_indentstr << itor->power << ", " << itor->torque_percent;
1077 }
1078 }
1079 else
1080 {
1081 m_stream << m_dataline_indentstr << module->torquecurve[0].predefined_func_name;
1082 }
1083 m_stream << endl; // Empty line
1084}
1085
1087{
1088 if (module->particles.empty())
1089 {
1090 return;
1091 }
1092 m_stream << "particles" << endl;
1093 auto end_itor = module->particles.end();
1094 for (auto itor = module->particles.begin(); itor != end_itor; ++itor)
1095 {
1096 this->ExportDocComment(module, Keyword::PARTICLES, std::distance(module->particles.begin(), itor));
1097
1098 RigDef::Particle & def = *itor;
1099
1101 << setw(m_node_id_width) << def.emitter_node.Str() << ", "
1102 << setw(m_node_id_width) << def.reference_node.Str() << ", "
1103 << def.particle_system_name;
1104 m_stream << endl;
1105 }
1106 m_stream << endl; // Empty line
1107}
1108
1110{
1111 if (module->ropables.empty())
1112 {
1113 return;
1114 }
1115 m_stream << "ropables" << endl;
1116 auto end_itor = module->ropables.end();
1117 for (auto itor = module->ropables.begin(); itor != end_itor; ++itor)
1118 {
1119 this->ExportDocComment(module, Keyword::ROPABLES, std::distance(module->ropables.begin(), itor));
1120
1121 RigDef::Ropable & def = *itor;
1122
1124 << ", " << def.group
1125 << ", " << (int) def.has_multilock;
1126 m_stream << endl;
1127 }
1128 m_stream << endl; // Empty line
1129}
1130
1132{
1133 if (module->ties.empty())
1134 {
1135 return;
1136 }
1137 m_stream << "ties" << endl;
1138 auto end_itor = module->ties.end();
1139 for (auto itor = module->ties.begin(); itor != end_itor; ++itor)
1140 {
1141 this->ExportDocComment(module, Keyword::TIES, std::distance(module->ties.begin(), itor));
1142
1143 RigDef::Tie & def = *itor;
1144
1146 << ", " << setw(m_float_width) << def.max_reach_length
1147 << ", " << setw(m_float_width) << def.auto_shorten_rate
1148 << ", " << setw(m_float_width) << def.min_length
1149 << ", " << setw(m_float_width) << def.max_length
1150 << ", " << (BITMASK_IS_1(def.options, Tie::OPTION_i_INVISIBLE) ? "i" : "n")
1151 << ", " << (BITMASK_IS_1(def.options, Tie::OPTION_s_DISABLE_SELF_LOCK) ? "s" : "")
1152 << ", " << setw(m_float_width) << def.max_stress
1153 << ", " << def.group;
1154 m_stream << endl;
1155 }
1156 m_stream << endl; // Empty line
1157}
1158
1160{
1161 if (module->fixes.empty())
1162 {
1163 return;
1164 }
1165 m_stream << "fixes" << endl;
1166 auto end_itor = module->fixes.end();
1167 for (auto itor = module->fixes.begin(); itor != end_itor; ++itor)
1168 {
1169 m_stream << m_dataline_indentstr << setw(m_node_id_width) << itor->Str();
1170 }
1171 m_stream << endl; // Empty line
1172}
1173
1175{
1176 if (module->ropes.empty())
1177 {
1178 return;
1179 }
1180 m_stream << "ropes" << endl;
1181 auto end_itor = module->ropes.end();
1182 bool first = true;
1183 BeamDefaults* beam_defaults = nullptr;
1184 for (auto itor = module->ropes.begin(); itor != end_itor; ++itor)
1185 {
1186 this->ExportDocComment(module, Keyword::ROPES, std::distance(module->ropes.begin(), itor));
1187
1188 RigDef::Rope & def = *itor;
1189
1190 if (first || (def.beam_defaults.get() != beam_defaults))
1191 {
1193 }
1194
1196 << setw(m_node_id_width) << def.root_node.Str() << ", "
1197 << setw(m_node_id_width) << def.end_node.Str();
1198 if (def.invisible)
1199 {
1200 m_stream << ", i";
1201 }
1202 first = false;
1203 m_stream << endl;
1204 }
1205 m_stream << endl; // Empty line
1206}
1207
1209{
1210 if (module->railgroups.empty())
1211 {
1212 return;
1213 }
1214 m_stream << "railgroups" << endl << endl;
1215 auto end_itor = module->railgroups.end();
1216 for (auto itor = module->railgroups.begin(); itor != end_itor; ++itor)
1217 {
1218 this->ExportDocComment(module, Keyword::RAILGROUPS, std::distance(module->railgroups.begin(), itor));
1219
1220 RigDef::RailGroup & def = *itor;
1221
1223 auto node_end = def.node_list.end();
1224 for (auto node_itor = def.node_list.begin(); node_itor != node_end; ++node_itor)
1225 {
1226 m_stream << ", " << node_itor->start.Str();
1227 if (node_itor->IsRange())
1228 {
1229 m_stream << " - " << node_itor->end.Str();
1230 }
1231 }
1232 m_stream << endl;
1233 }
1234 m_stream << endl; // Empty line
1235}
1236
1238{
1239 if (module->slidenodes.empty())
1240 {
1241 return;
1242 }
1243 m_stream << "slidenodes" << endl << endl;
1244 auto end_itor = module->slidenodes.end();
1245 for (auto itor = module->slidenodes.begin(); itor != end_itor; ++itor)
1246 {
1247 this->ExportDocComment(module, Keyword::SLIDENODES, std::distance(module->slidenodes.begin(), itor));
1248
1249 RigDef::SlideNode & def = *itor;
1250
1252
1253 // Define rail - either list of nodes, or raigroup ID
1254 if (!def.rail_node_ranges.empty())
1255 {
1256 auto end = def.rail_node_ranges.end();
1257 auto itor = def.rail_node_ranges.begin();
1258 for (; itor != end; ++itor)
1259 {
1260 m_stream << ", " << itor->start.Str();
1261 if (itor->IsRange())
1262 {
1263 m_stream << " - " << itor->end.Str();
1264 }
1265 }
1266 }
1267 else
1268 {
1269 m_stream << ", g" << def.railgroup_id;
1270 }
1271
1272 // Optional args
1273 if (def._spring_rate_set) { m_stream << ", s" << def.spring_rate; }
1274 if (def._break_force_set) { m_stream << ", b" << def.break_force; }
1275 if (def._tolerance_set) { m_stream << ", t" << def.tolerance; }
1276 if (def._attachment_rate_set) { m_stream << ", r" << def.attachment_rate; }
1277 if (def._max_attach_dist_set) { m_stream << ", d" << def.max_attach_dist; }
1278
1279 // Constraint flags (cX)
1284
1285 m_stream << endl;
1286 }
1287 m_stream << endl; // Empty line
1288}
1289
1291{
1292 if (module->hooks.empty())
1293 {
1294 return;
1295 }
1296 m_stream << "hooks" << endl << endl;
1297 auto end_itor = module->hooks.end();
1298 for (auto itor = module->hooks.begin(); itor != end_itor; ++itor)
1299 {
1300 this->ExportDocComment(module, Keyword::HOOKS, std::distance(module->hooks.begin(), itor));
1301
1302 RigDef::Hook & def = *itor;
1303
1305
1306 // Boolean options
1307 if (def.flag_auto_lock) { m_stream << ", auto-lock"; }
1308 if (def.flag_no_disable) { m_stream << ", nodisable"; }
1309 if (def.flag_no_rope) { m_stream << ", norope"; }
1310 if (def.flag_self_lock) { m_stream << ", self-lock"; }
1311 if (def.flag_visible) { m_stream << ", visible"; }
1312
1313 // Key-value options
1314 m_stream
1315 << ", hookrange: " << setw(m_float_width) << def.option_hook_range
1316 << ", speedcoef: " << setw(m_float_width) << def.option_speed_coef
1317 << ", maxforce: " << setw(m_float_width) << def.option_max_force
1318 << ", hookgroup: " << setw(4) << def.option_hookgroup
1319 << ", lockgroup: " << setw(4) << def.option_lockgroup
1320 << ", timer: " << setw(m_float_width) << def.option_timer
1321 << ", shortlimit: " << setw(m_float_width) << def.option_min_range_meters;
1322
1323 m_stream << endl;
1324 }
1325 m_stream << endl; // Empty line
1326}
1327
1329{
1330 if (module->lockgroups.empty())
1331 {
1332 return;
1333 }
1334 m_stream << "lockgroups" << endl << endl;
1335 auto end_itor = module->lockgroups.end();
1336 for (auto itor = module->lockgroups.begin(); itor != end_itor; ++itor)
1337 {
1338 this->ExportDocComment(module, Keyword::LOCKGROUPS, std::distance(module->lockgroups.begin(), itor));
1339
1340 RigDef::Lockgroup & def = *itor;
1341
1343 auto nodes_end = def.nodes.end();
1344 for (auto nodes_itor = def.nodes.begin(); nodes_itor != nodes_end; ++nodes_itor)
1345 {
1346 m_stream << ", " << nodes_itor->Str();
1347 }
1348 m_stream << endl;
1349 }
1350 m_stream << endl; // Empty line
1351}
1352
1354{
1355 if (module->triggers.empty())
1356 {
1357 return;
1358 }
1359 m_stream << "animators" << endl << endl;
1360 auto end_itor = module->triggers.end();
1361 for (auto itor = module->triggers.begin(); itor != end_itor; ++itor)
1362 {
1363 this->ExportDocComment(module, Keyword::TRIGGERS, std::distance(module->triggers.begin(), itor));
1364
1365 RigDef::Trigger & def = *itor;
1366
1368 << setw(m_node_id_width) << def.nodes[0].Str() << ", "
1369 << setw(m_node_id_width) << def.nodes[1].Str() << ", "
1370 << setw(m_float_width) << def.contraction_trigger_limit << ", "
1371 << setw(m_float_width) << def.expansion_trigger_limit << ", "
1372 << setw(4) << def.shortbound_trigger_action << ", "
1373 << setw(4) << def.longbound_trigger_action << ", ";
1374
1386
1387 m_stream << " " << def.boundary_timer;
1388 m_stream << endl;
1389 }
1390 m_stream << endl; // Empty line
1391}
1392
1393#define ANIMATOR_ADD_FLAG(DEF_VAR, AND_VAR, BITMASK_CONST, NAME_STR) \
1394 if (AND_VAR) { m_stream << " | "; } \
1395 if (BITMASK_IS_1((DEF_VAR).flags, RigDef::Animator::BITMASK_CONST)) { \
1396 AND_VAR = true; \
1397 m_stream << NAME_STR; \
1398 }
1399
1400#define ANIMATOR_ADD_AERIAL_FLAG(DEF_VAR, AND_VAR, BITMASK_CONST, NAME_STR) \
1401 if (AND_VAR) { m_stream << " | "; } \
1402 if (BITMASK_IS_1((DEF_VAR).aero_animator.flags, RigDef::AeroAnimator::BITMASK_CONST)) { \
1403 AND_VAR = true; \
1404 m_stream << NAME_STR << DEF_VAR.aero_animator.engine_idx + 1; \
1405 }
1406
1407#define ANIMATOR_ADD_LIMIT(DEF_VAR, AND_VAR, BITMASK_CONST, NAME_STR, VALUE) \
1408 if (AND_VAR) { m_stream << " | "; } \
1409 if (BITMASK_IS_1((DEF_VAR).aero_animator.flags, RigDef::Animator::BITMASK_CONST)) { \
1410 AND_VAR = true; \
1411 m_stream << NAME_STR << ": " << VALUE; \
1412 }
1413
1415{
1416 if (module->animators.empty())
1417 {
1418 return;
1419 }
1420 m_stream << "animators" << endl << endl;
1421 auto end_itor = module->animators.end();
1422 for (auto itor = module->animators.begin(); itor != end_itor; ++itor)
1423 {
1424 this->ExportDocComment(module, Keyword::ANIMATORS, std::distance(module->animators.begin(), itor));
1425
1426 RigDef::Animator & def = *itor;
1427
1429 << setw(m_node_id_width) << def.nodes[0].Str() << ", "
1430 << setw(m_node_id_width) << def.nodes[1].Str() << ", "
1431 << setw(m_float_width) << def.lenghtening_factor << ", ";
1432
1433 // Options
1434 bool bAnd = false;
1435 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_VISIBLE , "vis")
1436 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_INVISIBLE , "inv")
1437 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_AIRSPEED , "airspeed")
1438 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_VERTICAL_VELOCITY, "vvi")
1439 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_ALTIMETER_100K , "altimeter100k")
1440 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_ALTIMETER_10K , "altimeter10k")
1441 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_ALTIMETER_1K , "altimeter1k")
1442 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_ANGLE_OF_ATTACK , "aoa")
1443 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_FLAP , "flap")
1444 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_AIR_BRAKE , "airbrake")
1445 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_ROLL , "roll")
1446 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_PITCH , "pitch")
1447 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_BRAKES , "brakes")
1448 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_ACCEL , "accel")
1449 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_CLUTCH , "clutch")
1450 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_SPEEDO , "speedo")
1451 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_TACHO , "tacho")
1452 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_TURBO , "turbo")
1453 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_PARKING , "parking")
1454 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_SHIFT_LEFT_RIGHT , "shifterman1")
1455 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_SHIFT_BACK_FORTH , "shifterman2")
1456 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_SEQUENTIAL_SHIFT , "sequential")
1457 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_GEAR_SELECT , "shifterlin")
1458 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_TORQUE , "torque")
1459 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_DIFFLOCK , "difflock")
1460 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_BOAT_RUDDER , "rudderboat")
1461 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_BOAT_THROTTLE , "throttleboat")
1462 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_SHORT_LIMIT , "shortlimit")
1463 ANIMATOR_ADD_FLAG(def, bAnd, OPTION_LONG_LIMIT , "longlimit")
1464
1465 ANIMATOR_ADD_AERIAL_FLAG(def, bAnd, OPTION_THROTTLE , "throttle")
1466 ANIMATOR_ADD_AERIAL_FLAG(def, bAnd, OPTION_RPM , "rpm")
1467 ANIMATOR_ADD_AERIAL_FLAG(def, bAnd, OPTION_TORQUE , "aerotorq")
1468 ANIMATOR_ADD_AERIAL_FLAG(def, bAnd, OPTION_PITCH , "aeropit")
1469 ANIMATOR_ADD_AERIAL_FLAG(def, bAnd, OPTION_STATUS , "aerostatus")
1470
1471 ANIMATOR_ADD_LIMIT(def, bAnd, OPTION_SHORT_LIMIT , "shortlimit", def.short_limit)
1472 ANIMATOR_ADD_LIMIT(def, bAnd, OPTION_LONG_LIMIT , "longlimit", def.long_limit)
1473 m_stream << endl;
1474 }
1475 m_stream << endl; // Empty line
1476}
1477
1479{
1480 if (module->contacters.empty())
1481 {
1482 return;
1483 }
1484 m_stream << "contacters" << endl << endl;
1485
1486 for (RigDef::Node::Ref& node: module->contacters)
1487 {
1488 m_stream << setw(m_node_id_width) << node.Str() << endl;
1489 }
1490
1491 m_stream << endl; // Empty line
1492}
1493
1495{
1496 if (module->rotators.empty())
1497 {
1498 return;
1499 }
1500 m_stream << "rotators" << endl << endl;
1501 auto end_itor = module->rotators.end();
1502 for (auto itor = module->rotators.begin(); itor != end_itor; ++itor)
1503 {
1504 this->ExportDocComment(module, Keyword::ROTATORS, std::distance(module->rotators.begin(), itor));
1505
1506 Rotator & def = *itor;
1507
1508 // Axis nodes
1509 m_stream
1510 << setw(m_node_id_width) << def.axis_nodes[0].Str() << ", "
1511 << setw(m_node_id_width) << def.axis_nodes[1].Str() << ", ";
1512
1513 // Baseplate nodes
1514 for (int i = 0; i < 4; ++i)
1515 {
1516 m_stream << setw(m_node_id_width) << def.base_plate_nodes[i].Str() << ", ";
1517 }
1518
1519 // Rotating plate nodes
1520 for (int i = 0; i < 4; ++i)
1521 {
1522 m_stream << setw(m_node_id_width) << def.rotating_plate_nodes[i].Str() << ", ";
1523 }
1524
1525 // Attributes
1526 m_stream << setw(m_float_width) << def.rate << ", "
1527 << setw(4) << def.spin_left_key << ", "
1528 << setw(4) << def.spin_right_key << ", ";
1529
1530 // Inertia
1531 m_stream
1532 << setw(m_float_width) << def.inertia.start_delay_factor << ", "
1533 << setw(m_float_width) << def.inertia.stop_delay_factor << ", "
1534 << def.inertia.start_function << ", "
1535 << def.inertia.stop_function << ", "
1536 << def.engine_coupling << ", "
1537 << (def.needs_engine ? "true" : "false");
1538 m_stream << endl;
1539 }
1540 m_stream << endl; // Empty line
1541}
1542
1544{
1545 if (module->rotators2.empty())
1546 {
1547 return;
1548 }
1549
1550 // Calc column widths
1551 size_t desc_w = 0, startf_w = 0, stopf_w = 0;
1552 for (RigDef::Rotator2& def: module->rotators2)
1553 {
1554 desc_w = std::max(desc_w, def.description.length());
1555 startf_w = std::max(startf_w, def.inertia.start_function.length());
1556 stopf_w = std::max(stopf_w, def.inertia.stop_function.length());
1557 }
1558
1559 // Write data
1560 m_stream << "rotators2" << endl << endl;
1561 auto end_itor = module->rotators2.end();
1562 for (auto itor = module->rotators2.begin(); itor != end_itor; ++itor)
1563 {
1564 this->ExportDocComment(module, Keyword::ROTATORS, std::distance(module->rotators2.begin(), itor));
1565
1566 Rotator2& def = *itor;
1567 // Axis nodes
1568 m_stream
1569 << setw(m_node_id_width)<< def.axis_nodes[0].Str() << ", "
1570 << setw(m_node_id_width)<< def.axis_nodes[1].Str() << ", ";
1571
1572 // Baseplate nodes
1573 for (int i = 0; i < 4; ++i)
1574 {
1575 m_stream << setw(m_node_id_width) << def.base_plate_nodes[i].Str() << ", ";
1576 }
1577
1578 // Rotating plate nodes
1579 for (int i = 0; i < 4; ++i)
1580 {
1581 m_stream << setw(m_node_id_width) << def.rotating_plate_nodes[i].Str() << ", ";
1582 }
1583
1584 // Attributes
1585 m_stream
1586 << setw(m_float_width) << def.rate << ", "
1587 << def.spin_left_key << ", "
1588 << def.spin_right_key << ", "
1589 << setw(m_float_width) << def.rotating_force << ", "
1590 << setw(m_float_width) << def.tolerance << ", "
1591 << setw(desc_w) << def.description << ", ";
1592
1593 // Inertia
1594 m_stream
1595 << setw(m_float_width) << def.inertia.start_delay_factor << ", "
1596 << setw(m_float_width) << def.inertia.stop_delay_factor << ", "
1597 << setw(startf_w) << def.inertia.start_function << ", "
1598 << setw(stopf_w) << def.inertia.stop_function << ", "
1599 << setw(m_float_width) << def.engine_coupling << ", "
1600 << (def.needs_engine ? "true" : "false");
1601 m_stream << endl;
1602 }
1603 m_stream << endl; // Empty line
1604}
1605
1607{
1608 if (module->flexbodywheels.empty())
1609 {
1610 return;
1611 }
1612
1613 this->ResetPresets();
1614
1615 m_stream << "flexbodywheels" << endl << endl;
1616 auto end_itor = module->flexbodywheels.end();
1617 for (auto itor = module->flexbodywheels.begin(); itor != end_itor; ++itor)
1618 {
1619 this->UpdatePresets(itor->beam_defaults.get(), itor->node_defaults.get(), nullptr);
1620
1621 this->ExportDocComment(module, Keyword::FLEXBODYWHEELS, std::distance(module->flexbodywheels.begin(), itor));
1623 << setw(m_float_width) << itor->tyre_radius << ", "
1624 << setw(m_float_width) << itor->rim_radius << ", "
1625 << setw(m_float_width) << itor->width << ", "
1626 << setw(3) << itor->num_rays << ", "
1627 << setw(m_node_id_width) << itor->nodes[0].Str() << ", "
1628 << setw(m_node_id_width) << itor->nodes[1].Str() << ", "
1629 << setw(m_node_id_width) << RigidityNodeToStr(itor->rigidity_node) << ", "
1630 << setw(3) << (int)itor->braking << ", "
1631 << setw(3) << (int)itor->propulsion << ", "
1632 << setw(m_node_id_width) << itor->reference_arm_node.Str() << ", "
1633 << setw(m_float_width) << itor->mass << ", "
1634 << setw(m_float_width) << itor->tyre_springiness << ", "
1635 << setw(m_float_width) << itor->tyre_damping << ", "
1636 << setw(m_float_width) << itor->rim_springiness << ", "
1637 << setw(m_float_width) << itor->rim_damping << ", "
1638 << (static_cast<char>(itor->side)) << ", "
1639 << itor->rim_mesh_name << " " // Separator = space!
1640 << itor->tyre_mesh_name
1641 << endl;
1642 }
1643
1644 m_stream << endl; // Empty line
1645}
1646
1648{
1649 if (module->tractioncontrol.size() == 0) { return; }
1650
1651 RigDef::TractionControl& def = module->tractioncontrol[module->tractioncontrol.size() - 1];
1652
1653 m_stream << "TractionControl "
1654 << setw(m_float_width) << def.regulation_force << ", "
1655 << setw(m_float_width) << def.wheel_slip << ", "
1656 << setw(m_float_width) << def.fade_speed << ", "
1657 << setw(m_float_width) << def.pulse_per_sec << ", "
1658 << "mode: " << (def.attr_is_on ? "ON" : "OFF");
1659
1660 // Modes
1661 if (def.attr_no_dashboard) { m_stream << " & NODASH "; }
1662 if (def.attr_no_toggle) { m_stream << " & NOTOGGLE "; }
1663
1664 m_stream << endl << endl; // Empty line
1665}
1666
1668{
1669 if (module->brakes.size() == 0) { return; }
1670
1671 Brakes& brakes = module->brakes[module->brakes.size() - 1];
1672
1673 m_stream << "brakes\n\t"
1674 << setw(m_float_width) << brakes.default_braking_force << ", "
1675 << setw(m_float_width) << brakes.parking_brake_force;
1676
1677 m_stream << endl << endl; // Empty line
1678}
1679
1681{
1682 if (module->antilockbrakes.size() == 0) { return; }
1683
1684 RigDef::AntiLockBrakes* alb = &module->antilockbrakes[module->antilockbrakes.size() - 1];
1685
1686 m_stream << "AntiLockBrakes "
1687 << setw(m_float_width) << alb->regulation_force << ", "
1688 << setw(m_float_width) << alb->min_speed << ", "
1689 << setw(m_float_width) << alb->pulse_per_sec << ", "
1690 << "mode: " << (alb->attr_is_on ? "ON" : "OFF");
1691 // Modes
1692 if (alb->attr_no_dashboard) { m_stream << " & NODASH "; }
1693 if (alb->attr_no_toggle) { m_stream << " & NOTOGGLE "; }
1694
1695 m_stream << endl << endl; // Empty line
1696}
1697
1699{
1700 if (module->engine.size() == 0)
1701 {
1702 return;
1703 }
1704
1705 Engine& engine = module->engine[module->engine.size() - 1];
1706
1707 m_stream << "engine"
1708 "\n;\t"
1709 "ShiftDownRPM,"
1710 " ShiftUpRPM,"
1711 " Torque,"
1712 " GlobalGear,"
1713 " ReverseGear,"
1714 " NeutralGear,"
1715 " Forward gears...\n\t"
1716 << setw(12) << engine.shift_down_rpm << ", "
1717 << setw(10) << engine.shift_up_rpm << ", "
1718 << setw(10) << engine.torque << ", "
1719 << setw(10) << engine.global_gear_ratio << ", "
1720 << setw(11) << engine.reverse_gear_ratio << ", "
1721 << setw(11) << engine.neutral_gear_ratio;
1722
1723 auto itor = engine.gear_ratios.begin();
1724 auto end = engine.gear_ratios.end();
1725 for (; itor != end; ++itor)
1726 {
1727 m_stream << ", " << *itor;
1728 }
1729 m_stream << ", -1.0" /*terminator*/ << endl << endl;
1730}
1731
1733{
1734 if (module->engoption.size() == 0)
1735 {
1736 return;
1737 }
1738
1739 Engoption& engoption = module->engoption[module->engoption.size() - 1];
1740
1741 m_stream << "engoption"
1742 "\n;\t"
1743 "EngInertia,"
1744 " EngineType,"
1745 " ClutchForce,"
1746 " ShiftTime,"
1747 " ClutchTime,"
1748 " PostShiftTime,"
1749 " StallRPM,"
1750 " IdleRPM,"
1751 " MaxIdleMixture,"
1752 " MinIdleMixture"
1753 " BrakingForce"
1754 "\n\t"
1755 << setw(10) << engoption.inertia << ", "
1756 << setw(10) << (char)engoption.type << ", "
1757 << setw(11) << engoption.clutch_force << ", "
1758 << setw( 9) << engoption.shift_time << ", "
1759 << setw(10) << engoption.clutch_time << ", "
1760 << setw(13) << engoption.post_shift_time << ", "
1761 << setw( 8) << engoption.stall_rpm << ", "
1762 << setw( 7) << engoption.idle_rpm << ", "
1763 << setw(14) << engoption.max_idle_mixture << ", "
1764 << setw(14) << engoption.min_idle_mixture << ", "
1765 << setw(15) << engoption.braking_torque;
1766
1767 m_stream << endl << endl; // Empty line
1768}
1769
1771{
1772 if (module->help.size() == 0)
1773 {
1774 return;
1775 }
1776 m_stream << "help\n\t" << module->help[module->help.size() - 1].material << endl << endl;
1777}
1778
1780{
1781 if (module->wheels2.empty())
1782 {
1783 return;
1784 }
1785
1786 this->ResetPresets();
1787 m_stream << "wheels2" << endl << endl;
1788 auto end_itor = module->wheels2.end();
1789 for (auto itor = module->wheels2.begin(); itor != end_itor; ++itor)
1790 {
1791 this->UpdatePresets(itor->beam_defaults.get(), itor->node_defaults.get(), nullptr);
1792
1793 this->ExportDocComment(module, Keyword::WHEELS2, std::distance(module->wheels2.begin(), itor));
1795 << setw(m_float_width) << itor->tyre_radius << ", "
1796 << setw(m_float_width) << itor->rim_radius << ", "
1797 << setw(m_float_width) << itor->width << ", "
1798 << setw(3) << itor->num_rays << ", "
1799 << setw(m_node_id_width) << itor->nodes[0].Str() << ", "
1800 << setw(m_node_id_width) << itor->nodes[1].Str() << ", "
1801 << setw(m_node_id_width) << RigidityNodeToStr(itor->rigidity_node) << ", "
1802 << setw(3) << (int)itor->braking << ", "
1803 << setw(3) << (int)itor->propulsion << ", "
1804 << setw(m_node_id_width) << itor->reference_arm_node.Str() << ", "
1805 << setw(m_float_width) << itor->mass << ", "
1806 << setw(m_float_width) << itor->rim_springiness << ", "
1807 << setw(m_float_width) << itor->rim_damping << ", "
1808 << setw(m_float_width) << itor->tyre_springiness << ", "
1809 << setw(m_float_width) << itor->tyre_damping << ", "
1810 << itor->face_material_name << " " // Separator = space!
1811 << itor->band_material_name << " " // Separator = space!
1812 ;
1813 m_stream << endl;
1814 }
1815
1816 m_stream << endl; // Empty line
1817}
1818
1820{
1821 if (module->wheels.empty())
1822 {
1823 return;
1824 }
1825
1826 this->ResetPresets();
1827 m_stream << "wheels" << endl << endl;
1828 m_stream << ";\t"
1829 << setw(m_float_width) << "radius, "
1830 << setw(m_float_width) << "width, "
1831 << setw(3) << "nrays, "
1832 << setw(m_node_id_width) << "n1, "
1833 << setw(m_node_id_width) << "n2, "
1834 << setw(m_node_id_width) << "snode, "
1835 << setw(3) << "brk, "
1836 << setw(3) << "pwr, "
1837 << setw(m_node_id_width) << "arm, "
1838 << setw(m_float_width) << "mass, "
1839 << setw(m_float_width) << "spring, "
1840 << setw(m_float_width) << "damp, "
1841 << "facemat, "
1842 << "bandmat";
1843
1844 auto end_itor = module->wheels.end();
1845 for (auto itor = module->wheels.begin(); itor != end_itor; ++itor)
1846 {
1847 this->UpdatePresets(itor->beam_defaults.get(), itor->node_defaults.get(), nullptr);
1848
1849 this->ExportDocComment(module, Keyword::WHEELS, std::distance(module->wheels.begin(), itor));
1851 << setw(m_float_width) << itor->radius << ", "
1852 << setw(m_float_width) << itor->width << ", "
1853 << setw(3) << itor->num_rays << ", "
1854 << setw(m_node_id_width) << itor->nodes[0].Str() << ", "
1855 << setw(m_node_id_width) << itor->nodes[1].Str() << ", "
1856 << setw(m_node_id_width) << RigidityNodeToStr(itor->rigidity_node) << ", "
1857 << setw(3) << (int)itor->braking << ", "
1858 << setw(3) << (int)itor->propulsion << ", "
1859 << setw(m_node_id_width) << itor->reference_arm_node.Str() << ", "
1860 << setw(m_float_width) << itor->mass << ", "
1861 << setw(m_float_width) << itor->springiness << ", "
1862 << setw(m_float_width) << itor->damping << ", "
1863 << itor->face_material_name << " " // Separator = space!
1864 << itor->band_material_name << " " // Separator = space!
1865 ;
1866 m_stream << endl;
1867 }
1868
1869 m_stream << endl; // Empty line
1870}
1871
1873{
1874 this->UpdatePresets(def.beam_defaults.get(), def.node_defaults.get(), nullptr);
1875
1877 << setw(m_float_width) << def.tyre_radius << ", "
1878 << setw(m_float_width) << def.rim_radius << ", "
1879 << setw(m_float_width) << def.width << ", "
1880 << setw(3) << def.num_rays << ", "
1881 << setw(m_node_id_width) << def.nodes[0].Str() << ", "
1882 << setw(m_node_id_width) << def.nodes[1].Str() << ", "
1883 << setw(m_node_id_width) << RigidityNodeToStr(def.rigidity_node) << ", "
1884 << setw(3) << (int)def.braking << ", "
1885 << setw(3) << (int)def.propulsion << ", "
1886 << setw(m_node_id_width) << def.reference_arm_node.Str() << ", "
1887 << setw(m_float_width) << def.mass << ", "
1888 << setw(m_float_width) << def.spring << ", "
1889 << setw(m_float_width) << def.damping << ", "
1890 << (static_cast<char>(def.side)) << ", "
1891 << def.mesh_name << " " // Separator = space!
1892 << def.material_name;
1893 m_stream << endl;
1894}
1895
1897{
1898 if (module->meshwheels.empty()) { return; }
1899
1900 this->ResetPresets();
1901
1902 m_stream << "meshwheels" << "\n\n";
1903
1904 for (MeshWheel& def: module->meshwheels)
1905 {
1906 this->ExportBaseMeshWheel(def);
1907 }
1908
1909 m_stream << endl; // Empty line
1910
1911}
1912
1914{
1915 if (module->meshwheels2.empty()) { return; }
1916
1917 this->ResetPresets();
1918
1919 m_stream << "meshwheels2" << "\n\n";
1920
1921 for (MeshWheel2& def: module->meshwheels2)
1922 {
1923 this->ExportBaseMeshWheel(def);
1924 }
1925
1926 m_stream << endl; // Empty line
1927}
1928
1930{
1931 if (module->cameras.empty())
1932 {
1933 return;
1934 }
1935
1936 m_stream << "cameras\n\n";
1937 for (auto& camera: module->cameras)
1938 {
1939 m_stream
1940 << setw(m_node_id_width) << camera.center_node.Str() << ", "
1941 << setw(m_node_id_width) << camera.back_node.Str() << ", "
1942 << setw(m_node_id_width) << camera.left_node.Str() << "\n";
1943 }
1944 m_stream << "\n";
1945}
1946
1948{
1949 if (module->cinecam.empty())
1950 {
1951 return;
1952 }
1953
1954 m_stream << "cinecam" << endl << endl;
1955
1956 for (auto itor = module->cinecam.begin(); itor != module->cinecam.end(); ++itor)
1957 {
1958 this->ExportDocComment(module, Keyword::CINECAM, std::distance(module->cinecam.begin(), itor));
1960 << setw(m_float_width) << itor->position.x << ", "
1961 << setw(m_float_width) << itor->position.y << ", "
1962 << setw(m_float_width) << itor->position.z << ", ";
1963 m_stream
1964 << setw(m_node_id_width) << itor->nodes[0].Str() << ", "
1965 << setw(m_node_id_width) << itor->nodes[1].Str() << ", "
1966 << setw(m_node_id_width) << itor->nodes[2].Str() << ", "
1967 << setw(m_node_id_width) << itor->nodes[3].Str() << ", "
1968 << setw(m_node_id_width) << itor->nodes[4].Str() << ", "
1969 << setw(m_node_id_width) << itor->nodes[5].Str() << ", "
1970 << setw(m_node_id_width) << itor->nodes[6].Str() << ", "
1971 << setw(m_node_id_width) << itor->nodes[7].Str() << ", ";
1972 m_stream
1973 << setw(m_float_width) << itor->spring << ", "
1974 << setw(m_float_width) << itor->damping
1975 << endl;
1976 }
1977
1978 m_stream << endl; // Empty line
1979}
1980
1982{
1983 if (module->beams.empty())
1984 {
1985 return;
1986 }
1987
1988 // Write beams to file
1989 m_stream << "beams" << endl << endl;
1990
1991 BeamDefaults* prev_defaults = nullptr;
1992 for (size_t i = 0; i < module->beams.size(); i++)
1993 {
1994 Beam& beam = module->beams[i];
1995 if (prev_defaults != beam.defaults.get())
1996 {
1997 ProcessBeamDefaults(beam.defaults.get());
1998 prev_defaults = beam.defaults.get();
1999 }
2000 this->ExportDocComment(module, Keyword::BEAMS, i);
2001 this->ProcessBeam(beam);
2002 }
2003
2004 // Empty line
2005 m_stream << endl;
2006}
2007
2009{
2010 if (module->shocks.empty())
2011 {
2012 return;
2013 }
2014
2015 // Write shocks to file
2016 m_stream << "shocks" << endl << endl;
2017
2018 BeamDefaults* prev_defaults = nullptr;
2019 for (size_t i = 0; i < module->shocks.size(); i++)
2020 {
2021 Shock& shock = module->shocks[i];
2022 if (prev_defaults != shock.beam_defaults.get())
2023 {
2025 prev_defaults = shock.beam_defaults.get();
2026 }
2027 this->ExportDocComment(module, Keyword::SHOCKS, i);
2028 this->ProcessShock(shock);
2029 }
2030
2031 // Empty line
2032 m_stream << endl;
2033}
2034
2036{
2037 if (module->shocks2.empty())
2038 {
2039 return;
2040 }
2041
2042 // Write shocks2 to file
2043 m_stream << "shocks2" << endl << endl;
2044
2045 BeamDefaults* prev_defaults = nullptr;
2046 for (size_t i = 0; i < module->shocks2.size(); i++)
2047 {
2048 Shock2& shock2 = module->shocks2[i];
2049 if (prev_defaults != shock2.beam_defaults.get())
2050 {
2051 ProcessBeamDefaults(shock2.beam_defaults.get());
2052 prev_defaults = shock2.beam_defaults.get();
2053 }
2054 this->ExportDocComment(module, Keyword::SHOCKS2, i);
2055 this->ProcessShock2(shock2);
2056 }
2057
2058 // Empty line
2059 m_stream << endl;
2060}
2061
2063{
2064 if (module->shocks3.empty())
2065 {
2066 return;
2067 }
2068
2069 // Write shocks3 to file
2070 m_stream << "shocks3" << endl << endl;
2071
2072 BeamDefaults* prev_defaults = nullptr;
2073 for (size_t i = 0; i < module->shocks3.size(); i++)
2074 {
2075 Shock3& shock3 = module->shocks3[i];
2076 if (prev_defaults != shock3.beam_defaults.get())
2077 {
2078 ProcessBeamDefaults(shock3.beam_defaults.get());
2079 prev_defaults = shock3.beam_defaults.get();
2080 }
2081 this->ExportDocComment(module, Keyword::SHOCKS3, i);
2082 this->ProcessShock3(shock3);
2083 }
2084
2085 // Empty line
2086 m_stream << endl;
2087}
2088
2089
2091{
2092 if (module->hydros.empty())
2093 {
2094 return;
2095 }
2096
2097 // Write hydros to file
2098 m_stream << "hydros" << endl << endl;
2099
2100 BeamDefaults* prev_defaults = nullptr;
2101 for (size_t i = 0; i < module->hydros.size(); i++)
2102 {
2103 Hydro& hydro = module->hydros[i];
2104 if (prev_defaults != hydro.beam_defaults.get())
2105 {
2107 prev_defaults = hydro.beam_defaults.get();
2108 }
2109 this->ExportDocComment(module, Keyword::HYDROS, i);
2110 this->ProcessHydro(hydro);
2111 }
2112
2113 // Empty line
2114 m_stream << endl;
2115}
2116
2118{
2119 if (module->commands2.empty())
2120 {
2121 return;
2122 }
2123
2124 // Write commands to file
2125 m_stream << "commands" << endl << endl;
2126
2127 BeamDefaults* prev_defaults = nullptr;
2128 for (size_t i = 0; i < module->commands2.size(); i++)
2129 {
2130 Command2& command = module->commands2[i];
2131 if (prev_defaults != command.beam_defaults.get())
2132 {
2133 ProcessBeamDefaults(command.beam_defaults.get());
2134 prev_defaults = command.beam_defaults.get();
2135 }
2136 this->ExportDocComment(module, Keyword::COMMANDS2, i);
2137 this->ProcessCommand2(command);
2138 }
2139
2140 // Empty line
2141 m_stream << endl;
2142}
2143
2144
2146{
2148 << std::setw(m_node_id_width) << def.nodes[0].Str() << ", "
2149 << std::setw(m_node_id_width) << def.nodes[1].Str() << ", ";
2150
2151 m_stream << std::setw(m_float_width) << def.shorten_rate << ", ";
2152 m_stream << std::setw(m_float_width) << def.lengthen_rate << ", ";
2153 m_stream << std::setw(m_float_width) << def.max_contraction << ", "; // So-called 'shortbound'
2154 m_stream << std::setw(m_float_width) << def.max_extension << ", "; // So-called 'longbound'
2155 m_stream << std::setw(m_command_key_width) << def.contract_key << ", ";
2156 m_stream << std::setw(m_command_key_width) << def.extend_key << ", ";
2157
2158 // Options
2159 bool dummy = true;
2160 if (def.option_c_auto_center) { m_stream << "c"; dummy = false; }
2161 if (def.option_f_not_faster) { m_stream << "f"; dummy = false; }
2162 if (def.option_i_invisible) { m_stream << "i"; dummy = false; }
2163 if (def.option_o_1press_center) { m_stream << "o"; dummy = false; }
2164 if (def.option_p_1press) { m_stream << "p"; dummy = false; }
2165 if (def.option_r_rope) { m_stream << "r"; dummy = false; }
2166 if (dummy) { m_stream << "n"; } // Placeholder, does nothing
2167
2168 m_stream << ", ";
2169
2170 // Description
2171 m_stream << (def.description.length() > 0 ? def.description : "_");
2172
2173 // Inertia
2174 if (def.inertia.start_function != "" && def.inertia.stop_function != "")
2175 {
2176 m_stream << ", ";
2177 m_stream << std::setw(m_float_width) << def.inertia.start_delay_factor << ", ";
2178 m_stream << std::setw(m_float_width) << def.inertia.stop_delay_factor << ", ";
2179 m_stream << std::setw(m_inertia_function_width) << def.inertia.start_function << ", ";
2180 m_stream << std::setw(m_inertia_function_width) << def.inertia.stop_function << ", ";
2181 m_stream << std::setw(m_float_width) << def.affect_engine << ", ";
2182 m_stream << std::setw(m_bool_width) << (def.needs_engine ? "true" : "false");
2183 }
2184 m_stream << endl;
2185}
2186
2188{
2190 << std::setw(m_node_id_width) << def.nodes[0].Str() << ", "
2191 << std::setw(m_node_id_width) << def.nodes[1].Str() << ", ";
2192
2193 m_stream << std::setw(m_float_width) << def.lenghtening_factor << ", ";
2194
2195 // Options
2208 if (def.options == 0) m_stream << (char)HydroOption::n_INPUT_NORMAL;
2209
2210 // Inertia
2211 Inertia & inertia = def.inertia;
2212 if (inertia.start_delay_factor != 0 && inertia.stop_delay_factor != 0)
2213 {
2214 m_stream << ", ";
2215 m_stream << std::setw(m_float_width) << inertia.start_delay_factor << ", ";
2216 m_stream << std::setw(m_float_width) << inertia.stop_delay_factor;
2217 if (!inertia.start_function.empty())
2218 {
2219 m_stream << ", " << std::setw(m_inertia_function_width) << inertia.start_function;
2220 if (!inertia.stop_function.empty())
2221 {
2222 m_stream << ", " << std::setw(m_inertia_function_width) << inertia.stop_function;
2223 }
2224 }
2225 }
2226 m_stream << endl;
2227}
2228
2230{
2232 << std::setw(m_node_id_width) << def.nodes[0].Str() << ", "
2233 << std::setw(m_node_id_width) << def.nodes[1].Str() << ", ";
2234 m_stream << std::setw(m_float_width) << def.spring_rate << ", ";
2235 m_stream << std::setw(m_float_width) << def.damping << ", ";
2236 m_stream << std::setw(m_float_width) << def.short_bound << ", ";
2237 m_stream << std::setw(m_float_width) << def.long_bound << ", ";
2238 m_stream << std::setw(m_float_width) << def.precompression << ", ";
2239
2240 // Options
2241 if (def.options == 0)
2242 {
2243 m_stream << "n"; // Placeholder
2244 }
2245 else
2246 {
2248 {
2249 m_stream << "i";
2250 }
2252 {
2253 m_stream << "m";
2254 }
2256 {
2257 m_stream << "L";
2258 }
2260 {
2261 m_stream << "R";
2262 }
2263 }
2264
2265 // Empty line
2266 m_stream << endl;
2267}
2268
2270{
2272 << std::setw(m_node_id_width) << def.nodes[0].Str() << ", "
2273 << std::setw(m_node_id_width) << def.nodes[1].Str() << ", ";
2274
2275 m_stream << std::setw(m_float_width) << def.spring_in << ", ";
2276 m_stream << std::setw(m_float_width) << def.damp_in << ", ";
2277 m_stream << std::setw(m_float_width) << def.progress_factor_spring_in << ", ";
2278 m_stream << std::setw(m_float_width) << def.progress_factor_damp_in << ", ";
2279
2280 m_stream << std::setw(m_float_width) << def.spring_out << ", ";
2281 m_stream << std::setw(m_float_width) << def.damp_out << ", ";
2282 m_stream << std::setw(m_float_width) << def.progress_factor_spring_out << ", ";
2283 m_stream << std::setw(m_float_width) << def.progress_factor_damp_out << ", ";
2284
2285 m_stream << std::setw(m_float_width) << def.short_bound << ", ";
2286 m_stream << std::setw(m_float_width) << def.long_bound << ", ";
2287 m_stream << std::setw(m_float_width) << def.precompression << ", ";
2288
2289 // Options
2290 if (def.options == 0)
2291 {
2292 m_stream << "n"; // Placeholder
2293 }
2294 else
2295 {
2297 {
2298 m_stream << "i";
2299 }
2301 {
2302 m_stream << "m";
2303 }
2305 {
2306 m_stream << "M";
2307 }
2309 {
2310 m_stream << "s";
2311 }
2312 }
2313
2314 // Empty line
2315 m_stream << endl;
2316}
2317
2319{
2321 << std::setw(m_node_id_width) << def.nodes[0].Str() << ", "
2322 << std::setw(m_node_id_width) << def.nodes[1].Str() << ", ";
2323
2324 m_stream << std::setw(m_float_width) << def.spring_in << ", ";
2325 m_stream << std::setw(m_float_width) << def.damp_in << ", ";
2326 m_stream << std::setw(m_float_width) << def.damp_in_slow << ", ";
2327 m_stream << std::setw(m_float_width) << def.split_vel_in << ", ";
2328 m_stream << std::setw(m_float_width) << def.damp_in_fast << ", ";
2329
2330 m_stream << std::setw(m_float_width) << def.spring_out << ", ";
2331 m_stream << std::setw(m_float_width) << def.damp_out << ", ";
2332 m_stream << std::setw(m_float_width) << def.damp_out_slow << ", ";
2333 m_stream << std::setw(m_float_width) << def.split_vel_out << ", ";
2334 m_stream << std::setw(m_float_width) << def.damp_out_fast << ", ";
2335
2336 m_stream << std::setw(m_float_width) << def.short_bound << ", ";
2337 m_stream << std::setw(m_float_width) << def.long_bound << ", ";
2338 m_stream << std::setw(m_float_width) << def.precompression << ", ";
2339
2340 // Options
2341 if (def.options != 0)
2342 {
2343 m_stream << "n"; // Placeholder
2344 }
2345 else
2346 {
2348 {
2349 m_stream << "i";
2350 }
2352 {
2353 m_stream << "m";
2354 }
2356 {
2357 m_stream << "M";
2358 }
2359 }
2360
2361 // Empty line
2362 m_stream << endl;
2363}
2364
2366{
2367 if (beam_defaults != nullptr)
2368 {
2369 m_stream << fmt::format("{}set_beam_defaults {}, {}, {}, {}, {}, {}, {}\n",
2371 (beam_defaults->springiness == DEFAULT_SPRING) ? -1.f : beam_defaults->springiness,
2372 (beam_defaults->damping_constant == DEFAULT_DAMP) ? -1.f : beam_defaults->damping_constant,
2373 (beam_defaults->deformation_threshold == BEAM_DEFORM) ? -1.f : beam_defaults->deformation_threshold,
2374 (beam_defaults->breaking_threshold == BEAM_BREAK) ? -1.f : beam_defaults->breaking_threshold,
2375 beam_defaults->visual_beam_diameter,
2376 beam_defaults->beam_material_name,
2377 beam_defaults->plastic_deform_coef);
2378 }
2379 else
2380 {
2381 m_stream << fmt::format("{}set_beam_defaults {}, {}, {}, {}, {}, {}, {}\n",
2382 m_setdefaults_indentstr, -1, -1, -1, -1, -1, " ", -1);
2383 }
2384}
2385
2387{
2389 << std::setw(m_node_id_width) << beam.nodes[0].Str() << ", "
2390 << std::setw(m_node_id_width) << beam.nodes[1].Str() << ", ";
2391
2392 // Options
2393 if (beam.options == 0u)
2394 {
2395 m_stream << "n"; // Placeholder
2396 }
2397 else
2398 {
2400 {
2401 m_stream << "i";
2402 }
2404 {
2405 m_stream << "r";
2406 }
2408 {
2409 m_stream << "s";
2410 }
2411 }
2412
2414 {
2415 m_stream << ", " << beam.extension_break_limit;
2416 }
2417
2418 m_stream << endl;
2419}
2420
2422{
2423 if (module->nodes.empty())
2424 {
2425 return;
2426 }
2427
2428 // Numbered nodes
2429 m_stream << "nodes" << endl << endl;
2430
2431 size_t num_named = 0;
2432 NodeDefaults* prev_preset = nullptr;
2433 DefaultMinimass* prev_dminimass = nullptr;
2434 for (size_t i = 0; i < module->nodes.size(); i++)
2435 {
2436 Node& node = module->nodes[i];
2437 if (node.id.IsTypeNamed())
2438 {
2439 ++num_named;
2440 }
2441
2442 NodeDefaults* preset = node.node_defaults.get();
2443 if (preset != prev_preset)
2444 {
2445 this->ProcessNodeDefaults(preset);
2446 prev_preset = preset;
2447 }
2448
2449 DefaultMinimass* dminimass = node.default_minimass.get();
2450 if (dminimass != prev_dminimass)
2451 {
2452 this->ProcessDefaultMinimass(dminimass);
2453 prev_dminimass = dminimass;
2454 }
2455 this->ExportDocComment(module, Keyword::NODES, i);
2456 this->ProcessNode(node);
2457 }
2458
2459 // Named nodes
2460 if (num_named > 0)
2461 {
2462 m_stream << endl << endl << "nodes2" << endl;
2463
2464 for (size_t i = 0; i < module->nodes.size(); i++)
2465 {
2466 Node& node = module->nodes[i];
2467 if (!node.id.IsTypeNamed())
2468 {
2469 continue;
2470 }
2471
2472 NodeDefaults* preset = node.node_defaults.get();
2473 if (preset != prev_preset)
2474 {
2475 this->ProcessNodeDefaults(preset);
2476 prev_preset = preset;
2477 }
2478
2479 DefaultMinimass* dminimass = node.default_minimass.get();
2480 if (dminimass != prev_dminimass)
2481 {
2482 this->ProcessDefaultMinimass(dminimass);
2483 prev_dminimass = dminimass;
2484 }
2485
2486 this->ExportDocComment(module, Keyword::NODES2, i);
2487 this->ProcessNode(node);
2488 }
2489 }
2490
2491 // Empty line
2492 m_stream << endl;
2493}
2494
2496{
2497 if (node_defaults != nullptr)
2498 {
2499 m_stream << fmt::format("{}set_node_defaults {}, {}, {}, {}, {}\n",
2501 node_defaults->load_weight,
2502 node_defaults->friction,
2503 node_defaults->volume,
2504 node_defaults->surface,
2505 NodeOptionsToStr(node_defaults->options));
2506 }
2507 else
2508 {
2509 m_stream << fmt::format("{}set_node_defaults {}, {}, {}, {}, {}\n",
2510 m_setdefaults_indentstr, -1, -1, -1, -1, 'n');
2511 }
2512}
2513
2515{
2516 std::string retval;
2517
2518 if (options & Node::OPTION_m_NO_MOUSE_GRAB ) { retval += (char)NodeOption::m_NO_MOUSE_GRAB ; }
2519 if (options & Node::OPTION_f_NO_SPARKS ) { retval += (char)NodeOption::f_NO_SPARKS ; }
2520 if (options & Node::OPTION_x_EXHAUST_POINT ) { retval += (char)NodeOption::x_EXHAUST_POINT ; }
2521 if (options & Node::OPTION_y_EXHAUST_DIRECTION ) { retval += (char)NodeOption::y_EXHAUST_DIRECTION ; }
2522 if (options & Node::OPTION_c_NO_GROUND_CONTACT ) { retval += (char)NodeOption::c_NO_GROUND_CONTACT ; }
2523 if (options & Node::OPTION_h_HOOK_POINT ) { retval += (char)NodeOption::h_HOOK_POINT ; }
2525 if (options & Node::OPTION_b_EXTRA_BUOYANCY ) { retval += (char)NodeOption::b_EXTRA_BUOYANCY ; }
2526 if (options & Node::OPTION_p_NO_PARTICLES ) { retval += (char)NodeOption::p_NO_PARTICLES ; }
2527 if (options & Node::OPTION_L_LOG ) { retval += (char)NodeOption::L_LOG ; }
2528 if (options & Node::OPTION_l_LOAD_WEIGHT ) { retval += (char)NodeOption::l_LOAD_WEIGHT ; }
2529
2530 if (retval == "")
2531 retval += (char)RigDef::NodeOption::n_DUMMY;
2532
2533 return retval;
2534}
2535
2537{
2538 m_stream << fmt::format("{}set_default_minimass {}\n",
2540 (def != nullptr) ? def->min_mass_Kg : -1);
2541}
2542
2544{
2545 m_stream << fmt::format("{}{}, {:>{}}, {:>{}}, {:>{}}, {}, {}\n",
2547 node.id.Str(),
2548 node.position.x, m_float_width,
2549 node.position.y, m_float_width,
2550 node.position.z, m_float_width,
2552 (node._has_load_weight_override) ? fmt::format("{}", node.load_weight_override) : "");
2553}
2554
2556{
2557 if (m_rig_def->enable_advanced_deformation)
2558 {
2559 m_stream << "enable_advanced_deformation" << endl << endl;
2560 }
2561 if (m_rig_def->hide_in_chooser)
2562 {
2563 m_stream << "hideInChooser" << endl << endl;
2564 }
2565 if (m_rig_def->slide_nodes_connect_instantly)
2566 {
2567 m_stream << "slidenode_connect_instantly" << endl << endl;
2568 }
2569 if (m_rig_def->lockgroup_default_nolock)
2570 {
2571 m_stream << "lockgroup_default_nolock" << endl << endl;
2572 }
2573 if (m_rig_def->rollon)
2574 {
2575 m_stream << "rollon" << endl << endl;
2576 }
2577 if (m_rig_def->rescuer)
2578 {
2579 m_stream << "rescuer" << endl << endl;
2580 }
2581 if (m_rig_def->disable_default_sounds)
2582 {
2583 m_stream << "disabledefaultsounds" << endl << endl;
2584 }
2585 if (m_rig_def->forward_commands)
2586 {
2587 m_stream << "forwardcommands" << endl << endl;
2588 }
2589 if (m_rig_def->import_commands)
2590 {
2591 m_stream << "importcommands" << endl << endl;
2592 }
2593}
2594
2596{
2597 if (module->fileinfo.size() > 0)
2598 {
2599 Fileinfo& data = module->fileinfo[module->fileinfo.size() - 1];
2600
2601 m_stream << "fileinfo ";
2602 m_stream << data.unique_id;
2603 m_stream << ", " << data.category_id;
2604 m_stream << ", " << data.file_version;
2605
2606 m_stream << endl << endl;
2607 }
2608}
2609
2611{
2612 if (! module->guid.empty())
2613 {
2614 m_stream << "guid " << module->guid[module->guid.size() - 1].guid << endl << endl;
2615 }
2616}
2617
2619{
2620 if (module->description.size() != 0)
2621 {
2622 m_stream << "description";
2623 for (auto itor = module->description.begin(); itor != module->description.end(); ++itor)
2624 {
2625 std::string line = *itor;
2626 m_stream << endl << line;
2627 }
2628 m_stream << endl << "end_description" << endl << endl;
2629 }
2630}
2631
2633{
2634 for (auto itor = module->author.begin(); itor != module->author.end(); ++itor)
2635 {
2636 Author & def = *itor;
2637 m_stream << "author " << def.type << " ";
2638 if (def._has_forum_account)
2639 {
2640 m_stream << def.forum_account_id << " ";
2641 }
2642 else
2643 {
2644 m_stream << "-1 ";
2645 }
2646 m_stream << def.name << " " << def.email << endl;
2647 }
2648 m_stream << endl;
2649}
2650
2652{
2653 if (module->globals.size() == 0)
2654 {
2655 return;
2656 }
2657
2658 m_stream << "globals\n\t"
2659 << module->globals[0].dry_mass << ", "
2660 << module->globals[0].cargo_mass;
2661 if (!module->globals[0].material_name.empty())
2662 {
2663 m_stream << ", " << module->globals[0].material_name;
2664 }
2665 m_stream << endl << endl;
2666}
2667
2669{
2670 m_current_node_defaults = nullptr;
2671 m_current_beam_defaults = nullptr;
2673}
2674
2675void Serializer::UpdatePresets(BeamDefaults* beam_defaults, NodeDefaults* node_defaults, DefaultMinimass* default_minimass)
2676{
2677 if (m_current_node_defaults != node_defaults)
2678 {
2679 m_current_node_defaults = node_defaults;
2680 this->ProcessNodeDefaults(node_defaults);
2681 }
2682
2683 if (m_current_beam_defaults != beam_defaults)
2684 {
2685 m_current_beam_defaults = beam_defaults;
2686 this->ProcessBeamDefaults(beam_defaults);
2687 }
2688
2689 if (m_current_default_minimass != default_minimass)
2690 {
2691 m_current_default_minimass = default_minimass;
2692 this->ProcessDefaultMinimass(default_minimass);
2693 }
2694}
2695
2697{
2698 auto itor = std::find_if(module->_comments.begin(), module->_comments.end(),
2699 [keyword, vectorpos](const RigDef::DocComment& dc) { return dc.commented_keyword == keyword && dc.commented_datapos == (int)vectorpos; });
2700
2701 if (itor != module->_comments.end())
2702 {
2703 m_stream << itor->comment_text;
2704 }
2705}
2706
#define BITMASK_IS_1(VAR, FLAGS)
Definition BitFlags.h:14
uint32_t BitMask_t
Definition BitFlags.h:7
Data structures representing 'truck' file format, see https://docs.rigsofrods.org/vehicle-creation/fi...
#define ANIMATOR_ADD_FLAG(DEF_VAR, AND_VAR, BITMASK_CONST, NAME_STR)
void PropAnimFlag(std::stringstream &out, int flags, bool &join, unsigned int mask, const char *name, char joiner='|')
#define ANIMATOR_ADD_LIMIT(DEF_VAR, AND_VAR, BITMASK_CONST, NAME_STR, VALUE)
#define ANIMATOR_ADD_AERIAL_FLAG(DEF_VAR, AND_VAR, BITMASK_CONST, NAME_STR)
std::string const & Str() const
Definition RigDef_Node.h:61
Legacy parser resolved references on-the-fly and the condition to check named nodes was "are there an...
Definition RigDef_Node.h:78
bool IsValidAnyState() const
std::string const & Str() const
Definition RigDef_Node.h:94
void ProcessRopables(Document::Module *module)
void ProcessAntiLockBrakes(Document::Module *module)
void ProcessBrakes(Document::Module *module)
void ProcessTurboprops(Document::Module *module)
void ProcessScrewprops(Document::Module *module)
void ProcessShock2(Shock2 &def)
void ProcessAuthors(Document::Module *module)
std::string m_setdefaults_indentstr
'set_beam_defaults' for example
void ProcessExhausts(Document::Module *module)
void ProcessDefaultMinimass(DefaultMinimass *default_minimass)
void ProcessHelp(Document::Module *module)
void ProcessDirectiveAddAnimation(RigDef::Animation &anim)
NodeDefaults * m_current_node_defaults
void ProcessCollisionBoxes(Document::Module *module)
void ExportBaseMeshWheel(BaseMeshWheel &def)
void ProcessAirbrakes(Document::Module *module)
void ProcessInterAxles(Document::Module *module)
void ProcessFusedrag(Document::Module *module)
void ProcessSubmeshGroundmodel(Document::Module *module)
void ProcessSoundsources2(Document::Module *module)
void ProcessRopes(Document::Module *module)
void ProcessShocks(Document::Module *)
void ProcessNode(Node &node)
void ProcessNodeDefaults(NodeDefaults *node_defaults)
void ProcessCameras(Document::Module *module)
void ProcessMeshWheels2(Document::Module *module)
void ProcessBeam(Beam &beam)
void ProcessWings(Document::Module *module)
void ProcessParticles(Document::Module *module)
void ProcessGlobals(Document::Module *module)
std::string RigidityNodeToStr(Node::Ref node)
void ProcessCinecam(Document::Module *)
DefaultMinimass * m_current_default_minimass
void ProcessWheels2(Document::Module *module)
void ProcessRailGroups(Document::Module *module)
void ProcessSubmesh(Document::Module *module)
void ProcessHooks(Document::Module *module)
void ProcessWheels(Document::Module *module)
void ProcessCommand2(Command2 &def)
void ProcessEngoption(Document::Module *module)
void ProcessPistonprops(Document::Module *module)
void ProcessFileinfo(Document::Module *module)
void ProcessHydro(Hydro &def)
void ProcessShock3(Shock3 &def)
void ProcessFlexbodies(Document::Module *module)
void ProcessContacters(Document::Module *module)
void ProcessTriggers(Document::Module *module)
void ProcessBeamDefaults(BeamDefaults *beam_defaults)
void ProcessGuid(Document::Module *module)
void ProcessDescription(Document::Module *module)
void ProcessCommands2(Document::Module *)
std::stringstream m_stream
void ProcessAnimators(Document::Module *module)
void UpdatePresets(BeamDefaults *beam, NodeDefaults *node, DefaultMinimass *minimass)
void ProcessCustomDashboardInputs(Document::Module *module)
void ProcessTies(Document::Module *module)
void ProcessShocks3(Document::Module *)
void ProcessFlexBodyWheels(Document::Module *module)
void ProcessShock(Shock &def)
std::string NodeOptionsToStr(BitMask_t options)
void ProcessTractionControl(Document::Module *module)
void ProcessMaterialFlareBindings(Document::Module *module)
void ProcessGuiSettings(Document::Module *module)
void ProcessNodes(Document::Module *)
void ProcessMeshWheels(Document::Module *module)
void ProcessFixes(Document::Module *module)
void ProcessPropsAndAnimations(Document::Module *module)
void SerializeModule(std::shared_ptr< RigDef::Document::Module > m)
void ProcessHydros(Document::Module *)
void ExportDocComment(Document::Module *module, RigDef::Keyword keyword, ptrdiff_t vectorpos)
void ProcessSetSkeletonSettings(Document::Module *module)
void ProcessTurbojets(Document::Module *module)
void ProcessLockgroups(Document::Module *module)
void ProcessFlares2(Document::Module *module)
void ProcessShocks2(Document::Module *)
Serializer(RigDef::DocumentPtr rig_def)
void ProcessSoundsources(Document::Module *module)
void ProcessRotators(Document::Module *module)
void ProcessBeams(Document::Module *)
RigDef::DocumentPtr m_rig_def
BeamDefaults * m_current_beam_defaults
void ProcessManagedMaterialsAndOptions(Document::Module *module)
std::string m_dataline_indentstr
a node or a beam line for example
void ProcessSpeedLimiter(Document::Module *module)
void ProcessTorqueCurve(Document::Module *module)
void ProcessVideocamera(Document::Module *module)
void ProcessCruiseControl(Document::Module *module)
void ProcessRotators2(Document::Module *module)
void ProcessAxles(Document::Module *module)
void ProcessSlideNodes(Document::Module *module)
void ProcessExtCamera(Document::Module *module)
void ProcessEngine(Document::Module *module)
void ProcessTransferCase(Document::Module *module)
static const float DEFAULT_SPRING
static const float BEAM_DEFORM
static const float DEFAULT_DAMP
static const float BEAM_BREAK
const char * ROOT_MODULE_NAME
@ c_COMMAND_STYLE
trigger is set with commandstyle boundaries instead of shocksytle
@ s_CMD_NUM_SWITCH
switch that exchanges cmdshort/cmdshort for all triggers with the same commandnumbers,...
@ t_CONTINUOUS
this trigger sends values between 0 and 1
@ A_INV_TRIGGER_BLOCKER
Blocker that enable/disable other triggers, reversed activation method (inverted Blocker style,...
@ B_TRIGGER_BLOCKER
Blocker that enable/disable other triggers.
@ E_ENGINE_TRIGGER
this trigger is used to control an engine
@ x_START_DISABLED
this trigger is disabled on startup, default is enabled
@ b_KEY_BLOCKER
Set the CommandKeys that are set in a commandkeyblocker or trigger to blocked on startup,...
std::shared_ptr< Document > DocumentPtr
Node::Ref aditional_node
Node::Ref y_axis_node
Node::Ref reference_node
float max_inclination_angle
Node::Ref x_axis_node
Ogre::Vector3 offset
static const BitMask64_t SOURCE_TURBO
static const BitMask64_t SOURCE_SEQUENTIAL_SHIFT
static const BitMask64_t SOURCE_AIR_RUDDER
static const BitMask_t MODE_ROTATION_X
static const BitMask64_t SOURCE_ALTIMETER_1K
static const BitMask_t MODE_OFFSET_Y
static const BitMask64_t SOURCE_SHIFT_LEFT_RIGHT
static const BitMask_t MODE_NO_FLIP
static const BitMask64_t SOURCE_FLAP
static const BitMask64_t SOURCE_SPEEDO
static const BitMask64_t SOURCE_DIFFLOCK
static const BitMask64_t SOURCE_ALTIMETER_10K
static const BitMask64_t SOURCE_AIRSPEED
BitMask64_t source
static const BitMask_t MODE_AUTO_ANIMATE
static const BitMask64_t SOURCE_ROLL
static const BitMask64_t SOURCE_BOAT_THROTTLE
static const BitMask64_t SOURCE_CLUTCH
static const BitMask_t MODE_OFFSET_Z
static const BitMask64_t SOURCE_PITCH
static const BitMask64_t SOURCE_TACHO
static const BitMask64_t SOURCE_AILERON
static const BitMask_t MODE_ROTATION_Y
static const BitMask64_t SOURCE_ELEVATOR
static const BitMask64_t SOURCE_PERMANENT
static const BitMask_t MODE_EVENT_LOCK
Ogre::String event_name
static const BitMask64_t SOURCE_STEERING_WHEEL
static const BitMask64_t SOURCE_PARKING
static const BitMask64_t SOURCE_SHIFT_BACK_FORTH
static const BitMask64_t SOURCE_ACCEL
static const BitMask64_t SOURCE_AIR_BRAKE
static const BitMask64_t SOURCE_ANGLE_OF_ATTACK
static const BitMask64_t SOURCE_VERTICAL_VELOCITY
static const BitMask_t MODE_OFFSET_X
static const BitMask_t MODE_BOUNCE
static const BitMask64_t SOURCE_SHIFTERLIN
static const BitMask64_t SOURCE_ALTIMETER_100K
static const BitMask64_t SOURCE_BOAT_RUDDER
static const BitMask64_t SOURCE_BRAKES
static const BitMask64_t SOURCE_TORQUE
static const BitMask_t MODE_ROTATION_Z
static const BitMask64_t SOURCE_EVENT
static const BitMask64_t SOURCE_HEADING
Node::Ref nodes[2]
Ogre::String name
unsigned int forum_account_id
bool _has_forum_account
Ogre::String type
Ogre::String email
DifferentialTypeVec options
Order matters!
Node::Ref wheels[2][2]
Ogre::String material_name
RoR::WheelSide side
Ogre::String mesh_name
RoR::WheelBraking braking
unsigned int num_rays
std::shared_ptr< BeamDefaults > beam_defaults
std::shared_ptr< NodeDefaults > node_defaults
Node::Ref rigidity_node
RoR::WheelPropulsion propulsion
Node::Ref nodes[2]
Node::Ref reference_arm_node
Ogre::String beam_material_name
static const BitMask_t OPTION_r_ROPE
BitMask_t options
bool _has_extension_break_limit
std::shared_ptr< BeamDefaults > defaults
float extension_break_limit
static const BitMask_t OPTION_i_INVISIBLE
Node::Ref nodes[2]
static const BitMask_t OPTION_s_SUPPORT
float default_braking_force
float parking_brake_force
static const BitMask_t OPTION_r_BUOYANT_ONLY_DRAG
static const BitMask_t OPTION_p_10xTOUGHER
static const BitMask_t OPTION_s_BUOYANT_NO_DRAG
static const BitMask_t OPTION_F_10xTOUGHER_BUOYANT
static const BitMask_t OPTION_b_BUOYANT
static const BitMask_t OPTION_D_CONTACT_BUOYANT
static const BitMask_t OPTION_S_INVULNERABLE_BUOYANT
static const BitMask_t OPTION_c_CONTACT
static const BitMask_t OPTION_u_INVULNERABLE
std::vector< Node::Ref > nodes
Ogre::String description
Node::Ref nodes[2]
RoR::CommandkeyID_t extend_key
RoR::CommandkeyID_t contract_key
std::shared_ptr< BeamDefaults > beam_defaults
bool option_o_1press_center
float min_mass_Kg
minimum node mass in Kg
< Represents a comment (line starting with ';' or '//') that can be anywhere in the file.
std::vector< Node::Ref > fixes
std::vector< Wheel2 > wheels2
std::vector< Exhaust > exhausts
std::vector< Ropable > ropables
std::vector< Prop > props
std::vector< CollisionBox > collisionboxes
std::vector< InterAxle > interaxles
std::vector< Rotator2 > rotators2
std::vector< SoundSource2 > soundsources2
std::vector< Rotator > rotators
std::vector< SkeletonSettings > set_skeleton_settings
std::vector< Ogre::String > submesh_groundmodel
std::vector< Wing > wings
std::vector< CustomDashboardInput > customdashboardinputs
std::vector< GuiSettings > guisettings
std::vector< AntiLockBrakes > antilockbrakes
std::vector< DocComment > _comments
std::vector< Ogre::String > description
std::vector< MeshWheel2 > meshwheels2
std::vector< Turbojet > turbojets
std::vector< Particle > particles
std::vector< VideoCamera > videocameras
std::vector< Shock > shocks
std::vector< CruiseControl > cruisecontrol
std::vector< Shock2 > shocks2
std::vector< Tie > ties
std::vector< Hook > hooks
std::vector< Pistonprop > pistonprops
std::vector< TractionControl > tractioncontrol
std::vector< Author > author
std::vector< MeshWheel > meshwheels
std::vector< Animator > animators
std::vector< SoundSource > soundsources
std::vector< Cinecam > cinecam
std::vector< ManagedMaterial > managedmaterials
std::vector< SpeedLimiter > speedlimiter
std::vector< FlexBodyWheel > flexbodywheels
std::vector< TransferCase > transfercase
std::vector< Flexbody > flexbodies
std::vector< Globals > globals
std::vector< Lockgroup > lockgroups
std::vector< Node > nodes
std::vector< Rope > ropes
std::vector< Node::Ref > contacters
std::vector< Wheel > wheels
std::vector< Engoption > engoption
std::vector< Command2 > commands2
std::vector< TorqueCurve > torquecurve
std::vector< Trigger > triggers
std::vector< MaterialFlareBinding > materialflarebindings
std::vector< ExtCamera > extcamera
std::vector< Turboprop2 > turboprops2
std::vector< RailGroup > railgroups
std::vector< Fileinfo > fileinfo
std::vector< Engine > engine
std::vector< Axle > axles
std::vector< Shock3 > shocks3
std::vector< Hydro > hydros
std::vector< Screwprop > screwprops
std::vector< SlideNode > slidenodes
std::vector< Beam > beams
std::vector< Brakes > brakes
std::vector< Camera > cameras
std::vector< Help > help
std::vector< Flare2 > flares2
std::vector< Airbrake > airbrakes
std::vector< Guid > guid
std::vector< float > gear_ratios
float global_gear_ratio
float neutral_gear_ratio
float reverse_gear_ratio
float shift_time
Seconds.
float post_shift_time
Seconds.
float clutch_time
Seconds.
Node::Ref direction_node
Node::Ref reference_node
Ogre::String particle_name
RoR::ExtCameraMode mode
Ogre::String unique_id
RoR::FlareType type
Ogre::String material_name
Node::Ref node_axis_x
Node::Ref reference_node
Ogre::Vector3 offset
int control_number
Only 'u' type flares.
Node::Ref node_axis_y
Ogre::String mesh_name
Node::Ref y_axis_node
Ogre::Vector3 rotation
std::list< Animation > animations
Ogre::Vector3 offset
Node::Ref reference_node
Node::Ref x_axis_node
std::vector< Node::Ref > node_list
Node::Ref node
float option_max_force
bool flag_no_disable
bool flag_self_lock
float option_timer
float option_speed_coef
bool flag_auto_lock
float option_hook_range
float option_min_range_meters
static const BitMask_t OPTION_e_INPUT_ELEVATOR
float lenghtening_factor
static const BitMask_t OPTION_s_DISABLE_ON_HIGH_SPEED
BitMask_t options
static const BitMask_t OPTION_h_INPUT_InvELEVATOR_RUDDER
static const BitMask_t OPTION_g_INPUT_ELEVATOR_RUDDER
static const BitMask_t OPTION_y_INPUT_InvAILERON_RUDDER
Node::Ref nodes[2]
static const BitMask_t OPTION_j_INVISIBLE
static const BitMask_t OPTION_v_INPUT_InvAILERON_ELEVATOR
static const BitMask_t OPTION_a_INPUT_AILERON
static const BitMask_t OPTION_r_INPUT_RUDDER
static const BitMask_t OPTION_n_INPUT_NORMAL
static const BitMask_t OPTION_u_INPUT_AILERON_ELEVATOR
Inertia inertia
static const BitMask_t OPTION_x_INPUT_AILERON_RUDDER
std::shared_ptr< BeamDefaults > beam_defaults
Ogre::String start_function
float start_delay_factor
float stop_delay_factor
Ogre::String stop_function
DifferentialTypeVec options
Order matters!
std::vector< Node::Ref > nodes
static const char * TypeToStr(ManagedMaterialType type)
unsigned int options
Bit flags.
static const BitMask_t OPTION_c_NO_GROUND_CONTACT
static const BitMask_t OPTION_p_NO_PARTICLES
std::shared_ptr< DefaultMinimass > default_minimass
bool _has_load_weight_override
static const BitMask_t OPTION_f_NO_SPARKS
static const BitMask_t OPTION_b_EXTRA_BUOYANCY
BitMask_t options
static const BitMask_t OPTION_L_LOG
static const BitMask_t OPTION_x_EXHAUST_POINT
static const BitMask_t OPTION_e_TERRAIN_EDIT_POINT
std::shared_ptr< NodeDefaults > node_defaults
float load_weight_override
static const BitMask_t OPTION_h_HOOK_POINT
Ogre::Vector3 position
static const BitMask_t OPTION_m_NO_MOUSE_GRAB
static const BitMask_t OPTION_l_LOAD_WEIGHT
static const BitMask_t OPTION_y_EXHAUST_DIRECTION
Node::Ref emitter_node
Node::Ref reference_node
Ogre::String particle_system_name
Ogre::ColourValue color
Node::Ref reference_node
Node::Ref x_axis_node
DashboardSpecial special_prop_dashboard
Ogre::Vector3 offset
Ogre::String mesh_name
BeaconSpecial special_prop_beacon
Node::Ref y_axis_node
SpecialProp special
std::list< Animation > animations
Ogre::Vector3 rotation
std::vector< Node::Range > node_list
unsigned int id
std::shared_ptr< BeamDefaults > beam_defaults
Node::Ref end_node
Node::Ref root_node
Ogre::String description
unsigned int spin_left_key
Node::Ref base_plate_nodes[4]
Node::Ref axis_nodes[2]
Node::Ref rotating_plate_nodes[4]
unsigned int spin_right_key
BitMask_t options
Node::Ref nodes[2]
static const BitMask_t OPTION_i_INVISIBLE
float short_bound
Maximum contraction limit, in percentage ( 1.00 = 100% )
float progress_factor_damp_out
Progression factor dampout, 0 = disabled, 1...x as multipliers, example:maximum dampingrate == spring...
float damp_out
damping value applied when shock extending
float progress_factor_damp_in
Progression factor for dampin. 0 = disabled, 1...x as multipliers, example:maximum dampingrate == spr...
std::shared_ptr< BeamDefaults > beam_defaults
static const BitMask_t OPTION_m_METRIC
float spring_in
Spring value applied when the shock is compressing.
static const BitMask_t OPTION_s_SOFT_BUMP_BOUNDS
float precompression
Changes compression or extension of the suspension when the truck spawns. This can be used to "level"...
float progress_factor_spring_out
Progression factor springout, 0 = disabled, 1...x as multipliers, example:maximum springrate == sprin...
static const BitMask_t OPTION_M_ABSOLUTE_METRIC
float spring_out
spring value applied when shock extending
float long_bound
Maximum extension limit, in percentage ( 1.00 = 100% )
float damp_in
Damping value applied when the shock is compressing.
float progress_factor_spring_in
Progression factor for springin. A value of 0 disables this option. 1...x as multipliers,...
float damp_in_slow
Damping value applied when shock is commpressing slower than split in velocity.
float spring_in
Spring value applied when the shock is compressing.
float spring_out
Spring value applied when shock extending.
static const BitMask_t OPTION_M_ABSOLUTE_METRIC
float damp_in
Damping value applied when the shock is compressing.
float split_vel_in
Split velocity in (m/s) - threshold for slow / fast damping during compression.
BitMask_t options
float precompression
Changes compression or extension of the suspension when the truck spawns. This can be used to "level"...
Node::Ref nodes[2]
static const BitMask_t OPTION_i_INVISIBLE
static const BitMask_t OPTION_m_METRIC
std::shared_ptr< BeamDefaults > beam_defaults
float damp_out
Damping value applied when shock extending.
float long_bound
Maximum extension limit, in percentage ( 1.00 = 100% )
float short_bound
Maximum contraction limit, in percentage ( 1.00 = 100% )
float damp_out_slow
Damping value applied when shock is commpressing slower than split out velocity.
float damp_out_fast
Damping value applied when shock is commpressing faster than split out velocity.
float damp_in_fast
Damping value applied when shock is commpressing faster than split in velocity.
float split_vel_out
Split velocity in (m/s) - threshold for slow / fast damping during extension.
static const BitMask_t OPTION_L_ACTIVE_LEFT
std::shared_ptr< BeamDefaults > beam_defaults
float damping
The 'resistance to motion' of the shock. The best value is given by this equation: 2 * sqrt(suspended...
float spring_rate
The 'stiffness' of the shock. The higher the value, the less the shock will move for a given bump.
static const BitMask_t OPTION_m_METRIC
float precompression
Changes compression or extension of the suspension when the truck spawns. This can be used to "level"...
Node::Ref nodes[2]
float short_bound
Maximum contraction. The shortest length the shock can be, as a proportion of its original length....
float long_bound
Maximum extension. The longest length a shock can be, as a proportion of its original length....
static const BitMask_t OPTION_i_INVISIBLE
static const BitMask_t OPTION_R_ACTIVE_RIGHT
BitMask_t options
static const BitMask_t CONSTRAINT_ATTACH_ALL
static const BitMask_t CONSTRAINT_ATTACH_NONE
static const BitMask_t CONSTRAINT_ATTACH_FOREIGN
static const BitMask_t CONSTRAINT_ATTACH_SELF
BitMask_t constraint_flags
std::vector< Node::Range > rail_node_ranges
int mode
A special constant or cinecam index.
Ogre::String sound_script_name
Node::Ref root_node
float auto_shorten_rate
static const BitMask_t OPTION_i_INVISIBLE
static const BitMask_t OPTION_s_DISABLE_SELF_LOCK
BitMask_t options
float max_reach_length
std::vector< float > gear_ratios
static const BitMask_t OPTION_B_TRIGGER_BLOCKER
static const BitMask_t OPTION_s_CMD_NUM_SWITCH
static const BitMask_t OPTION_h_UNLOCKS_HOOK_GROUP
static const BitMask_t OPTION_i_INVISIBLE
static const BitMask_t OPTION_t_CONTINUOUS
static const BitMask_t OPTION_E_ENGINE_TRIGGER
static const BitMask_t OPTION_c_COMMAND_STYLE
static const BitMask_t OPTION_b_KEY_BLOCKER
float contraction_trigger_limit
static const BitMask_t OPTION_x_START_DISABLED
BitMask_t options
float expansion_trigger_limit
Node::Ref nodes[2]
static const BitMask_t OPTION_H_LOCKS_HOOK_GROUP
static const BitMask_t OPTION_A_INV_TRIGGER_BLOCKER
int shortbound_trigger_action
Node::Ref blade_tip_nodes[4]
Node::Ref reference_node
Ogre::String airfoil
RoR::VideoCamRole camera_role
Ogre::String material_name
unsigned int texture_width
Ogre::String camera_name
Node::Ref alt_orientation_node
Node::Ref alt_reference_node
unsigned int texture_height
Ogre::Vector3 rotation
Ogre::Vector3 offset
float tex_coords[8]
float min_deflection
float efficacy_coef
WingControlSurface control_surface
Ogre::String airfoil
float max_deflection
Node::Ref nodes[8]