38 #include <OgreException.h>
39 #include <OgreString.h>
40 #include <OgreStringVector.h>
41 #include <OgreStringConverter.h>
52 return (c ==
' ') || (c ==
'\t');
57 return IsWhitespace(c) || (c ==
':') || (c ==
'|') || (c ==
',');
62 if (s1.size() != s2.size()) {
return false; }
63 for (
size_t i = 0; i < s1.size(); ++i)
65 if (tolower(s1[i]) != tolower(s2[i])) {
return false; }
73 m_ror_default_inertia = std::shared_ptr<Inertia>(
new Inertia);
74 m_ror_node_defaults = std::shared_ptr<NodeDefaults>(
new NodeDefaults);
77 void Parser::ProcessCurrentLine()
80 if (m_definition->name ==
"" && m_current_line !=
"")
82 m_definition->name = m_current_line;
87 if (m_current_block != Keyword::COMMENT &&
88 m_current_block != Keyword::DESCRIPTION)
90 this->TokenizeCurrentLine();
96 char c = tolower(m_current_line[0]);
97 if (c >=
'a' && c <=
'z')
99 keyword = Parser::IdentifyKeyword(m_current_line);
105 case Keyword::INVALID:
109 case Keyword::DISABLEDEFAULTSOUNDS:
110 case Keyword::ENABLE_ADVANCED_DEFORMATION:
111 case Keyword::FORWARDCOMMANDS:
112 case Keyword::HIDEINCHOOSER:
113 case Keyword::IMPORTCOMMANDS:
114 case Keyword::LOCKGROUP_DEFAULT_NOLOCK:
115 case Keyword::RESCUER:
116 case Keyword::ROLLON:
117 case Keyword::SLIDENODE_CONNECT_INSTANTLY:
118 this->ProcessGlobalDirective(
keyword);
120 case Keyword::END_SECTION:
121 this->ProcessChangeModuleLine(
keyword);
125 case Keyword::ADD_ANIMATION:
126 this->ParseDirectiveAddAnimation();
128 case Keyword::ANTILOCKBRAKES:
129 this->ParseAntiLockBrakes();
131 case Keyword::AUTHOR:
134 case Keyword::BACKMESH:
135 this->ParseDirectiveBackmesh();
137 case Keyword::CRUISECONTROL:
138 this->ParseCruiseControl();
140 case Keyword::DEFAULT_SKIN:
141 this->ParseDirectiveDefaultSkin();
143 case Keyword::DETACHER_GROUP:
144 this->ParseDirectiveDetacherGroup();
146 case Keyword::EXTCAMERA:
147 this->ParseExtCamera();
149 case Keyword::FILEFORMATVERSION:
150 this->ParseFileFormatVersion();
152 case Keyword::FILEINFO:
153 this->ParseFileinfo();
155 case Keyword::FLEXBODY_CAMERA_MODE:
156 this->ParseDirectiveFlexbodyCameraMode();
158 case Keyword::FORSET:
159 this->ParseDirectiveForset();
161 case Keyword::FORVERT:
162 this->ParseDirectiveForvert();
167 case Keyword::PROP_CAMERA_MODE:
168 this->ParseDirectivePropCameraMode();
170 case Keyword::SECTION:
171 this->ParseDirectiveSection();
173 case Keyword::SET_BEAM_DEFAULTS:
174 this->ParseDirectiveSetBeamDefaults();
176 case Keyword::SET_BEAM_DEFAULTS_SCALE:
177 this->ParseDirectiveSetBeamDefaultsScale();
179 case Keyword::SET_COLLISION_RANGE:
180 this->ParseSetCollisionRange();
182 case Keyword::SET_DEFAULT_MINIMASS:
183 this->ParseDirectiveSetDefaultMinimass();
185 case Keyword::SET_INERTIA_DEFAULTS:
186 this->ParseDirectiveSetInertiaDefaults();
188 case Keyword::SET_MANAGEDMATERIALS_OPTIONS:
189 this->ParseDirectiveSetManagedMaterialsOptions();
191 case Keyword::SET_NODE_DEFAULTS:
192 this->ParseDirectiveSetNodeDefaults();
194 case Keyword::SET_SKELETON_SETTINGS:
195 this->ParseSetSkeletonSettings();
197 case Keyword::SPEEDLIMITER:
198 this->ParseSpeedLimiter();
200 case Keyword::SUBMESH:
201 this->ParseDirectiveSubmesh();
203 case Keyword::SUBMESH_GROUNDMODEL:
204 this->ParseSubmeshGroundModel();
206 case Keyword::TRACTIONCONTROL:
207 this->ParseTractionControl();
211 case Keyword::END_COMMENT:
212 case Keyword::END_DESCRIPTION:
214 this->BeginBlock(Keyword::INVALID);
218 case Keyword::ENVMAP:
219 case Keyword::HOOKGROUP:
220 case Keyword::NODECOLLISION:
221 case Keyword::RIGIDIFIERS:
231 if ((
keyword == Keyword::NODES ||
keyword == Keyword::NODES2) && m_current_module->_hint_nodes12_start_linenumber == -1)
233 m_current_module->_hint_nodes12_start_linenumber = (int)m_current_line_number;
235 else if (
keyword == Keyword::BEAMS && m_current_module->_hint_beams_start_linenumber == -1)
237 m_current_module->_hint_beams_start_linenumber = (int)m_current_line_number;
239 else if (m_current_module->_hint_nodes12_end_linenumber == -1)
241 m_current_module->_hint_nodes12_start_linenumber = (int)m_current_line_number - 1;
243 else if (m_current_module->_hint_beams_end_linenumber == -1)
245 m_current_module->_hint_beams_start_linenumber = (int)m_current_line_number - 1;
249 m_log_keyword = m_current_block;
250 switch (m_current_block)
252 case Keyword::AIRBRAKES: this->ParseAirbrakes();
return;
253 case Keyword::ANIMATORS: this->ParseAnimator();
return;
254 case Keyword::ASSETPACKS: this->ParseAssetpacks();
return;
255 case Keyword::AXLES: this->ParseAxles();
return;
256 case Keyword::BEAMS: this->ParseBeams();
return;
257 case Keyword::BRAKES: this->ParseBrakes();
return;
258 case Keyword::CAMERAS: this->ParseCameras();
return;
259 case Keyword::CAB: this->ParseCab();
return;
260 case Keyword::CAMERARAIL: this->ParseCameraRails();
return;
261 case Keyword::CINECAM: this->ParseCinecam();
return;
262 case Keyword::COMMANDS:
263 case Keyword::COMMANDS2: this->ParseCommandsUnified();
return;
264 case Keyword::COLLISIONBOXES: this->ParseCollisionBox();
return;
265 case Keyword::CONTACTERS: this->ParseContacter();
return;
266 case Keyword::CUSTOMDASHBOARDINPUTS:this->ParseCustomDashboardInputs();
return;
267 case Keyword::DESCRIPTION: this->ParseDescription();
return;
268 case Keyword::ENGINE: this->ParseEngine();
return;
269 case Keyword::ENGOPTION: this->ParseEngoption();
return;
270 case Keyword::ENGTURBO: this->ParseEngturbo();
return;
271 case Keyword::EXHAUSTS: this->ParseExhaust();
return;
272 case Keyword::FIXES: this->ParseFixes();
return;
273 case Keyword::FLARES:
274 case Keyword::FLARES2: this->ParseFlaresUnified();
return;
275 case Keyword::FLARES3: this->ParseFlares3();
return;
276 case Keyword::FLAREGROUPS_NO_IMPORT:this->ParseFlaregroupsNoImport();
return;
277 case Keyword::FLEXBODIES: this->ParseFlexbody();
return;
278 case Keyword::FLEXBODYWHEELS: this->ParseFlexBodyWheel();
return;
279 case Keyword::FUSEDRAG: this->ParseFusedrag();
return;
280 case Keyword::GLOBALS: this->ParseGlobals();
return;
281 case Keyword::GUISETTINGS: this->ParseGuiSettings();
return;
282 case Keyword::HELP: this->ParseHelp();
return;
283 case Keyword::HOOKS: this->ParseHook();
return;
284 case Keyword::HYDROS: this->ParseHydros();
return;
285 case Keyword::INTERAXLES: this->ParseInterAxles();
return;
286 case Keyword::LOCKGROUPS: this->ParseLockgroups();
return;
287 case Keyword::MANAGEDMATERIALS: this->ParseManagedMaterials();
return;
288 case Keyword::MATERIALFLAREBINDINGS:this->ParseMaterialFlareBindings();
return;
289 case Keyword::MESHWHEELS: this->ParseMeshWheel();
return;
290 case Keyword::MESHWHEELS2: this->ParseMeshWheel2();
return;
291 case Keyword::MINIMASS: this->ParseMinimass();
return;
293 case Keyword::NODES2: this->ParseNodesUnified();
return;
294 case Keyword::PARTICLES: this->ParseParticles();
return;
295 case Keyword::PISTONPROPS: this->ParsePistonprops();
return;
296 case Keyword::PROPS: this->ParseProps();
return;
297 case Keyword::RAILGROUPS: this->ParseRailGroups();
return;
298 case Keyword::ROPABLES: this->ParseRopables();
return;
299 case Keyword::ROPES: this->ParseRopes();
return;
300 case Keyword::ROTATORS:
301 case Keyword::ROTATORS2: this->ParseRotatorsUnified();
return;
302 case Keyword::SCREWPROPS: this->ParseScrewprops();
return;
303 case Keyword::SCRIPTS: this->ParseScripts();
return;
304 case Keyword::SHOCKS: this->ParseShock();
return;
305 case Keyword::SHOCKS2: this->ParseShock2();
return;
306 case Keyword::SHOCKS3: this->ParseShock3();
return;
307 case Keyword::SLIDENODES: this->ParseSlidenodes();
return;
308 case Keyword::SOUNDSOURCES: this->ParseSoundsources();
return;
309 case Keyword::SOUNDSOURCES2: this->ParseSoundsources2();
return;
310 case Keyword::TEXCOORDS: this->ParseTexcoords();
return;
311 case Keyword::TIES: this->ParseTies();
return;
312 case Keyword::TORQUECURVE: this->ParseTorqueCurve();
return;
313 case Keyword::TRANSFERCASE: this->ParseTransferCase();
return;
314 case Keyword::TRIGGERS: this->ParseTriggers();
return;
315 case Keyword::TURBOJETS: this->ParseTurbojets();
return;
316 case Keyword::TURBOPROPS:
317 case Keyword::TURBOPROPS2: this->ParseTurbopropsUnified();
return;
318 case Keyword::VIDEOCAMERA: this->ParseVideoCamera();
return;
319 case Keyword::WHEELDETACHERS: this->ParseWheelDetachers();
return;
320 case Keyword::WHEELS: this->ParseWheel();
return;
321 case Keyword::WHEELS2: this->ParseWheel2();
return;
322 case Keyword::WINGS: this->ParseWing();
return;
327 bool Parser::CheckNumArguments(
int min_args)
329 if (min_args > m_num_args)
332 fmt::format(
"Not enough arguments (got {}, {} needed), skipping line", m_num_args, min_args));
342 void Parser::ParseWing()
344 if (!this->CheckNumArguments(16)) {
return; }
348 for (
int i = 0; i < 8; i++) { wing.
nodes[i] = this->GetArgNodeRef (i); }
349 for (
int i = 8; i < 16; i++) { wing.
tex_coords[i-8] = this->GetArgFloat (i); }
351 if (m_num_args > 16) { wing.
control_surface = this->GetArgWingSurface (16); }
352 if (m_num_args > 17) { wing.
chord_point = this->GetArgFloat (17); }
353 if (m_num_args > 18) { wing.
min_deflection = this->GetArgFloat (18); }
354 if (m_num_args > 19) { wing.
max_deflection = this->GetArgFloat (19); }
355 if (m_num_args > 20) { wing.
airfoil = this->GetArgStr (20); }
356 if (m_num_args > 21) { wing.
efficacy_coef = this->GetArgFloat (21); }
358 m_current_module->wings.push_back(wing);
362 void Parser::ParseSetCollisionRange()
364 if (! this->CheckNumArguments(2)) {
return; }
369 m_current_module->set_collision_range.push_back(cr);
373 void Parser::ParseWheel2()
375 if (!this->CheckNumArguments(17)) {
return; }
383 wheel_2.
width = this->GetArgFloat ( 2);
384 wheel_2.
num_rays = this->GetArgInt ( 3);
385 wheel_2.
nodes[0] = this->GetArgNodeRef ( 4);
386 wheel_2.
nodes[1] = this->GetArgNodeRef ( 5);
388 wheel_2.
braking = this->GetArgBraking ( 7);
389 wheel_2.
propulsion = this->GetArgPropulsion ( 8);
391 wheel_2.
mass = this->GetArgFloat (10);
399 if (m_sequential_importer.IsEnabled())
404 m_current_module->wheels2.push_back(wheel_2);
408 void Parser::ParseWheel()
410 if (! this->CheckNumArguments(14)) {
return; }
416 wheel.
radius = this->GetArgFloat ( 0);
417 wheel.
width = this->GetArgFloat ( 1);
418 wheel.
num_rays = this->GetArgInt ( 2);
419 wheel.
nodes[0] = this->GetArgNodeRef ( 3);
420 wheel.
nodes[1] = this->GetArgNodeRef ( 4);
422 wheel.
braking = this->GetArgBraking ( 6);
423 wheel.
propulsion = this->GetArgPropulsion ( 7);
425 wheel.
mass = this->GetArgFloat ( 9);
427 wheel.
damping = this->GetArgFloat (11);
431 if (m_sequential_importer.IsEnabled())
436 m_current_module->wheels.push_back(wheel);
440 void Parser::ParseWheelDetachers()
442 if (! this->CheckNumArguments(2)) {
return; }
446 wheeldetacher.
wheel_id = this->GetArgInt(0);
449 m_current_module->wheeldetachers.push_back(wheeldetacher);
453 void Parser::ParseTractionControl()
455 Ogre::StringVector tokens = Ogre::StringUtil::split(m_current_line + 15,
",");
456 m_num_args = (int)tokens.size();
457 if (! this->CheckNumArguments(2)) {
return; }
461 tc.
wheel_slip = this->ParseArgFloat(tokens[1].c_str());
462 if (tokens.size() > 2) { tc.
fade_speed = this->ParseArgFloat(tokens[2].c_str()); }
463 if (tokens.size() > 3) { tc.
pulse_per_sec = this->ParseArgFloat(tokens[3].c_str()); }
465 for (
unsigned int i=4; i<tokens.size(); i++)
467 Ogre::StringVector args2 = Ogre::StringUtil::split(tokens[i],
":");
468 Ogre::StringUtil::trim(args2[0]);
469 Ogre::StringUtil::toLowerCase(args2[0]);
471 if (args2[0] ==
"mode" && args2.size() == 2)
473 Ogre::StringVector attrs = Ogre::StringUtil::split(args2[1],
"&");
474 auto itor = attrs.begin();
475 auto endi = attrs.end();
476 for (; itor != endi; ++itor)
478 std::string attr = *itor;
479 Ogre::StringUtil::trim(attr);
480 Ogre::StringUtil::toLowerCase(attr);
482 else if (strncmp(attr.c_str(),
"notoggle", 8) == 0) { tc.
attr_no_toggle =
true; }
483 else if (strncmp(attr.c_str(),
"on", 2) == 0) { tc.
attr_is_on =
true; }
484 else if (strncmp(attr.c_str(),
"off", 3) == 0) { tc.
attr_is_on =
false; }
496 m_current_module->tractioncontrol.push_back(tc);
500 void Parser::ParseTransferCase()
502 if (! this->CheckNumArguments(2)) {
return; }
506 tc.
a1 = this->GetArgInt(0) - 1;
507 tc.
a2 = this->GetArgInt(1) - 1;
508 if (m_num_args > 2) { tc.
has_2wd = this->GetArgInt(2); }
509 if (m_num_args > 3) { tc.
has_2wd_lo = this->GetArgInt(3); }
510 for (
int i = 4; i < m_num_args; i++) { tc.
gear_ratios.push_back(this->GetArgFloat(i)); }
512 m_current_module->transfercase.push_back(tc);
516 void Parser::ParseSubmeshGroundModel()
518 if (!this->CheckNumArguments(2)) {
return; }
520 m_current_module->submesh_groundmodel.push_back(this->GetArgStr(1));
524 void Parser::ParseSpeedLimiter()
526 if (! this->CheckNumArguments(2)) {
return; }
532 m_current_module->speedlimiter.push_back(sl);
536 void Parser::ParseSetSkeletonSettings()
538 if (! this->CheckNumArguments(2)) {
return; }
540 if (m_current_module->set_skeleton_settings.size() == 0)
554 void Parser::ParseDirectiveSetNodeDefaults()
556 if (!this->CheckNumArguments(2)) {
return; }
558 float load_weight = this->GetArgFloat(1);
559 float friction = (m_num_args > 2) ? this->GetArgFloat(2) : -1;
560 float volume = (m_num_args > 3) ? this->GetArgFloat(3) : -1;
561 float surface = (m_num_args > 4) ? this->GetArgFloat(4) : -1;
563 m_user_node_defaults = std::shared_ptr<NodeDefaults>(
new NodeDefaults(*m_user_node_defaults) );
565 m_user_node_defaults->load_weight = (load_weight < 0) ? m_ror_node_defaults->load_weight : load_weight;
566 m_user_node_defaults->friction = (friction < 0) ? m_ror_node_defaults->friction : friction;
567 m_user_node_defaults->volume = (volume < 0) ? m_ror_node_defaults->volume : volume;
568 m_user_node_defaults->surface = (surface < 0) ? m_ror_node_defaults->surface : surface;
570 if (m_num_args > 5) m_user_node_defaults->options = this->GetArgNodeOptions(5);
573 void Parser::ParseDirectiveSetManagedMaterialsOptions()
575 if (! this->CheckNumArguments(2)) {
return; }
578 m_current_managed_material_options.double_sided = (this->GetArgChar(1) !=
'0');
581 void Parser::ParseDirectiveSetBeamDefaultsScale()
583 if (! this->CheckNumArguments(5)) {
return; }
592 m_user_beam_defaults = std::shared_ptr<BeamDefaults>(b);
595 void Parser::ParseDirectiveSetBeamDefaults()
597 if (! this->CheckNumArguments(2)) {
return; }
626 m_user_beam_defaults = std::shared_ptr<BeamDefaults>(
new BeamDefaults(d) );
630 void Parser::ParseDirectivePropCameraMode()
632 if (! this->CheckNumArguments(2)) {
return; }
634 if (m_current_module->props.size() > 0)
636 m_current_module->props[m_current_module->props.size() - 1].camera_settings.mode = this->GetArgInt(1);
644 void Parser::ParseDirectiveSubmesh()
646 this->BeginBlock(Keyword::INVALID);
647 m_current_submesh = std::shared_ptr<Submesh>(
new Submesh() );
650 void Parser::ParseDirectiveBackmesh()
652 if (m_current_submesh)
654 m_current_submesh->backmesh =
true;
666 case Keyword::DISABLEDEFAULTSOUNDS: m_definition->disable_default_sounds =
true;
return;
667 case Keyword::ENABLE_ADVANCED_DEFORMATION: m_definition->enable_advanced_deformation =
true;
return;
668 case Keyword::FORWARDCOMMANDS: m_definition->forward_commands =
true;
return;
669 case Keyword::IMPORTCOMMANDS: m_definition->import_commands =
true;
return;
670 case Keyword::HIDEINCHOOSER: m_definition->hide_in_chooser =
true;
return;
671 case Keyword::LOCKGROUP_DEFAULT_NOLOCK: m_definition->lockgroup_default_nolock =
true;
return;
672 case Keyword::RESCUER: m_definition->rescuer =
true;
return;
673 case Keyword::ROLLON: m_definition->rollon =
true;
return;
674 case Keyword::SLIDENODE_CONNECT_INSTANTLY: m_definition->slide_nodes_connect_instantly =
true;
return;
686 mesh_wheel.
rim_radius = this->GetArgFloat ( 1);
687 mesh_wheel.
width = this->GetArgFloat ( 2);
688 mesh_wheel.
num_rays = this->GetArgInt ( 3);
689 mesh_wheel.
nodes[0] = this->GetArgNodeRef ( 4);
690 mesh_wheel.
nodes[1] = this->GetArgNodeRef ( 5);
692 mesh_wheel.
braking = this->GetArgBraking ( 7);
693 mesh_wheel.
propulsion = this->GetArgPropulsion ( 8);
695 mesh_wheel.
mass = this->GetArgFloat (10);
696 mesh_wheel.
spring = this->GetArgFloat (11);
697 mesh_wheel.
damping = this->GetArgFloat (12);
698 mesh_wheel.
side = this->GetArgWheelSide (13);
699 mesh_wheel.
mesh_name = this->GetArgStr (14);
703 void Parser::ParseMeshWheel()
705 if (! this->CheckNumArguments(16)) {
return; }
708 this->_ParseBaseMeshWheel(mesh_wheel);
710 if (m_sequential_importer.IsEnabled())
715 m_current_module->meshwheels.push_back(mesh_wheel);
719 void Parser::ParseMeshWheel2()
721 if (! this->CheckNumArguments(16)) {
return; }
724 this->_ParseBaseMeshWheel(mesh_wheel);
726 if (m_sequential_importer.IsEnabled())
731 m_current_module->meshwheels2.push_back(mesh_wheel);
735 void Parser::ParseHook()
737 if (! this->CheckNumArguments(1)) {
return; }
740 hook.
node = this->GetArgNodeRef(0);
743 while (i < m_num_args)
745 std::string attr = this->GetArgStr(i);
746 Ogre::StringUtil::trim(attr);
747 const bool has_value = (i < (m_num_args - 1));
750 if (has_value && (attr ==
"hookrange") ) { hook.
option_hook_range = this->GetArgFloat(++i); }
751 else if (has_value && (attr ==
"speedcoef") ) { hook.
option_speed_coef = this->GetArgFloat(++i); }
752 else if (has_value && (attr ==
"maxforce") ) { hook.
option_max_force = this->GetArgFloat(++i); }
753 else if (has_value && (attr ==
"timer") ) { hook.
option_timer = this->GetArgFloat(++i); }
754 else if (has_value && (attr ==
"hookgroup" || attr ==
"hgroup") ) { hook.
option_hookgroup = this->GetArgInt (++i); }
755 else if (has_value && (attr ==
"lockgroup" || attr ==
"lgroup") ) { hook.
option_lockgroup = this->GetArgInt (++i); }
756 else if (has_value && (attr ==
"shortlimit" || attr ==
"short_limit")) { hook.
option_min_range_meters = this->GetArgFloat(++i); }
758 else if ((attr ==
"selflock") ||(attr ==
"self-lock") ||(attr ==
"self_lock") ) { hook.
flag_self_lock =
true; }
759 else if ((attr ==
"autolock") ||(attr ==
"auto-lock") ||(attr ==
"auto_lock") ) { hook.
flag_auto_lock =
true; }
760 else if ((attr ==
"nodisable")||(attr ==
"no-disable")||(attr ==
"no_disable")) { hook.
flag_no_disable =
true; }
761 else if ((attr ==
"norope") ||(attr ==
"no-rope") ||(attr ==
"no_rope") ) { hook.
flag_no_rope =
true; }
762 else if ((attr ==
"visible") ||(attr ==
"vis") ) { hook.
flag_visible =
true; }
770 m_current_module->hooks.push_back(hook);
774 void Parser::ParseHelp()
778 m_current_module->help.push_back(h);
781 void Parser::ParseGuiSettings()
783 if (! this->CheckNumArguments(2)) {
return; }
786 gs.
key = this->GetArgStr(0);
787 gs.
value = this->GetArgStr(1);
789 m_current_module->guisettings.push_back(gs);
793 void Parser::ParseGuid()
795 if (! this->CheckNumArguments(2)) {
return; }
798 g.
guid = this->GetArgStr(1);
800 m_current_module->guid.push_back(g);
804 void Parser::ParseGlobals()
806 if (! this->CheckNumArguments(2)) {
return; }
809 globals.
dry_mass = this->GetArgFloat(0);
812 if (m_num_args > 2) { globals.
material_name = this->GetArgStr(2); }
814 m_current_module->globals.push_back(globals);
818 void Parser::ParseFusedrag()
820 if (! this->CheckNumArguments(3)) {
return; }
824 fusedrag.
rear_node = this->GetArgNodeRef(1);
826 if (this->GetArgStr(2) ==
"autocalc")
832 if (m_num_args > 4) { fusedrag.
airfoil_name = this->GetArgStr (4); }
839 if (m_num_args > 3) { fusedrag.
airfoil_name = this->GetArgStr(3); }
842 m_current_module->fusedrag.push_back(fusedrag);
846 void Parser::ParseDirectiveFlexbodyCameraMode()
848 if (! this->CheckNumArguments(2)) {
return; }
850 if (m_current_module->flexbodies.size() > 0)
852 m_current_module->flexbodies[m_current_module->flexbodies.size() - 1].camera_settings.mode = this->GetArgInt(1);
860 void Parser::ParseCab()
862 if (! this->CheckNumArguments(3)) {
return; }
864 if (!m_current_submesh)
871 cab.
nodes[0] = this->GetArgNodeRef(0);
872 cab.
nodes[1] = this->GetArgNodeRef(1);
873 cab.
nodes[2] = this->GetArgNodeRef(2);
874 if (m_num_args > 3) cab.
options = this->GetArgCabOptions(3);
876 m_current_submesh->cab_triangles.push_back(cab);
880 void Parser::ParseTexcoords()
882 if (! this->CheckNumArguments(3)) {
return; }
884 if (!m_current_submesh)
891 texcoord.
node = this->GetArgNodeRef(0);
892 texcoord.
u = this->GetArgFloat (1);
893 texcoord.
v = this->GetArgFloat (2);
895 m_current_submesh->texcoords.push_back(texcoord);
899 void Parser::ParseFlexbody()
901 if (! this->CheckNumArguments(10)) {
return; }
907 flexbody.
offset.x = this->GetArgFloat (3);
908 flexbody.
offset.y = this->GetArgFloat (4);
909 flexbody.
offset.z = this->GetArgFloat (5);
910 flexbody.
rotation.x = this->GetArgFloat (6);
911 flexbody.
rotation.y = this->GetArgFloat (7);
912 flexbody.
rotation.z = this->GetArgFloat (8);
913 flexbody.
mesh_name = this->GetArgStr (9);
915 m_current_module->flexbodies.push_back(flexbody);
919 void Parser::ParseDirectiveForset()
921 if (m_current_module->flexbodies.size() == 0)
927 Parser::ProcessForsetLine(m_current_module->flexbodies.back(), m_current_line, m_current_line_number);
930 void Parser::ParseDirectiveForvert()
932 if (m_current_module->flexbodies.size() == 0)
938 if (!this->CheckNumArguments(4)) {
return; }
942 forvert.
node_ref = this->GetArgNodeRef(1);
943 forvert.
node_x = this->GetArgNodeRef(2);
944 forvert.
node_y = this->GetArgNodeRef(3);
948 const char* input_pos = std::strstr(m_current_line,
"verts:");
955 std::string input = input_pos;
956 std::regex pattern(R
"((\d+)\s*-\s*(\d+)|(\d+))");
959 std::string::const_iterator searchStart(input.cbegin());
960 while (std::regex_search(searchStart, input.cend(), matches, pattern))
962 if (matches[1].matched && matches[2].matched)
965 int start = std::stoi(matches[1].str());
966 int end = std::stoi(matches[2].str());
967 for (
int i = start; i <= end; ++i)
970 m_current_module->flexbodies.back().forvert.push_back(forvert);
973 else if (matches[3].matched)
976 forvert.
vert_index = std::stoi(matches[3].str());
977 m_current_module->flexbodies.back().forvert.push_back(forvert);
979 searchStart = matches.suffix().first;
983 void Parser::ProcessForsetLine(
RigDef::Flexbody& def,
const std::string& _line,
int line_number )
993 std::string line = _line;
994 char* pos = &line[0] + 6;
995 while (*pos ==
' ' || *pos ==
':' || *pos ==
',') { pos++; }
1002 while (*end !=
'-' && *end !=
',' && *end != 0) end++;
1005 val1 = strtoul(pos, 0, 10);
1010 while (*end !=
',' && *end != 0) end++;
1013 val2 = strtoul(pos, 0, 10);
1017 Node::Ref(std::to_string(val1), val1, Node::Ref::IMPORT_STATE_IS_VALID, line_number),
1018 Node::Ref(std::to_string(val2), val2, Node::Ref::IMPORT_STATE_IS_VALID, line_number)));
1030 void Parser::ParseFlaresUnified()
1032 const bool is_flares2 = (m_current_block == Keyword::FLARES2);
1033 if (! this->CheckNumArguments(is_flares2 ? 6 : 5)) {
return; }
1040 flare2.
offset.x = this->GetArgFloat (pos++);
1041 flare2.
offset.y = this->GetArgFloat (pos++);
1043 if (m_current_block == Keyword::FLARES2)
1045 flare2.
offset.z = this->GetArgFloat(pos++);
1048 if (m_num_args > pos) { flare2.
type = this->GetArgFlareType(pos++); }
1050 if (m_num_args > pos)
1052 switch (flare2.
type)
1062 if (m_num_args > pos) { flare2.
size = this->GetArgFloat (pos++); }
1063 if (m_num_args > pos) { flare2.
material_name = this->GetArgStr (pos++); }
1065 m_current_module->flares2.push_back(flare2);
1069 void Parser::ParseFlares3()
1071 const bool is_flares2 = (m_current_block == Keyword::FLARES2);
1072 if (! this->CheckNumArguments(is_flares2 ? 6 : 5)) {
return; }
1080 flare3.
offset.x = this->GetArgFloat(3);
1081 flare3.
offset.y = this->GetArgFloat(4);
1082 flare3.
offset.z = this->GetArgFloat(5);
1083 if (m_num_args > 6) { flare3.
type = this->GetArgFlareType(6); }
1087 switch (flare3.
type)
1096 if (m_num_args > 9) { flare3.
size = this->GetArgFloat (9); }
1097 if (m_num_args > 10) { flare3.
material_name = this->GetArgStr (10); }
1099 m_current_module->flares3.push_back(flare3);
1103 void Parser::ParseFixes()
1105 m_current_module->fixes.push_back(this->GetArgNodeRef(0));
1108 void Parser::ParseExtCamera()
1110 if (! this->CheckNumArguments(2)) {
return; }
1113 extcam.
mode = this->GetArgExtCameraMode(1);
1114 if (m_num_args > 2) { extcam.
node = this->GetArgNodeRef(2); }
1116 m_current_module->extcamera.push_back(extcam);
1120 void Parser::ParseExhaust()
1122 if (! this->CheckNumArguments(2)) {
return; }
1129 if (m_num_args > 3) { exhaust.
particle_name = this->GetArgStr(3); }
1131 m_current_module->exhausts.push_back(exhaust);
1135 void Parser::ParseFileFormatVersion()
1137 if (! this->CheckNumArguments(2)) {
return; }
1140 ffv.
version = this->GetArgInt(1);
1142 m_current_module->fileformatversion.push_back(ffv);
1143 m_current_block = Keyword::INVALID;
1146 void Parser::ParseDirectiveDefaultSkin()
1148 if (!this->CheckNumArguments(2)) {
return; }
1154 m_current_module->default_skin.push_back(data);
1158 void Parser::ParseDirectiveDetacherGroup()
1160 if (! this->CheckNumArguments(2)) {
return; }
1162 if (this->GetArgStr(1) ==
"end")
1164 m_current_detacher_group = 0;
1168 m_current_detacher_group = this->GetArgInt(1);
1172 void Parser::ParseCruiseControl()
1174 if (! this->CheckNumArguments(3)) {
return; }
1177 cruise_control.
min_speed = this->GetArgFloat(1);
1178 cruise_control.
autobrake = this->GetArgInt(2);
1180 m_current_module->cruisecontrol.push_back(cruise_control);
1184 void Parser::ParseDescription()
1186 m_current_module->description.push_back(m_current_line);
1189 void Parser::ParseDirectiveAddAnimation()
1191 Ogre::StringVector tokens = Ogre::StringUtil::split(m_current_line + 14,
",");
1192 m_num_args = (int)tokens.size();
1193 if (! this->CheckNumArguments(4)) {
return; }
1195 if (m_current_module->props.size() == 0)
1202 animation.
ratio = this->ParseArgFloat(tokens[0].c_str());
1203 animation.
lower_limit = this->ParseArgFloat(tokens[1].c_str());
1204 animation.
upper_limit = this->ParseArgFloat(tokens[2].c_str());
1206 for (
auto itor = tokens.begin() + 3; itor != tokens.end(); ++itor)
1208 Ogre::StringVector entry = Ogre::StringUtil::split(*itor,
":");
1209 Ogre::StringUtil::trim(entry[0]);
1210 if (entry.size() > 1) Ogre::StringUtil::trim(entry[1]);
1212 const int WARN_LEN = 500;
1213 char warn_msg[WARN_LEN] =
"";
1215 if (entry.size() == 1)
1217 if (entry[0] ==
"autoanimate") { animation.
mode |= Animation::MODE_AUTO_ANIMATE; }
1218 else if (entry[0] ==
"noflip") { animation.
mode |= Animation::MODE_NO_FLIP; }
1219 else if (entry[0] ==
"bounce") { animation.
mode |= Animation::MODE_BOUNCE; }
1220 else if (entry[0] ==
"eventlock") { animation.
mode |= Animation::MODE_EVENT_LOCK; }
1222 else { snprintf(warn_msg, WARN_LEN,
"Invalid keyword: %s", entry[0].c_str()); }
1224 else if (entry.size() == 2 && (entry[0] ==
"mode" || entry[0] ==
"event" || entry[0] ==
"source" || entry[0] ==
"link"))
1226 Ogre::StringVector values = Ogre::StringUtil::split(entry[1],
"|");
1227 if (entry[0] ==
"mode")
1229 for (
auto itor = values.begin(); itor != values.end(); ++itor)
1231 std::string value = *itor;
1232 Ogre::StringUtil::trim(value);
1234 if (value ==
"x-rotation") { animation.
mode |= Animation::MODE_ROTATION_X; }
1235 else if (value ==
"y-rotation") { animation.
mode |= Animation::MODE_ROTATION_Y; }
1236 else if (value ==
"z-rotation") { animation.
mode |= Animation::MODE_ROTATION_Z; }
1237 else if (value ==
"x-offset" ) { animation.
mode |= Animation::MODE_OFFSET_X; }
1238 else if (value ==
"y-offset" ) { animation.
mode |= Animation::MODE_OFFSET_Y; }
1239 else if (value ==
"z-offset" ) { animation.
mode |= Animation::MODE_OFFSET_Z; }
1241 else { snprintf(warn_msg, WARN_LEN,
"Invalid 'mode': %s, ignoring...", entry[1].c_str()); }
1244 else if (entry[0] ==
"event")
1247 Ogre::StringUtil::trim(animation.
event_name);
1248 Ogre::StringUtil::toUpperCase(animation.
event_name);
1250 else if (entry[0] ==
"link")
1255 else if (entry[0] ==
"source")
1257 for (
auto itor = values.begin(); itor != values.end(); ++itor)
1259 std::string value = *itor;
1260 Ogre::StringUtil::trim(value);
1262 if (value ==
"airspeed") { animation.
source |= Animation::SOURCE_AIRSPEED; }
1263 else if (value ==
"vvi") { animation.
source |= Animation::SOURCE_VERTICAL_VELOCITY; }
1264 else if (value ==
"altimeter100k") { animation.
source |= Animation::SOURCE_ALTIMETER_100K; }
1265 else if (value ==
"altimeter10k") { animation.
source |= Animation::SOURCE_ALTIMETER_10K; }
1266 else if (value ==
"altimeter1k") { animation.
source |= Animation::SOURCE_ALTIMETER_1K; }
1267 else if (value ==
"aoa") { animation.
source |= Animation::SOURCE_ANGLE_OF_ATTACK; }
1268 else if (value ==
"flap") { animation.
source |= Animation::SOURCE_FLAP; }
1269 else if (value ==
"airbrake") { animation.
source |= Animation::SOURCE_AIR_BRAKE; }
1270 else if (value ==
"roll") { animation.
source |= Animation::SOURCE_ROLL; }
1271 else if (value ==
"pitch") { animation.
source |= Animation::SOURCE_PITCH; }
1272 else if (value ==
"brakes") { animation.
source |= Animation::SOURCE_BRAKES; }
1273 else if (value ==
"accel") { animation.
source |= Animation::SOURCE_ACCEL; }
1274 else if (value ==
"clutch") { animation.
source |= Animation::SOURCE_CLUTCH; }
1275 else if (value ==
"speedo") { animation.
source |= Animation::SOURCE_SPEEDO; }
1276 else if (value ==
"tacho") { animation.
source |= Animation::SOURCE_TACHO; }
1277 else if (value ==
"turbo") { animation.
source |= Animation::SOURCE_TURBO; }
1278 else if (value ==
"parking") { animation.
source |= Animation::SOURCE_PARKING; }
1279 else if (value ==
"shifterman1") { animation.
source |= Animation::SOURCE_SHIFT_LEFT_RIGHT; }
1280 else if (value ==
"shifterman2") { animation.
source |= Animation::SOURCE_SHIFT_BACK_FORTH; }
1281 else if (value ==
"sequential") { animation.
source |= Animation::SOURCE_SEQUENTIAL_SHIFT; }
1282 else if (value ==
"shifterlin") { animation.
source |= Animation::SOURCE_SHIFTERLIN; }
1283 else if (value ==
"autoshifterlin"){ animation.
source |= Animation::SOURCE_AUTOSHIFTERLIN; }
1284 else if (value ==
"torque") { animation.
source |= Animation::SOURCE_TORQUE; }
1285 else if (value ==
"heading") { animation.
source |= Animation::SOURCE_HEADING; }
1286 else if (value ==
"difflock") { animation.
source |= Animation::SOURCE_DIFFLOCK; }
1287 else if (value ==
"rudderboat") { animation.
source |= Animation::SOURCE_BOAT_RUDDER; }
1288 else if (value ==
"throttleboat") { animation.
source |= Animation::SOURCE_BOAT_THROTTLE; }
1289 else if (value ==
"steeringwheel") { animation.
source |= Animation::SOURCE_STEERING_WHEEL; }
1290 else if (value ==
"aileron") { animation.
source |= Animation::SOURCE_AILERON; }
1291 else if (value ==
"elevator") { animation.
source |= Animation::SOURCE_ELEVATOR; }
1292 else if (value ==
"rudderair") { animation.
source |= Animation::SOURCE_AIR_RUDDER; }
1293 else if (value ==
"permanent") { animation.
source |= Animation::SOURCE_PERMANENT; }
1294 else if (value ==
"event") { animation.
source |= Animation::SOURCE_EVENT; }
1295 else if (value ==
"dashboard") { animation.
source |= Animation::SOURCE_DASHBOARD; }
1296 else if (value ==
"signalstalk") { animation.
source |= Animation::SOURCE_SIGNALSTALK; }
1297 else if (value ==
"gearreverse") { animation.
source |= Animation::SOURCE_GEAR_REVERSE; }
1298 else if (value ==
"gearneutral") { animation.
source |= Animation::SOURCE_GEAR_NEUTRAL; }
1304 if (entry[1].compare(0, 8,
"throttle") == 0)
1306 motor_source.
source = Animation::MotorSource::SOURCE_AERO_THROTTLE;
1307 motor_source.
motor = this->ParseArgUint(entry[1].substr(8));
1309 else if (entry[1].compare(0, 3,
"rpm") == 0)
1311 motor_source.
source = Animation::MotorSource::SOURCE_AERO_RPM;
1312 motor_source.
motor = this->ParseArgUint(entry[1].substr(3));
1314 else if (entry[1].compare(0, 8,
"aerotorq") == 0)
1316 motor_source.
source = Animation::MotorSource::SOURCE_AERO_TORQUE;
1317 motor_source.
motor = this->ParseArgUint(entry[1].substr(8));
1319 else if (entry[1].compare(0, 7,
"aeropit") == 0)
1321 motor_source.
source = Animation::MotorSource::SOURCE_AERO_PITCH;
1322 motor_source.
motor = this->ParseArgUint(entry[1].substr(7));
1324 else if (entry[1].compare(0, 10,
"aerostatus") == 0)
1326 motor_source.
source = Animation::MotorSource::SOURCE_AERO_STATUS;
1327 motor_source.
motor = this->ParseArgUint(entry[1].substr(10));
1330 else if (entry[1].compare(0, 4,
"gear") == 0)
1332 motor_source.
source = Animation::MotorSource::SOURCE_GEAR_FORWARD;
1333 motor_source.
motor = this->ParseArgUint(entry[1].substr(4));
1337 snprintf(warn_msg, WARN_LEN,
"Invalid 'source': %s, ignoring...", entry[1].c_str());
1346 snprintf(warn_msg, WARN_LEN,
"Invalid keyword: %s, ignoring...", entry[0].c_str());
1351 snprintf(warn_msg, WARN_LEN,
"Invalid item: %s, ignoring...", entry[0].c_str());
1354 if (warn_msg[0] !=
'\0')
1357 fmt::format(
"Ignoring invalid token '{}' ({})", itor->c_str(), warn_msg));
1361 m_current_module->props.back().animations.push_back(animation);
1364 void Parser::ParseAntiLockBrakes()
1367 Ogre::StringVector tokens = Ogre::StringUtil::split(m_current_line + 15,
",");
1368 m_num_args = (int)tokens.size();
1369 if (! this->CheckNumArguments(2)) {
return; }
1372 alb.
min_speed = this->ParseArgInt (tokens[1].c_str());
1374 if (tokens.size() > 3) { alb.
pulse_per_sec = this->ParseArgFloat(tokens[2].c_str()); }
1376 for (
unsigned int i=3; i<tokens.size(); i++)
1378 Ogre::StringVector args2 = Ogre::StringUtil::split(tokens[i],
":");
1379 Ogre::StringUtil::trim(args2[0]);
1380 Ogre::StringUtil::toLowerCase(args2[0]);
1381 if (args2[0] ==
"mode" && args2.size() == 2)
1383 Ogre::StringVector attrs = Ogre::StringUtil::split(args2[1],
"&");
1384 auto itor = attrs.begin();
1385 auto endi = attrs.end();
1386 for (; itor != endi; ++itor)
1388 std::string attr = *itor;
1389 Ogre::StringUtil::trim(attr);
1390 Ogre::StringUtil::toLowerCase(attr);
1392 else if (strncmp(attr.c_str(),
"notoggle", 8) == 0) { alb.
attr_no_toggle =
true; }
1393 else if (strncmp(attr.c_str(),
"on", 2) == 0) { alb.
attr_is_on =
true; }
1394 else if (strncmp(attr.c_str(),
"off", 3) == 0) { alb.
attr_is_on =
false; }
1406 m_current_module->antilockbrakes.push_back(alb);
1410 void Parser::ParseEngoption()
1412 if (! this->CheckNumArguments(1)) {
return; }
1415 engoption.
inertia = this->GetArgFloat(0);
1417 if (m_num_args > 1) { engoption.
type = this->GetArgEngineType(1); }
1418 if (m_num_args > 2) { engoption.
clutch_force = this->GetArgFloat(2); }
1419 if (m_num_args > 3) { engoption.
shift_time = this->GetArgFloat(3); }
1420 if (m_num_args > 4) { engoption.
clutch_time = this->GetArgFloat(4); }
1421 if (m_num_args > 5) { engoption.
post_shift_time = this->GetArgFloat(5); }
1422 if (m_num_args > 6) { engoption.
stall_rpm = this->GetArgFloat(6); }
1423 if (m_num_args > 7) { engoption.
idle_rpm = this->GetArgFloat(7); }
1426 if (m_num_args > 10){ engoption.
braking_torque = this->GetArgFloat(10);}
1428 m_current_module->engoption.push_back(engoption);
1432 void Parser::ParseEngturbo()
1434 if (! this->CheckNumArguments(4)) {
return; }
1437 engturbo.
version = this->GetArgInt ( 0);
1439 engturbo.
nturbos = this->GetArgInt ( 2);
1440 engturbo.
param1 = this->GetArgFloat( 3);
1442 if (m_num_args > 4) { engturbo.
param2 = this->GetArgFloat( 4); }
1443 if (m_num_args > 5) { engturbo.
param3 = this->GetArgFloat( 5); }
1444 if (m_num_args > 6) { engturbo.
param4 = this->GetArgFloat( 6); }
1445 if (m_num_args > 7) { engturbo.
param5 = this->GetArgFloat( 7); }
1446 if (m_num_args > 8) { engturbo.
param6 = this->GetArgFloat( 8); }
1447 if (m_num_args > 9) { engturbo.
param7 = this->GetArgFloat( 9); }
1448 if (m_num_args > 10) { engturbo.
param8 = this->GetArgFloat(10); }
1449 if (m_num_args > 11) { engturbo.
param9 = this->GetArgFloat(11); }
1450 if (m_num_args > 12) { engturbo.
param10 = this->GetArgFloat(12); }
1451 if (m_num_args > 13) { engturbo.
param11 = this->GetArgFloat(13); }
1459 m_current_module->engturbo.push_back(engturbo);
1463 void Parser::ParseEngine()
1465 if (! this->CheckNumArguments(6)) {
return; }
1470 engine.
torque = this->GetArgFloat(2);
1476 for (
int i = 6; i < m_num_args; i++)
1478 float ratio = this->GetArgFloat(i);
1492 m_current_module->engine.push_back(engine);
1496 void Parser::ParseContacter()
1498 if (! this->CheckNumArguments(1)) {
return; }
1500 m_current_module->contacters.push_back(this->GetArgNodeRef(0));
1504 void Parser::ParseCustomDashboardInputs()
1506 if (!this->CheckNumArguments(2)) {
return; }
1509 dashVal.
name = this->GetArgStr(0);
1510 dashVal.
data_type = this->GetArgDashboardInputDataType(1);
1514 fmt::format(
"Dashboard value \"{}\" has an invalid data type. Ignoring it.", dashVal.
name));
1518 m_current_module->customdashboardinputs.push_back(dashVal);
1522 void Parser::ParseCommandsUnified()
1524 const bool is_commands2 = (m_current_block == Keyword::COMMANDS2);
1525 const int max_args = (is_commands2 ? 8 : 7);
1526 if (! this->CheckNumArguments(max_args)) {
return; }
1534 command2.
nodes[0] = this->GetArgNodeRef(pos++);
1535 command2.
nodes[1] = this->GetArgNodeRef(pos++);
1550 command2.
extend_key = this->GetArgInt (pos++);
1552 if (m_num_args <= max_args)
1554 m_current_module->commands2.push_back(command2);
1559 std::string options_str = this->GetArgStr(pos++);
1561 for (
auto itor = options_str.begin(); itor != options_str.end(); ++itor)
1563 const char c = *itor;
1564 if ((winner == 0) && (c ==
'o' || c ==
'p' || c ==
'c')) { winner = c; }
1599 if (
ignored != 0 && winner ==
'c')
1602 "Command cannot be one-pressed and self centering at the same time, ignoring flag '%c'");
1604 else if (
ignored != 0 && (winner ==
'o' || winner ==
'p'))
1607 "Command already has a one-pressed c.mode, ignoring flag '%c'");
1610 if (m_num_args > pos) { command2.
description = this->GetArgStr (pos++);}
1612 if (m_num_args > pos) { ParseOptionalInertia(command2.
inertia, pos); pos += 4; }
1614 if (m_num_args > pos) { command2.
affect_engine = this->GetArgFloat(pos++);}
1615 if (m_num_args > pos) { command2.
needs_engine = this->GetArgBool (pos++);}
1616 if (m_num_args > pos) { command2.
plays_sound = this->GetArgBool (pos++);}
1618 m_current_module->commands2.push_back(command2);
1622 void Parser::ParseCollisionBox()
1626 Ogre::StringVector tokens = Ogre::StringUtil::split(m_current_line,
",");
1627 Ogre::StringVector::iterator iter = tokens.begin();
1628 for ( ; iter != tokens.end(); iter++)
1630 collisionbox.
nodes.push_back( this->_ParseNodeRef(*iter) );
1633 m_current_module->collisionboxes.push_back(collisionbox);
1637 void Parser::ParseCinecam()
1639 if (! this->CheckNumArguments(11)) {
return; }
1646 cinecam.
position.x = this->GetArgFloat ( 0);
1647 cinecam.
position.y = this->GetArgFloat ( 1);
1648 cinecam.
position.z = this->GetArgFloat ( 2);
1649 cinecam.
nodes[0] = this->GetArgNodeRef( 3);
1650 cinecam.
nodes[1] = this->GetArgNodeRef( 4);
1651 cinecam.
nodes[2] = this->GetArgNodeRef( 5);
1652 cinecam.
nodes[3] = this->GetArgNodeRef( 6);
1653 cinecam.
nodes[4] = this->GetArgNodeRef( 7);
1654 cinecam.
nodes[5] = this->GetArgNodeRef( 8);
1655 cinecam.
nodes[6] = this->GetArgNodeRef( 9);
1656 cinecam.
nodes[7] = this->GetArgNodeRef(10);
1659 if (m_num_args > 11) { cinecam.
spring = this->GetArgFloat(11); }
1660 if (m_num_args > 12) { cinecam.
damping = this->GetArgFloat(12); }
1662 if (m_num_args > 13)
1664 float value = this->GetArgFloat(13);
1669 if (m_sequential_importer.IsEnabled())
1671 m_sequential_importer.AddGeneratedNode(Keyword::CINECAM);
1674 m_current_module->cinecam.push_back(cinecam);
1678 void Parser::ParseCameraRails()
1680 m_current_camera_rail->nodes.push_back( this->GetArgNodeRef(0) );
1683 void Parser::ParseBrakes()
1685 if (!this->CheckNumArguments(1)) {
return; }
1693 m_current_module->brakes.push_back(brakes);
1697 void Parser::ParseAxles()
1701 Ogre::StringVector tokens = Ogre::StringUtil::split(m_current_line,
",");
1702 Ogre::StringVector::iterator iter = tokens.begin();
1703 for ( ; iter != tokens.end(); iter++)
1705 std::smatch results;
1706 if (! std::regex_search(*iter, results, Regexes::SECTION_AXLES_PROPERTY))
1713 if (results[1].matched)
1715 unsigned int wheel_index =
PARSEINT(results[2]) - 1;
1716 axle.
wheels[wheel_index][0] = _ParseNodeRef(results[3]);
1717 axle.
wheels[wheel_index][1] = _ParseNodeRef(results[4]);
1719 else if (results[5].matched)
1721 this->_ParseDifferentialTypes(axle.
options, results[6].str());
1725 m_current_module->axles.push_back(axle);
1729 void Parser::ParseInterAxles()
1731 auto args = Ogre::StringUtil::split(m_current_line,
",");
1732 if (args.size() < 2) {
return; }
1736 interaxle.
a1 = this->ParseArgInt(args[0].c_str()) - 1;
1737 interaxle.
a2 = this->ParseArgInt(args[1].c_str()) - 1;
1739 std::smatch results;
1740 if (! std::regex_search(args[2], results, Regexes::SECTION_AXLES_PROPERTY))
1747 if (results[5].matched)
1749 this->_ParseDifferentialTypes(interaxle.
options, results[6].str());
1752 m_current_module->interaxles.push_back(interaxle);
1756 void Parser::ParseAirbrakes()
1758 if (! this->CheckNumArguments(14)) {
return; }
1765 airbrake.
offset.x = this->GetArgFloat ( 4);
1766 airbrake.
offset.y = this->GetArgFloat ( 5);
1767 airbrake.
offset.z = this->GetArgFloat ( 6);
1768 airbrake.
width = this->GetArgFloat ( 7);
1769 airbrake.
height = this->GetArgFloat ( 8);
1776 m_current_module->airbrakes.push_back(airbrake);
1777 this->FlushPendingDocComment(m_current_module->airbrakes.size(), Keyword::AIRBRAKES);
1780 void Parser::ParseAssetpacks()
1782 if (! this->CheckNumArguments(1)) {
return; }
1786 assetpack.
filename = this->GetArgStr(0);
1788 m_current_module->assetpacks.push_back(assetpack);
1789 this->FlushPendingDocComment(m_current_module->assetpacks.size(), Keyword::ASSETPACKS);
1792 void Parser::ParseVideoCamera()
1794 if (! this->CheckNumArguments(19)) {
return; }
1799 videocamera.
left_node = this->GetArgNodeRef ( 1);
1800 videocamera.
bottom_node = this->GetArgNodeRef ( 2);
1803 videocamera.
offset.x = this->GetArgFloat ( 5);
1804 videocamera.
offset.y = this->GetArgFloat ( 6);
1805 videocamera.
offset.z = this->GetArgFloat ( 7);
1806 videocamera.
rotation.x = this->GetArgFloat ( 8);
1807 videocamera.
rotation.y = this->GetArgFloat ( 9);
1808 videocamera.
rotation.z = this->GetArgFloat (10);
1814 videocamera.
camera_role = this->GetArgVideoCamRole(16);
1818 if (m_num_args > 19) { videocamera.
camera_name = this->GetArgStr(19); }
1820 m_current_module->videocameras.push_back(videocamera);
1821 this->FlushPendingDocComment(m_current_module->videocameras.size(), Keyword::VIDEOCAMERA);
1824 void Parser::ParseCameras()
1826 if (! this->CheckNumArguments(3)) {
return; }
1830 camera.
back_node = this->GetArgNodeRef(1);
1831 camera.
left_node = this->GetArgNodeRef(2);
1833 m_current_module->cameras.push_back(camera);
1834 this->FlushPendingDocComment(m_current_module->cameras.size(), Keyword::CAMERAS);
1837 void Parser::ParseTurbopropsUnified()
1839 bool is_turboprop_2 = m_current_block == Keyword::TURBOPROPS2;
1841 if (! this->CheckNumArguments(is_turboprop_2 ? 9 : 8)) {
return; }
1846 turboprop.
axis_node = this->GetArgNodeRef(1);
1856 turboprop.
couple_node = this->GetArgNullableNode(6);
1862 turboprop.
airfoil = this->GetArgStr (7 + offset);
1864 m_current_module->turboprops2.push_back(turboprop);
1865 this->FlushPendingDocComment(m_current_module->turboprops2.size(), Keyword::TURBOPROPS2);
1868 void Parser::ParseTurbojets()
1870 if (! this->CheckNumArguments(9)) {
return; }
1873 turbojet.
front_node = this->GetArgNodeRef(0);
1874 turbojet.
back_node = this->GetArgNodeRef(1);
1875 turbojet.
side_node = this->GetArgNodeRef(2);
1883 m_current_module->turbojets.push_back(turbojet);
1884 this->FlushPendingDocComment(m_current_module->turbojets.size(), Keyword::TURBOJETS);
1887 void Parser::ParseTriggers()
1889 if (! this->CheckNumArguments(6)) {
return; }
1894 trigger.
nodes[0] = this->GetArgNodeRef(0);
1895 trigger.
nodes[1] = this->GetArgNodeRef(1);
1900 if (m_num_args > 6) trigger.
options = this->GetArgTriggerOptions(6);
1901 if (m_num_args > 7) trigger.
boundary_timer = this->GetArgFloat(7);
1903 m_current_module->triggers.push_back(trigger);
1904 this->FlushPendingDocComment(m_current_module->triggers.size(), Keyword::TRIGGERS);
1907 void Parser::ParseTorqueCurve()
1909 if (m_current_module->torquecurve.size() == 0)
1911 m_current_module->torquecurve.push_back(
TorqueCurve());
1914 Ogre::StringVector args = Ogre::StringUtil::split(m_current_line,
",");
1916 if (args.size() == 1u)
1918 m_current_module->torquecurve[0].predefined_func_name = args[0];
1920 else if (args.size() == 2u)
1923 sample.
power = this->ParseArgFloat(args[0].c_str());
1925 m_current_module->torquecurve[0].samples.push_back(sample);
1934 void Parser::ParseTies()
1936 if (! this->CheckNumArguments(5)) {
return; }
1950 for (
char c: this->GetArgStr(5))
1954 case (
char)TieOption::n_DUMMY:
1955 case (
char)TieOption::v_DUMMY:
1958 case (
char)TieOption::i_INVISIBLE:
1959 tie.
options |= Tie::OPTION_i_INVISIBLE;
1962 case (
char)TieOption::s_NO_SELF_LOCK:
1963 tie.
options |= Tie::OPTION_s_DISABLE_SELF_LOCK;
1974 if (m_num_args > 6) { tie.
max_stress = this->GetArgFloat (6); }
1975 if (m_num_args > 7) { tie.
group = this->GetArgInt (7); }
1977 m_current_module->ties.push_back(tie);
1978 this->FlushPendingDocComment(m_current_module->ties.size(), Keyword::TIES);
1981 void Parser::ParseSoundsources()
1983 if (! this->CheckNumArguments(2)) {
return; }
1986 soundsource.
node = this->GetArgNodeRef(0);
1989 m_current_module->soundsources.push_back(soundsource);
1990 this->FlushPendingDocComment(m_current_module->soundsources.size(), Keyword::SOUNDSOURCES);
1993 void Parser::ParseSoundsources2()
1995 if (! this->CheckNumArguments(3)) {
return; }
1998 soundsource2.
node = this->GetArgNodeRef(0);
1999 soundsource2.
mode = this->GetArgInt(1);
2002 if (soundsource2.
mode < -2)
2005 fmt::format(
"invalid mode {}, falling back to default -2", soundsource2.
mode));
2006 soundsource2.
mode = -2;
2009 m_current_module->soundsources2.push_back(soundsource2);
2010 this->FlushPendingDocComment(m_current_module->soundsources2.size(), Keyword::SOUNDSOURCES2);
2013 void Parser::ParseSlidenodes()
2015 Ogre::StringVector args = Ogre::StringUtil::split(m_current_line,
", ");
2016 m_num_args = (int)args.size();
2017 if (! this->CheckNumArguments(2)) {
return; }
2020 slidenode.
slide_node = this->_ParseNodeRef(args[0]);
2022 bool in_rail_node_list =
true;
2024 for (
auto itor = args.begin() + 1; itor != args.end(); ++itor)
2026 char c = toupper(itor->at(0));
2030 slidenode.
spring_rate = this->ParseArgFloat(itor->substr(1));
2032 in_rail_node_list =
false;
2035 slidenode.
break_force = this->ParseArgFloat(itor->substr(1));
2037 in_rail_node_list =
false;
2040 slidenode.
tolerance = this->ParseArgFloat(itor->substr(1));
2042 in_rail_node_list =
false;
2047 in_rail_node_list =
false;
2050 slidenode.
railgroup_id = this->ParseArgFloat(itor->substr(1));
2052 in_rail_node_list =
false;
2057 in_rail_node_list =
false;
2060 switch (itor->at(1))
2076 fmt::format(
"Ignoring invalid option '{}'", itor->at(1)));
2079 in_rail_node_list =
false;
2082 if (in_rail_node_list)
2088 m_current_module->slidenodes.push_back(slidenode);
2089 this->FlushPendingDocComment(m_current_module->slidenodes.size(), Keyword::SLIDENODES);
2092 void Parser::ParseShock3()
2094 if (! this->CheckNumArguments(15)) {
return; }
2100 shock_3.
nodes[0] = this->GetArgNodeRef( 0);
2101 shock_3.
nodes[1] = this->GetArgNodeRef( 1);
2102 shock_3.
spring_in = this->GetArgFloat ( 2);
2103 shock_3.
damp_in = this->GetArgFloat ( 3);
2108 shock_3.
damp_out = this->GetArgFloat ( 8);
2116 if (m_num_args > 15) shock_3.
options = this->GetArgShock3Options(15);
2118 m_current_module->shocks3.push_back(shock_3);
2119 this->FlushPendingDocComment(m_current_module->shocks3.size(), Keyword::SHOCKS3);
2122 void Parser::ParseShock2()
2124 if (! this->CheckNumArguments(13)) {
return; }
2130 shock_2.
nodes[0] = this->GetArgNodeRef( 0);
2131 shock_2.
nodes[1] = this->GetArgNodeRef( 1);
2132 shock_2.
spring_in = this->GetArgFloat ( 2);
2133 shock_2.
damp_in = this->GetArgFloat ( 3);
2137 shock_2.
damp_out = this->GetArgFloat ( 7);
2144 if (m_num_args > 13) shock_2.
options = this->GetArgShock2Options(13);
2146 m_current_module->shocks2.push_back(shock_2);
2147 this->FlushPendingDocComment(m_current_module->shocks2.size(), Keyword::SHOCKS2);
2150 void Parser::ParseShock()
2152 if (! this->CheckNumArguments(7)) {
return; }
2158 shock.
nodes[0] = this->GetArgNodeRef(0);
2159 shock.
nodes[1] = this->GetArgNodeRef(1);
2161 shock.
damping = this->GetArgFloat (3);
2165 if (m_num_args > 7) shock.
options = this->GetArgShockOptions(7);
2167 m_current_module->shocks.push_back(shock);
2168 this->FlushPendingDocComment(m_current_module->shocks.size(), Keyword::SHOCKS);
2171 Node::Ref Parser::_ParseNodeRef(std::string
const & node_id_str)
2173 if (m_sequential_importer.IsEnabled())
2176 int node_id_num =
PARSEINT(node_id_str);
2177 if (node_id_num < 0)
2183 unsigned int flags = Node::Ref::IMPORT_STATE_IS_VALID |
2184 Node::Ref::REGULAR_STATE_IS_VALID | Node::Ref::REGULAR_STATE_IS_NAMED;
2185 if (m_any_named_node_defined)
2187 flags |= Node::Ref::IMPORT_STATE_MUST_CHECK_NAMED_FIRST;
2189 return Node::Ref(node_id_str, node_id_num, flags, m_current_line_number);
2194 return Node::Ref(node_id_str, 0, Node::Ref::REGULAR_STATE_IS_VALID | Node::Ref::REGULAR_STATE_IS_NAMED, m_current_line_number);
2198 void Parser::ParseDirectiveSetDefaultMinimass()
2200 if (! this->CheckNumArguments(2)) {
return; }
2202 m_set_default_minimass = std::shared_ptr<DefaultMinimass>(
new DefaultMinimass());
2203 m_set_default_minimass->min_mass_Kg = this->GetArgFloat(1);
2206 void Parser::ParseFlaregroupsNoImport()
2210 if (!this->CheckNumArguments(1)) {
return; }
2213 fni.
type = this->GetArgFlareType(0);
2228 m_current_module->flaregroups_no_import.push_back(fni);
2231 void Parser::ParseDirectiveSetInertiaDefaults()
2233 if (! this->CheckNumArguments(2)) {
return; }
2235 float start_delay = this->GetArgFloat(1);
2236 float stop_delay = 0;
2237 if (m_num_args > 2) { stop_delay = this->GetArgFloat(2); }
2239 if (start_delay < 0 || stop_delay < 0)
2241 m_user_default_inertia = m_ror_default_inertia;
2251 if (m_num_args > 4) { i->
stop_function = this->GetArgStr(4); }
2253 m_user_default_inertia = std::shared_ptr<Inertia>(i);
2256 void Parser::ParseScrewprops()
2258 if (! this->CheckNumArguments(4)) {
return; }
2262 screwprop.
prop_node = this->GetArgNodeRef(0);
2263 screwprop.
back_node = this->GetArgNodeRef(1);
2264 screwprop.
top_node = this->GetArgNodeRef(2);
2265 screwprop.
power = this->GetArgFloat (3);
2267 m_current_module->screwprops.push_back(screwprop);
2268 this->FlushPendingDocComment(m_current_module->screwprops.size(), Keyword::SCREWPROPS);
2271 void Parser::ParseScripts()
2273 if (!this->CheckNumArguments(1)) {
return; }
2277 script.
filename = this->GetArgStr(0);
2279 m_current_module->scripts.push_back(script);
2280 this->FlushPendingDocComment(m_current_module->scripts.size(), Keyword::SCRIPTS);
2283 void Parser::ParseRotatorsUnified()
2285 if (! this->CheckNumArguments(13)) {
return; }
2290 rotator.
axis_nodes[0] = this->GetArgNodeRef( 0);
2291 rotator.
axis_nodes[1] = this->GetArgNodeRef( 1);
2300 rotator.
rate = this->GetArgFloat (10);
2306 if (m_current_block == Keyword::ROTATORS2)
2308 if (! this->CheckNumArguments(16)) {
return; }
2309 if (m_num_args > 13) { rotator.
rotating_force = this->GetArgFloat(13); }
2310 if (m_num_args > 14) { rotator.
tolerance = this->GetArgFloat(14); }
2311 if (m_num_args > 15) { rotator.
description = this->GetArgStr (15); }
2316 this->ParseOptionalInertia(rotator.
inertia, 13 + offset);
2317 if (m_num_args > 17 + offset) { rotator.
engine_coupling = this->GetArgFloat(17 + offset); }
2318 if (m_num_args > 18 + offset) { rotator.
needs_engine = this->GetArgBool (18 + offset); }
2320 if (m_current_block == Keyword::ROTATORS2)
2322 m_current_module->rotators2.push_back(rotator);
2323 this->FlushPendingDocComment(m_current_module->rotators2.size(), Keyword::ROTATORS2);
2327 m_current_module->rotators.push_back(rotator);
2328 this->FlushPendingDocComment(m_current_module->rotators.size(), Keyword::ROTATORS);
2332 void Parser::ParseFileinfo()
2334 if (! this->CheckNumArguments(2)) {
return; }
2338 fileinfo.
unique_id = this->GetArgStr(1);
2339 Ogre::StringUtil::trim(fileinfo.
unique_id);
2341 if (m_num_args > 2) { fileinfo.
category_id = this->GetArgInt(2); }
2342 if (m_num_args > 3) { fileinfo.
file_version = this->GetArgInt(3); }
2344 m_current_module->fileinfo.push_back(fileinfo);
2346 m_current_block = Keyword::INVALID;
2349 void Parser::ParseRopes()
2351 if (! this->CheckNumArguments(2)) {
return; }
2356 rope.
root_node = this->GetArgNodeRef(0);
2357 rope.
end_node = this->GetArgNodeRef(1);
2359 if (m_num_args > 2) { rope.
invisible = (this->GetArgChar(2) ==
'i'); }
2361 m_current_module->ropes.push_back(rope);
2362 this->FlushPendingDocComment(m_current_module->ropes.size(), Keyword::ROPES);
2365 void Parser::ParseRopables()
2367 if (! this->CheckNumArguments(1)) {
return; }
2370 ropable.
node = this->GetArgNodeRef(0);
2372 if (m_num_args > 1) { ropable.
group = this->GetArgInt(1); }
2373 if (m_num_args > 2) { ropable.
has_multilock = (this->GetArgInt(2) == 1); }
2375 m_current_module->ropables.push_back(ropable);
2376 this->FlushPendingDocComment(m_current_module->ropables.size(), Keyword::ROPABLES);
2379 void Parser::ParseRailGroups()
2381 Ogre::StringVector args = Ogre::StringUtil::split(m_current_line,
",");
2382 m_num_args = (int)args.size();
2383 if (! this->CheckNumArguments(3)) {
return; }
2386 railgroup.
id = this->ParseArgInt(args[0].c_str());
2388 for (
auto itor = args.begin() + 1; itor != args.end(); itor++)
2390 railgroup.
node_list.push_back( this->_ParseNodeRef(*itor));
2393 m_current_module->railgroups.push_back(railgroup);
2394 this->FlushPendingDocComment(m_current_module->railgroups.size(), Keyword::RAILGROUPS);
2397 void Parser::ParseProps()
2399 if (! this->CheckNumArguments(10)) {
return; }
2405 prop.
offset.x = this->GetArgFloat (3);
2406 prop.
offset.y = this->GetArgFloat (4);
2407 prop.
offset.z = this->GetArgFloat (5);
2408 prop.
rotation.x = this->GetArgFloat (6);
2409 prop.
rotation.y = this->GetArgFloat (7);
2410 prop.
rotation.z = this->GetArgFloat (8);
2414 if ((prop.
special == SpecialProp::BEACON) && (m_num_args >= 14))
2420 this->GetArgFloat(11), this->GetArgFloat(12), this->GetArgFloat(13));
2422 else if (prop.
special == SpecialProp::DASHBOARD_LEFT ||
2423 prop.
special == SpecialProp::DASHBOARD_RIGHT)
2426 if (m_num_args > 13)
2434 m_current_module->props.push_back(prop);
2435 this->FlushPendingDocComment(m_current_module->props.size(), Keyword::PROPS);
2438 void Parser::ParsePistonprops()
2440 if (!this->CheckNumArguments(10)) {
return; }
2444 pistonprop.
axis_node = this->GetArgNodeRef (1);
2449 pistonprop.
couple_node = this->GetArgNullableNode(6);
2451 pistonprop.
pitch = this->GetArgFloat (8);
2452 pistonprop.
airfoil = this->GetArgStr (9);
2454 m_current_module->pistonprops.push_back(pistonprop);
2455 this->FlushPendingDocComment(m_current_module->pistonprops.size(), Keyword::PISTONPROPS);
2458 void Parser::ParseParticles()
2460 if (!this->CheckNumArguments(3)) {
return; }
2467 m_current_module->particles.push_back(particle);
2468 this->FlushPendingDocComment(m_current_module->particles.size(), Keyword::PARTICLES);
2472 void Parser::_TrimTrailingComments(std::string
const & line_in, std::string & line_out)
2476 int comment_start =
static_cast<int>(line_in.find_first_of(
";"));
2477 if (comment_start != Ogre::String::npos)
2479 line_out = line_in.substr(0, comment_start);
2483 comment_start =
static_cast<int>(line_in.find_last_of(
"/"));
2484 if (comment_start != Ogre::String::npos)
2486 while (comment_start >= 0)
2488 char c = line_in[comment_start - 1];
2489 if (c !=
'/' && c !=
' ' && c !=
'\t')
2495 line_out = line_in.substr(0, comment_start);
2502 void Parser::ParseNodesUnified()
2504 if (! this->CheckNumArguments(4)) {
return; }
2512 if (m_current_block == Keyword::NODES2)
2514 std::string node_name = this->GetArgStr(0);
2516 if (m_sequential_importer.IsEnabled())
2518 m_sequential_importer.AddNamedNode(node_name);
2520 m_any_named_node_defined =
true;
2524 const unsigned int node_num = this->GetArgUint(0);
2526 if (m_sequential_importer.IsEnabled())
2528 m_sequential_importer.AddNumberedNode(node_num);
2532 node.
position.x = this->GetArgFloat(1);
2533 node.
position.y = this->GetArgFloat(2);
2534 node.
position.z = this->GetArgFloat(3);
2537 node.
options = this->GetArgNodeOptions(4);
2541 if (node.
options & Node::OPTION_l_LOAD_WEIGHT)
2549 "Node has load-weight-override value specified, but option 'l' is not present. Ignoring value...");
2553 m_current_module->nodes.push_back(node);
2554 this->FlushPendingDocComment(m_current_module->nodes.size(), Keyword::NODES);
2557 void Parser::ParseMinimass()
2559 if (! this->CheckNumArguments(1)) {
return; }
2563 if (m_num_args > 1) { mm.
option = this->GetArgMinimassOption(1); }
2565 m_current_module->minimass.push_back(mm);
2566 m_current_block = Keyword::INVALID;
2569 void Parser::ParseFlexBodyWheel()
2571 if (! this->CheckNumArguments(16)) {
return; }
2577 flexbody_wheel.
tyre_radius = this->GetArgFloat ( 0);
2578 flexbody_wheel.
rim_radius = this->GetArgFloat ( 1);
2579 flexbody_wheel.
width = this->GetArgFloat ( 2);
2580 flexbody_wheel.
num_rays = this->GetArgInt ( 3);
2581 flexbody_wheel.
nodes[0] = this->GetArgNodeRef ( 4);
2582 flexbody_wheel.
nodes[1] = this->GetArgNodeRef ( 5);
2583 flexbody_wheel.
rigidity_node = this->GetArgRigidityNode ( 6);
2584 flexbody_wheel.
braking = this->GetArgBraking ( 7);
2585 flexbody_wheel.
propulsion = this->GetArgPropulsion ( 8);
2587 flexbody_wheel.
mass = this->GetArgFloat (10);
2591 flexbody_wheel.
rim_damping = this->GetArgFloat (14);
2592 flexbody_wheel.
side = this->GetArgWheelSide (15);
2594 if (m_num_args > 16) { flexbody_wheel.
rim_mesh_name = this->GetArgStr(16); }
2595 if (m_num_args > 17) { flexbody_wheel.
tyre_mesh_name = this->GetArgStr(17); }
2597 if (m_sequential_importer.IsEnabled())
2602 m_current_module->flexbodywheels.push_back(flexbody_wheel);
2603 this->FlushPendingDocComment(m_current_module->flexbodywheels.size(), Keyword::FLEXBODYWHEELS);
2606 void Parser::ParseMaterialFlareBindings()
2608 if (! this->CheckNumArguments(2)) {
return; }
2614 m_current_module->materialflarebindings.push_back(binding);
2615 this->FlushPendingDocComment(m_current_module->materialflarebindings.size(), Keyword::MATERIALFLAREBINDINGS);
2618 void Parser::ParseManagedMaterials()
2620 if (! this->CheckNumArguments(2)) {
return; }
2623 managed_mat.
options = m_current_managed_material_options;
2624 managed_mat.
name = this->GetArgStr(0);
2625 managed_mat.
type = this->GetArgManagedMatType(1);
2627 if (managed_mat.
type != ManagedMaterialType::INVALID)
2629 if (! this->CheckNumArguments(3)) {
return; }
2633 if (managed_mat.
type == ManagedMaterialType::MESH_STANDARD ||
2634 managed_mat.
type == ManagedMaterialType::MESH_TRANSPARENT)
2636 if (m_num_args > 3) { managed_mat.
specular_map = this->GetArgManagedTex(3); }
2638 else if (managed_mat.
type == ManagedMaterialType::FLEXMESH_STANDARD ||
2639 managed_mat.
type == ManagedMaterialType::FLEXMESH_TRANSPARENT)
2642 if (m_num_args > 4) { managed_mat.
specular_map = this->GetArgManagedTex(4); }
2645 m_current_module->managedmaterials.push_back(managed_mat);
2646 this->FlushPendingDocComment(m_current_module->managedmaterials.size(), Keyword::MANAGEDMATERIALS);
2650 void Parser::ParseLockgroups()
2652 if (! this->CheckNumArguments(2)) {
return; }
2655 lockgroup.
number = this->GetArgInt(0);
2657 for (
int i = 1; i < m_num_args; ++i)
2659 lockgroup.
nodes.push_back(this->GetArgNodeRef(i));
2662 m_current_module->lockgroups.push_back(lockgroup);
2663 this->FlushPendingDocComment(m_current_module->lockgroups.size(), Keyword::LOCKGROUPS);
2666 void Parser::ParseHydros()
2668 if (! this->CheckNumArguments(3)) {
return; }
2675 hydro.
nodes[0] = this->GetArgNodeRef(0);
2676 hydro.
nodes[1] = this->GetArgNodeRef(1);
2679 if (m_num_args > 3) { hydro.
options = this->GetArgHydroOptions(3); }
2683 hydro.
options |= Hydro::OPTION_n_INPUT_NORMAL;
2686 this->ParseOptionalInertia(hydro.
inertia, 4);
2688 m_current_module->hydros.push_back(hydro);
2689 this->FlushPendingDocComment(m_current_module->hydros.size(), Keyword::HYDROS);
2692 void Parser::ParseOptionalInertia(
Inertia & inertia,
int index)
2695 if (m_num_args > index) { inertia.
stop_delay_factor = this->GetArgFloat(index++); }
2696 if (m_num_args > index) { inertia.
start_function = this->GetArgStr (index++); }
2697 if (m_num_args > index) { inertia.
stop_function = this->GetArgStr (index++); }
2702 for (
char c: options_str)
2706 case (
char)DifferentialType::o_OPEN:
2707 case (
char)DifferentialType::l_LOCKED:
2708 case (
char)DifferentialType::s_SPLIT:
2709 case (
char)DifferentialType::v_VISCOUS:
2715 fmt::format(
"ignoring invalid differential type '{}'", c));
2721 void Parser::ParseBeams()
2723 if (! this->CheckNumArguments(2)) {
return; }
2726 beam.
defaults = m_user_beam_defaults;
2729 beam.
nodes[0] = this->GetArgNodeRef(0);
2730 beam.
nodes[1] = this->GetArgNodeRef(1);
2731 if (m_num_args > 2) beam.
options = this->GetArgBeamOptions(2);
2735 float support_break_limit = 0.0f;
2736 float support_break_factor = this->GetArgInt(3);
2737 if (support_break_factor > 0.0f)
2739 support_break_limit = support_break_factor;
2745 m_current_module->beams.push_back(beam);
2746 this->FlushPendingDocComment(m_current_module->beams.size(), Keyword::BEAMS);
2749 void Parser::ParseAnimator()
2751 auto args = Ogre::StringUtil::split(m_current_line,
",");
2752 if (args.size() < 4) {
return; }
2759 animator.
nodes[0] = this->_ParseNodeRef(args[0]);
2760 animator.
nodes[1] = this->_ParseNodeRef(args[1]);
2764 Ogre::StringVector attrs = Ogre::StringUtil::split(args[3],
"|");
2766 auto itor = attrs.begin();
2767 auto endi = attrs.end();
2768 for (; itor != endi; ++itor)
2770 Ogre::String token = *itor;
2771 Ogre::StringUtil::trim(token);
2772 std::smatch results;
2773 bool is_shortlimit =
false;
2776 if (std::regex_search(token, results, Regexes::PARSE_ANIMATORS_NUMBERED_KEYWORD))
2778 if (results[1] ==
"throttle") animator.
aero_animator.
flags |= AeroAnimator::OPTION_THROTTLE;
2779 else if (results[1] ==
"rpm") animator.
aero_animator.
flags |= AeroAnimator::OPTION_RPM;
2780 else if (results[1] ==
"aerotorq") animator.
aero_animator.
flags |= AeroAnimator::OPTION_TORQUE;
2781 else if (results[1] ==
"aeropit") animator.
aero_animator.
flags |= AeroAnimator::OPTION_PITCH;
2782 else if (results[1] ==
"aerostatus") animator.
aero_animator.
flags |= AeroAnimator::OPTION_STATUS;
2786 else if ((is_shortlimit = (token.compare(0, 10,
"shortlimit") == 0)) || (token.compare(0, 9,
"longlimit") == 0))
2788 Ogre::StringVector fields = Ogre::StringUtil::split(token,
":");
2789 if (fields.size() > 1)
2793 animator.
short_limit = std::strtod(fields[1].c_str(),
nullptr);
2794 animator.
flags |= Animator::OPTION_SHORT_LIMIT;
2798 animator.
long_limit = std::strtod(fields[1].c_str(),
nullptr);
2799 animator.
flags |= Animator::OPTION_LONG_LIMIT;
2806 if (token ==
"vis") animator.
flags |= Animator::OPTION_VISIBLE;
2807 else if (token ==
"inv") animator.
flags |= Animator::OPTION_INVISIBLE;
2808 else if (token ==
"airspeed") animator.
flags |= Animator::OPTION_AIRSPEED;
2809 else if (token ==
"vvi") animator.
flags |= Animator::OPTION_VERTICAL_VELOCITY;
2810 else if (token ==
"altimeter100k") animator.
flags |= Animator::OPTION_ALTIMETER_100K;
2811 else if (token ==
"altimeter10k") animator.
flags |= Animator::OPTION_ALTIMETER_10K;
2812 else if (token ==
"altimeter1k") animator.
flags |= Animator::OPTION_ALTIMETER_1K;
2813 else if (token ==
"aoa") animator.
flags |= Animator::OPTION_ANGLE_OF_ATTACK;
2814 else if (token ==
"flap") animator.
flags |= Animator::OPTION_FLAP;
2815 else if (token ==
"airbrake") animator.
flags |= Animator::OPTION_AIR_BRAKE;
2816 else if (token ==
"roll") animator.
flags |= Animator::OPTION_ROLL;
2817 else if (token ==
"pitch") animator.
flags |= Animator::OPTION_PITCH;
2818 else if (token ==
"brakes") animator.
flags |= Animator::OPTION_BRAKES;
2819 else if (token ==
"accel") animator.
flags |= Animator::OPTION_ACCEL;
2820 else if (token ==
"clutch") animator.
flags |= Animator::OPTION_CLUTCH;
2821 else if (token ==
"speedo") animator.
flags |= Animator::OPTION_SPEEDO;
2822 else if (token ==
"tacho") animator.
flags |= Animator::OPTION_TACHO;
2823 else if (token ==
"turbo") animator.
flags |= Animator::OPTION_TURBO;
2824 else if (token ==
"parking") animator.
flags |= Animator::OPTION_PARKING;
2825 else if (token ==
"shifterman1") animator.
flags |= Animator::OPTION_SHIFT_LEFT_RIGHT;
2826 else if (token ==
"shifterman2") animator.
flags |= Animator::OPTION_SHIFT_BACK_FORTH;
2827 else if (token ==
"sequential") animator.
flags |= Animator::OPTION_SEQUENTIAL_SHIFT;
2828 else if (token ==
"shifterlin") animator.
flags |= Animator::OPTION_GEAR_SELECT;
2829 else if (token ==
"torque") animator.
flags |= Animator::OPTION_TORQUE;
2830 else if (token ==
"difflock") animator.
flags |= Animator::OPTION_DIFFLOCK;
2831 else if (token ==
"rudderboat") animator.
flags |= Animator::OPTION_BOAT_RUDDER;
2832 else if (token ==
"throttleboat") animator.
flags |= Animator::OPTION_BOAT_THROTTLE;
2836 m_current_module->animators.push_back(animator);
2837 this->FlushPendingDocComment(m_current_module->animators.size(), Keyword::ANIMATORS);
2840 void Parser::ParseAuthor()
2842 if (! this->CheckNumArguments(2)) {
return; }
2845 if (m_num_args > 1) { author.
type = this->GetArgStr(1); }
2847 if (m_num_args > 3) { author.
name = this->GetArgStr(3); }
2848 if (m_num_args > 4) { author.
email = this->GetArgStr(4); }
2850 m_current_module->author.push_back(author);
2851 this->FlushPendingDocComment(m_current_module->author.size(), Keyword::AUTHOR);
2852 m_current_block = Keyword::INVALID;
2865 m_filename, m_current_line_number,
KeywordToString(m_log_keyword), msg));
2868 Keyword Parser::IdentifyKeyword(
const std::string& line)
2871 std::smatch results;
2872 std::regex_search(line, results, Regexes::IDENTIFY_KEYWORD_IGNORE_CASE);
2876 for (
unsigned int i = 1; i < results.size(); i++)
2878 std::ssub_match sub = results[i];
2886 return Keyword::INVALID;
2889 void Parser::Prepare()
2891 m_current_block = Keyword::INVALID;
2892 m_current_line_number = 1;
2894 m_any_named_node_defined =
false;
2895 m_current_detacher_group = 0;
2897 m_user_default_inertia = m_ror_default_inertia;
2898 m_user_node_defaults = m_ror_node_defaults;
2901 m_user_beam_defaults = std::shared_ptr<BeamDefaults>(
new BeamDefaults);
2904 m_user_beam_defaults->deformation_threshold =
BEAM_DEFORM;
2905 m_user_beam_defaults->breaking_threshold =
BEAM_BREAK;
2908 m_root_module = m_definition->root_module;
2909 m_current_module = m_definition->root_module;
2911 m_sequential_importer.Init(
true);
2916 if (
keyword == Keyword::INVALID)
2919 if (m_current_submesh !=
nullptr)
2921 m_current_module->submeshes.push_back(*m_current_submesh);
2922 m_current_submesh.reset();
2926 if (m_current_camera_rail !=
nullptr)
2928 if (m_current_camera_rail->nodes.size() == 0)
2934 m_current_module->camerarail.push_back(*m_current_camera_rail);
2935 m_current_camera_rail.reset();
2939 else if (
keyword == Keyword::CAMERARAIL)
2941 this->BeginBlock(Keyword::INVALID);
2942 m_current_camera_rail = std::shared_ptr<CameraRail>(
new CameraRail() );
2950 std::string new_module_name;
2951 if (
keyword == Keyword::END_SECTION)
2953 if (m_current_module == m_root_module)
2960 else if (
keyword == Keyword::SECTION)
2962 if (!this->CheckNumArguments(3))
2967 new_module_name = this->GetArgStr(2);
2968 if (new_module_name == m_current_module->name)
2976 this->BeginBlock(Keyword::INVALID);
2980 m_current_module = m_root_module;
2984 auto search_itor = m_definition->user_modules.find(new_module_name);
2985 if (search_itor != m_definition->user_modules.end())
2987 m_current_module = search_itor->second;
2991 m_current_module = std::make_shared<Document::Module>(new_module_name);
2992 m_definition->user_modules.insert(std::make_pair(new_module_name, m_current_module));
2998 if (m_pending_doc_comment.comment_text ==
"" || vectorlen == 0)
3003 m_pending_doc_comment.commented_keyword =
keyword;
3004 m_pending_doc_comment.commented_datapos =
static_cast<int>(vectorlen - 1);
3005 m_current_module->_comments.push_back(m_pending_doc_comment);
3010 void Parser::ParseDirectiveSection()
3012 this->ProcessChangeModuleLine(Keyword::SECTION);
3015 void Parser::ParseDirectiveSectionConfig()
3020 void Parser::Finalize()
3022 this->BeginBlock(Keyword::INVALID);
3024 if (m_sequential_importer.IsEnabled())
3026 m_sequential_importer.Process( m_definition );
3030 std::string Parser::GetArgStr(
int index)
3032 return std::string(m_args[index].start, m_args[index].length);
3035 char Parser::GetArgChar(
int index)
3037 return *(m_args[index].start);
3042 char c = this->GetArgChar(index);
3051 fmt::format(
"Bad arg~{} 'side' (value: {}), parsing as 'l' for backwards compatibility.", index + 1, c));
3056 long Parser::GetArgLong(
int index)
3059 char* out_end =
nullptr;
3060 long res = std::strtol(m_args[index].start, &out_end, 10);
3064 fmt::format(
"Cannot parse argument [{}] as integer, errno: {}", index + 1, errno));
3067 if (out_end == m_args[index].start)
3070 fmt::format(
"Argument [{}] is not valid integer", index + 1));
3073 else if (out_end != (m_args[index].start + m_args[index].length))
3076 fmt::format(
"Integer argument [{}] has invalid trailing characters", index + 1));
3081 int Parser::GetArgInt(
int index)
3083 return static_cast<int>(this->GetArgLong(index));
3088 std::string rigidity_node = this->GetArgStr(index);
3089 if (rigidity_node !=
"9999")
3091 return this->GetArgNodeRef(index);
3098 int p = this->GetArgInt(index);
3108 fmt::format(
"Bad value of param ~{} (propulsion), using 0 (no propulsion)", index + 1));
3115 int b = this->GetArgInt(index);
3127 fmt::format(
"Bad value of param ~{} (braking), using 0 (not braked)", index + 1));
3134 return this->_ParseNodeRef(this->GetArgStr(index));
3139 if (! (Ogre::StringConverter::parseReal(this->GetArgStr(index)) == -1.f))
3141 return this->GetArgNodeRef(index);
3146 unsigned Parser::GetArgUint(
int index)
3148 return static_cast<unsigned>(this->GetArgLong(index));
3153 char in = this->GetArgChar(index);
3174 fmt::format(
"Invalid flare type '{}', falling back to type 'f' (front light)...", in));
3181 std::string str = this->GetArgStr(index);
3187 fmt::format(
"Invalid ExtCameraMode '{}', falling back to type 'classic'...", str));
3191 float Parser::GetArgFloat(
int index)
3193 return (
float) Ogre::StringConverter::parseReal(this->GetArgStr(index), 0.f);
3196 float Parser::ParseArgFloat(
const char* str)
3198 return (
float) Ogre::StringConverter::parseReal(str, 0.f);
3201 float Parser::ParseArgFloat(std::string
const & str)
3203 return this->ParseArgFloat(str.c_str());
3206 unsigned Parser::ParseArgUint(
const char* str)
3209 long res = std::strtol(str,
nullptr, 10);
3213 fmt::format(
"Cannot parse argument '{}' as int, errno: {}", str, errno));
3216 return static_cast<unsigned>(res);
3219 unsigned Parser::ParseArgUint(std::string
const & str)
3221 return this->ParseArgUint(str.c_str());
3224 int Parser::ParseArgInt(
const char* str)
3226 return static_cast<int>(this->ParseArgUint(str));
3229 bool Parser::GetArgBool(
int index)
3231 return Ogre::StringConverter::parseBool(this->GetArgStr(index));
3236 char c = this->GetArgChar(index);
3239 case (
char)WingControlSurface::n_NONE:
3240 case (
char)WingControlSurface::a_RIGHT_AILERON:
3241 case (
char)WingControlSurface::b_LEFT_AILERON:
3242 case (
char)WingControlSurface::f_FLAP:
3243 case (
char)WingControlSurface::e_ELEVATOR:
3244 case (
char)WingControlSurface::r_RUDDER:
3245 case (
char)WingControlSurface::S_RIGHT_HAND_STABILATOR:
3246 case (
char)WingControlSurface::T_LEFT_HAND_STABILATOR:
3247 case (
char)WingControlSurface::c_RIGHT_ELEVON:
3248 case (
char)WingControlSurface::d_LEFT_ELEVON:
3249 case (
char)WingControlSurface::g_RIGHT_FLAPERON:
3250 case (
char)WingControlSurface::h_LEFT_FLAPERON:
3251 case (
char)WingControlSurface::U_RIGHT_HAND_TAILERON:
3252 case (
char)WingControlSurface::V_LEFT_HAND_TAILERON:
3253 case (
char)WingControlSurface::i_RIGHT_RUDDERVATOR:
3254 case (
char)WingControlSurface::j_LEFT_RUDDERVATOR:
3258 fmt::format(
"invalid WingControlSurface '{}', falling back to 'n' (none)", c);
3259 return WingControlSurface::n_NONE;
3263 std::string Parser::GetArgManagedTex(
int index)
3265 std::string tex_name = this->GetArgStr(index);
3266 return (tex_name.at(0) !=
'-') ? tex_name :
"";
3271 switch (this->GetArgStr(index)[0])
3273 case (
char)MinimassOption::l_SKIP_LOADED:
3274 return MinimassOption::l_SKIP_LOADED;
3276 case (
char)MinimassOption::n_DUMMY:
3277 return MinimassOption::n_DUMMY;
3281 fmt::format(
"Not a valid minimass option: {}, falling back to 'n' (dummy)", this->GetArgStr(index)));
3282 return MinimassOption::n_DUMMY;
3289 for (
char c: this->GetArgStr(index))
3293 case (
char)CabOption::n_DUMMY:
break;
3294 case (
char)CabOption::c_CONTACT: ret |= Cab::OPTION_c_CONTACT ;
break;
3295 case (
char)CabOption::b_BUOYANT: ret |= Cab::OPTION_b_BUOYANT ;
break;
3296 case (
char)CabOption::p_10xTOUGHER: ret |= Cab::OPTION_p_10xTOUGHER ;
break;
3297 case (
char)CabOption::u_INVULNERABLE: ret |= Cab::OPTION_u_INVULNERABLE ;
break;
3298 case (
char)CabOption::s_BUOYANT_NO_DRAG: ret |= Cab::OPTION_s_BUOYANT_NO_DRAG ;
break;
3299 case (
char)CabOption::r_BUOYANT_ONLY_DRAG: ret |= Cab::OPTION_r_BUOYANT_ONLY_DRAG ;
break;
3300 case (
char)CabOption::D_CONTACT_BUOYANT: ret |= Cab::OPTION_D_CONTACT_BUOYANT ;
break;
3301 case (
char)CabOption::F_10xTOUGHER_BUOYANT: ret |= Cab::OPTION_F_10xTOUGHER_BUOYANT ;
break;
3302 case (
char)CabOption::S_INVULNERABLE_BUOYANT: ret |= Cab::OPTION_S_INVULNERABLE_BUOYANT;
break;
3315 for (
char c: this->GetArgStr(index))
3319 case (
char)TriggerOption::i_INVISIBLE : ret |= Trigger::OPTION_i_INVISIBLE;
break;
3320 case (
char)TriggerOption::c_COMMAND_STYLE : ret |= Trigger::OPTION_c_COMMAND_STYLE;
break;
3321 case (
char)TriggerOption::x_START_DISABLED : ret |= Trigger::OPTION_x_START_DISABLED;
break;
3322 case (
char)TriggerOption::b_KEY_BLOCKER : ret |= Trigger::OPTION_b_KEY_BLOCKER;
break;
3323 case (
char)TriggerOption::B_TRIGGER_BLOCKER : ret |= Trigger::OPTION_B_TRIGGER_BLOCKER;
break;
3324 case (
char)TriggerOption::A_INV_TRIGGER_BLOCKER: ret |= Trigger::OPTION_A_INV_TRIGGER_BLOCKER;
break;
3325 case (
char)TriggerOption::s_CMD_NUM_SWITCH : ret |= Trigger::OPTION_s_CMD_NUM_SWITCH;
break;
3326 case (
char)TriggerOption::h_UNLOCKS_HOOK_GROUP : ret |= Trigger::OPTION_h_UNLOCKS_HOOK_GROUP;
break;
3327 case (
char)TriggerOption::H_LOCKS_HOOK_GROUP : ret |= Trigger::OPTION_H_LOCKS_HOOK_GROUP;
break;
3328 case (
char)TriggerOption::t_CONTINUOUS : ret |= Trigger::OPTION_t_CONTINUOUS;
break;
3329 case (
char)TriggerOption::E_ENGINE_TRIGGER : ret |= Trigger::OPTION_E_ENGINE_TRIGGER;
break;
3342 for (
char c: this->GetArgStr(index))
3346 case (
char)BeamOption::i_INVISIBLE: ret |= Beam::OPTION_i_INVISIBLE;
break;
3347 case (
char)BeamOption::r_ROPE : ret |= Beam::OPTION_r_ROPE ;
break;
3348 case (
char)BeamOption::s_SUPPORT : ret |= Beam::OPTION_s_SUPPORT ;
break;
3350 case (
char)BeamOption::v_DUMMY:
break;
3363 for (
char c: this->GetArgStr(index))
3367 case (
char)HydroOption::j_INVISIBLE : ret |= Hydro::OPTION_j_INVISIBLE ;
break;
3368 case (
char)HydroOption::s_DISABLE_ON_HIGH_SPEED : ret |= Hydro::OPTION_s_DISABLE_ON_HIGH_SPEED ;
break;
3369 case (
char)HydroOption::a_INPUT_AILERON : ret |= Hydro::OPTION_a_INPUT_AILERON ;
break;
3370 case (
char)HydroOption::r_INPUT_RUDDER : ret |= Hydro::OPTION_r_INPUT_RUDDER ;
break;
3371 case (
char)HydroOption::e_INPUT_ELEVATOR : ret |= Hydro::OPTION_e_INPUT_ELEVATOR ;
break;
3372 case (
char)HydroOption::u_INPUT_AILERON_ELEVATOR : ret |= Hydro::OPTION_u_INPUT_AILERON_ELEVATOR ;
break;
3373 case (
char)HydroOption::v_INPUT_InvAILERON_ELEVATOR: ret |= Hydro::OPTION_v_INPUT_InvAILERON_ELEVATOR;
break;
3374 case (
char)HydroOption::x_INPUT_AILERON_RUDDER : ret |= Hydro::OPTION_x_INPUT_AILERON_RUDDER ;
break;
3375 case (
char)HydroOption::y_INPUT_InvAILERON_RUDDER : ret |= Hydro::OPTION_y_INPUT_InvAILERON_RUDDER ;
break;
3376 case (
char)HydroOption::g_INPUT_ELEVATOR_RUDDER : ret |= Hydro::OPTION_g_INPUT_ELEVATOR_RUDDER ;
break;
3377 case (
char)HydroOption::h_INPUT_InvELEVATOR_RUDDER : ret |= Hydro::OPTION_h_INPUT_InvELEVATOR_RUDDER ;
break;
3378 case (
char)HydroOption::n_INPUT_NORMAL : ret |= Hydro::OPTION_n_INPUT_NORMAL ;
break;
3380 case (
char)HydroOption::i_INVISIBLE_INPUT_NORMAL:
3385 ret |= Hydro::OPTION_n_INPUT_NORMAL;
3387 ret |= Hydro::OPTION_j_INVISIBLE;
3402 for (
char c: this->GetArgStr(index))
3406 case (
char)ShockOption::i_INVISIBLE : ret |= Shock::OPTION_i_INVISIBLE ;
break;
3407 case (
char)ShockOption::L_ACTIVE_LEFT : ret |= Shock::OPTION_L_ACTIVE_LEFT ;
break;
3408 case (
char)ShockOption::R_ACTIVE_RIGHT : ret |= Shock::OPTION_R_ACTIVE_RIGHT;
break;
3409 case (
char)ShockOption::m_METRIC : ret |= Shock::OPTION_m_METRIC ;
break;
3411 case (
char)ShockOption::n_DUMMY:
break;
3412 case (
char)ShockOption::v_DUMMY:
break;
3425 for (
char c: this->GetArgStr(index))
3429 case (
char)Shock2Option::i_INVISIBLE: ret |= Shock2::OPTION_i_INVISIBLE;
break;
3430 case (
char)Shock2Option::s_SOFT_BUMP_BOUNDS: ret |= Shock2::OPTION_s_SOFT_BUMP_BOUNDS;
break;
3431 case (
char)Shock2Option::m_METRIC: ret |= Shock2::OPTION_m_METRIC;
break;
3432 case (
char)Shock2Option::M_ABSOLUTE_METRIC: ret |= Shock2::OPTION_M_ABSOLUTE_METRIC;
break;
3434 case (
char)Shock2Option::n_DUMMY:
break;
3435 case (
char)Shock2Option::v_DUMMY:
break;
3448 for (
char c: this->GetArgStr(index))
3452 case (
char)Shock3Option::i_INVISIBLE: ret |= Shock3::OPTION_i_INVISIBLE;
break;
3453 case (
char)Shock3Option::m_METRIC: ret |= Shock3::OPTION_m_METRIC;
break;
3454 case (
char)Shock3Option::M_ABSOLUTE_METRIC: ret |= Shock3::OPTION_M_ABSOLUTE_METRIC;
break;
3456 case (
char)Shock3Option::n_DUMMY:
break;
3457 case (
char)Shock3Option::v_DUMMY:
break;
3470 for (
char c: this->GetArgStr(index))
3474 case (
char)NodeOption::m_NO_MOUSE_GRAB : ret |= Node::OPTION_m_NO_MOUSE_GRAB ;
break;
3475 case (
char)NodeOption::f_NO_SPARKS : ret |= Node::OPTION_f_NO_SPARKS ;
break;
3476 case (
char)NodeOption::x_EXHAUST_POINT : ret |= Node::OPTION_x_EXHAUST_POINT ;
break;
3477 case (
char)NodeOption::y_EXHAUST_DIRECTION : ret |= Node::OPTION_y_EXHAUST_DIRECTION ;
break;
3478 case (
char)NodeOption::c_NO_GROUND_CONTACT : ret |= Node::OPTION_c_NO_GROUND_CONTACT ;
break;
3479 case (
char)NodeOption::h_HOOK_POINT : ret |= Node::OPTION_h_HOOK_POINT ;
break;
3480 case (
char)NodeOption::e_TERRAIN_EDIT_POINT: ret |= Node::OPTION_e_TERRAIN_EDIT_POINT;
break;
3481 case (
char)NodeOption::b_EXTRA_BUOYANCY : ret |= Node::OPTION_b_EXTRA_BUOYANCY ;
break;
3482 case (
char)NodeOption::p_NO_PARTICLES : ret |= Node::OPTION_p_NO_PARTICLES ;
break;
3483 case (
char)NodeOption::L_LOG : ret |= Node::OPTION_L_LOG ;
break;
3484 case (
char)NodeOption::l_LOAD_WEIGHT : ret |= Node::OPTION_l_LOAD_WEIGHT ;
break;
3486 case (
char)NodeOption::n_DUMMY:
break;
3498 if (str.find(
"leftmirror" ) != std::string::npos) {
return SpecialProp::MIRROR_LEFT; }
3499 if (str.find(
"rightmirror" ) != std::string::npos) {
return SpecialProp::MIRROR_RIGHT; }
3500 if (str.find(
"dashboard-rh") != std::string::npos) {
return SpecialProp::DASHBOARD_RIGHT; }
3501 if (str.find(
"dashboard" ) != std::string::npos) {
return SpecialProp::DASHBOARD_LEFT; }
3502 if (Ogre::StringUtil::startsWith(str,
"spinprop",
false) ) {
return SpecialProp::AERO_PROP_SPIN; }
3503 if (Ogre::StringUtil::startsWith(str,
"pale",
false) ) {
return SpecialProp::AERO_PROP_BLADE; }
3504 if (Ogre::StringUtil::startsWith(str,
"seat",
false) ) {
return SpecialProp::DRIVER_SEAT; }
3505 if (Ogre::StringUtil::startsWith(str,
"seat2",
false) ) {
return SpecialProp::DRIVER_SEAT_2; }
3506 if (Ogre::StringUtil::startsWith(str,
"beacon",
false) ) {
return SpecialProp::BEACON; }
3507 if (Ogre::StringUtil::startsWith(str,
"redbeacon",
false)) {
return SpecialProp::REDBEACON; }
3508 if (Ogre::StringUtil::startsWith(str,
"lightb",
false) ) {
return SpecialProp::LIGHTBAR; }
3509 return SpecialProp::NONE;
3512 int Parser::GetArgDashboardInputDataType(
int index)
3514 std::string str = this->GetArgStr(index);
3515 if (str ==
"bool")
return DC_BOOL;
3516 if (str ==
"int")
return DC_INT;
3517 if (str ==
"float")
return DC_FLOAT;
3518 if (str ==
"string")
return DC_CHAR;
3521 fmt::format(
"Not a valid dashboard input data type: '{}'", str));
3527 char c = this->GetArgChar(index);
3530 case (
char)EngineType::t_TRUCK:
3531 case (
char)EngineType::c_CAR:
3532 case (
char)EngineType::e_ECAR:
3536 fmt::format(
"invalid EngineType '{}', falling back to 't' (truck)", c);
3537 return EngineType::t_TRUCK;
3543 std::string str = this->GetArgStr(index);
3544 if (str ==
"mesh_standard")
return ManagedMaterialType::MESH_STANDARD;
3545 if (str ==
"mesh_transparent")
return ManagedMaterialType::MESH_TRANSPARENT;
3546 if (str ==
"flexmesh_standard")
return ManagedMaterialType::FLEXMESH_STANDARD;
3547 if (str ==
"flexmesh_transparent")
return ManagedMaterialType::FLEXMESH_TRANSPARENT;
3550 fmt::format(
"Not a valid ManagedMaterialType: '{}'", str));
3551 return ManagedMaterialType::INVALID;
3556 int role = this->GetArgInt(index);
3565 fmt::format(
"Invalid value of 'camera role' ({}), videocamera will not work", role));
3570 int Parser::TokenizeCurrentLine()
3573 const char* cur_char = m_current_line;
3575 while ((*cur_char !=
'\0') && (cur_arg < Parser::LINE_MAX_ARGS))
3578 if ((arg_len == 0) && is_arg)
3580 m_args[cur_arg].start = cur_char;
3583 else if ((arg_len > 0) && !is_arg)
3585 m_args[cur_arg].length = arg_len;
3597 m_args[cur_arg].length = arg_len;
3601 m_num_args = cur_arg;
3605 void Parser::ProcessOgreStream(Ogre::DataStream* stream, Ogre::String resource_group)
3607 m_resource_group = resource_group;
3608 m_filename = stream->getName();
3610 char raw_line_buf[LINE_BUFFER_LENGTH];
3611 while (!stream->eof())
3615 stream->readLine(raw_line_buf, LINE_BUFFER_LENGTH - 1);
3616 raw_line_buf[LINE_BUFFER_LENGTH - 1] =
'\0';
3618 catch (Ogre::Exception &ex)
3621 fmt::format(
"Could not read truck file: {}", ex.getFullDescription()));
3625 this->ProcessRawLine(raw_line_buf);
3629 void Parser::ProcessRawLine(
const char* raw_line_buf)
3631 const char* raw_start = raw_line_buf;
3632 const char* raw_end = raw_line_buf +
strnlen(raw_line_buf, LINE_BUFFER_LENGTH);
3635 while (
IsWhitespace(*raw_start) && (raw_start != raw_end))
3641 if (raw_start == raw_end)
3643 ++m_current_line_number;
3648 if ((*raw_start ==
';') || (*raw_start ==
'/'))
3650 m_pending_doc_comment.comment_text += raw_line_buf;
3651 m_pending_doc_comment.comment_text +=
'\n';
3652 ++m_current_line_number;
3657 memset(m_current_line, 0, LINE_BUFFER_LENGTH);
3658 char* out_start = m_current_line;
3659 utf8::replace_invalid(raw_start, raw_end, out_start,
'?');
3662 this->ProcessCurrentLine();
3663 ++m_current_line_number;