RigsofRods
Soft-body Physics Simulation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
AddonPartFileFormat.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-2023 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 
22 #include "AddonPartFileFormat.h"
23 
24 #include "Actor.h"
25 #include "Application.h"
26 #include "CacheSystem.h"
27 #include "Console.h"
28 #include "GameContext.h"
29 #include "GenericFileFormat.h"
30 #include "GUI_MessageBox.h"
31 #include "RigDef_Parser.h"
32 #include "TuneupFileFormat.h"
33 
34 #include <Ogre.h>
35 
36 using namespace RoR;
37 using namespace RigDef;
38 
40  :m_silent_mode(silent_mode)
41 {
42  // Inits `RefCountingObjectPtr<>` (CacheEntryPtr, GenericDocumentPtr) - shouldn't be in header.
43 }
44 
46 {
47  // Destroys `RefCountingObjectPtr<>` (CacheEntryPtr, GenericDocumentPtr) - shouldn't be in header.
48 }
49 
50 std::shared_ptr<Document::Module> AddonPartUtility::TransformToRigDefModule(CacheEntryPtr& entry)
51 {
53  m_addonpart_entry = entry;
54  try
55  {
56  Ogre::DataStreamPtr datastream = Ogre::ResourceGroupManager::getSingleton().openResource(entry->fname, entry->resource_group);
57 
60  m_document->loadFromDataStream(datastream, options);
61 
62  m_module = std::shared_ptr<Document::Module>(new Document::Module(entry->dname));
63  m_module->origin_addonpart = entry;
65  Keyword keyword = Keyword::INVALID;
66  Keyword block = Keyword::INVALID;
67 
68  while (!m_context->endOfFile())
69  {
70  if (m_context->isTokKeyword())
71  {
72  // (ignore 'addonpart_*' directives)
73  if (m_context->getTokKeyword().find("addonpart_") != std::string::npos)
74  {
76  continue;
77  }
78 
79  keyword = Parser::IdentifyKeyword(m_context->getTokKeyword());
80  if (keyword == Keyword::INVALID && m_context->getTokKeyword() == "set_managedmaterials_options")
81  {
82  keyword = Keyword::SET_MANAGEDMATERIALS_OPTIONS; // Workaround, don't ask me why the regex doesn't match this.
83  }
84  if (keyword != Keyword::INVALID)
85  {
86  if (keyword == Keyword::SET_MANAGEDMATERIALS_OPTIONS)
87  {
90  continue;
91  }
92  else if (keyword == Keyword::MANAGEDMATERIALS
93  || keyword == Keyword::PROPS
94  || keyword == Keyword::FLEXBODIES
95  || keyword == Keyword::FLARES
96  || keyword == Keyword::FLARES2)
97  {
98  block = keyword;
100  continue;
101  }
102 
103  }
104  }
105 
106  if (block != Keyword::INVALID && !m_context->isTokComment() && !m_context->isTokLineBreak())
107  {
108  switch (block)
109  {
110  case Keyword::MANAGEDMATERIALS: this->ProcessManagedMaterial(); break;
111  case Keyword::PROPS: this->ProcessProp(); break;
112  case Keyword::FLEXBODIES: this->ProcessFlexbody(); break;
113  case Keyword::FLARES: this->ProcessFlare(); break;
114  case Keyword::FLARES2: this->ProcessFlare2(); break;
115  default: break;
116  }
117  }
118 
120  }
121  return m_module;
122  }
123  catch (Ogre::Exception& e)
124  {
127  fmt::format("Could not use addonpart: Error parsing file '{}', message: {}",
128  entry->fname, e.getFullDescription()));
129  return nullptr;
130  }
131 }
132 
134 {
135  // Evaluates 'addonpart_unwanted_*' directives, respecting 'protected_*' directives in the tuneup.
136  // Also handles 'addonpart_tweak_*' directives, resolving possible conflicts among used addonparts.
137  // ---------------------------------------------------------------------------------------------
138 
139  App::GetCacheSystem()->LoadResource(addonpart_entry);
140  m_addonpart_entry = addonpart_entry;
141  m_tuneup = tuneup;
142 
143  try
144  {
145  Ogre::DataStreamPtr datastream = Ogre::ResourceGroupManager::getSingleton().openResource(addonpart_entry->fname, addonpart_entry->resource_group);
146 
147  m_document = new GenericDocument();
149  m_document->loadFromDataStream(datastream, options);
151 
152  while (!m_context->endOfFile())
153  {
154  if (m_context->isTokKeyword())
155  {
156  if (m_context->getTokKeyword() == "addonpart_unwanted_prop" )
157  this->ProcessUnwantedProp();
158  else if (m_context->getTokKeyword() == "addonpart_unwanted_flexbody" )
159  this->ProcessUnwantedFlexbody();
160  else if (m_context->getTokKeyword() == "addonpart_unwanted_flare" )
161  this->ProcessUnwantedFlare();
162  else if (m_context->getTokKeyword() == "addonpart_unwanted_exhaust" )
163  this->ProcessUnwantedExhaust();
164  else if (m_context->getTokKeyword() == "addonpart_unwanted_managedmaterial")
166  else if (m_context->getTokKeyword() == "addonpart_tweak_wheel")
167  this->ProcessTweakWheel();
168  else if (m_context->getTokKeyword() == "addonpart_tweak_node")
169  this->ProcessTweakNode();
170  else if (m_context->getTokKeyword() == "addonpart_tweak_prop")
171  this->ProcessTweakProp();
172  else if (m_context->getTokKeyword() == "addonpart_tweak_flexbody")
173  this->ProcessTweakFlexbody();
174  else if (m_context->getTokKeyword() == "addonpart_tweak_managedmaterial")
175  this->ProcessTweakManagedMat();
176  else if (m_context->getTokKeyword() == "addonpart_tweak_cinecam")
177  this->ProcessTweakCineCamera();
178  }
179 
181  }
182 
183  }
184  catch (Ogre::Exception& e)
185  {
188  fmt::format("Addonpart unwanted elements check: Error parsing file '{}', message: {}",
189  addonpart_entry->fname, e.getFullDescription()));
190  }
191 }
192 
194 {
195  ROR_ASSERT(tuneup);
196 
197  // Unwanted
198  tuneup->unwanted_flexbodies.clear();
199  tuneup->unwanted_props.clear();
200  tuneup->unwanted_flares.clear();
201 
202  // Tweaked
203  tuneup->node_tweaks.clear();
204  tuneup->cinecam_tweaks.clear();
205  tuneup->wheel_tweaks.clear();
206  tuneup->prop_tweaks.clear();
207  tuneup->flexbody_tweaks.clear();
208 }
209 
210 
211 // Helpers of `TransformToRigDefModule()`, they expect `m_context` to be in position:
212 // These expect `m_context` to be in position:
213 
215 {
216  ManagedMaterial def;
217  int n = m_context->countLineArgs();
218 
219  // Name:
220  def.name = m_context->getStringData(0); // It may be a STRING (if with quotes), or KEYWORD (if without quotes - because it's at start of line).
221 
222  // Type:
223  std::string str = m_context->getTokString(1);
224  if (str == "mesh_standard") def.type = ManagedMaterialType::MESH_STANDARD;
225  if (str == "mesh_transparent") def.type = ManagedMaterialType::MESH_TRANSPARENT;
226  if (str == "flexmesh_standard") def.type = ManagedMaterialType::FLEXMESH_STANDARD;
227  if (str == "flexmesh_transparent") def.type = ManagedMaterialType::FLEXMESH_TRANSPARENT;
228 
229  // Textures:
231  if (n > 3) def.specular_map = m_context->getTokString(3);
232  if (n > 4) def.damaged_diffuse_map = m_context->getTokString(4);
233  // (placeholders)
234  if (def.specular_map == "-") def.specular_map = "";
235  if (def.damaged_diffuse_map == "-") def.damaged_diffuse_map = "";
236 
237  // Options:
239 
240  m_module->managedmaterials.push_back(def);
241 }
242 
244 {
245  int n = m_context->countLineArgs();
246  if (n > 1)
247  {
249  }
250 }
251 
253 {
254  RigDef::Prop def;
255  int n = m_context->countLineArgs();
256  if (n < 10)
257  {
260  fmt::format("Error parsing addonpart file '{}': 'install_prop' has only {} arguments, expected {}",
261  m_addonpart_entry->fname, n, 10));
262  return;
263  }
264 
265  int importflags = Node::Ref::REGULAR_STATE_IS_VALID | Node::Ref::REGULAR_STATE_IS_NUMBERED;
266  def.reference_node = Node::Ref("", (unsigned int)m_context->getTokFloat(0), importflags, 0);
267  def.x_axis_node = Node::Ref("", (unsigned int)m_context->getTokFloat(1), importflags, 0);
268  def.y_axis_node = Node::Ref("", (unsigned int)m_context->getTokFloat(2), importflags, 0);
269 
270  def.offset.x = m_context->getTokNumeric(3);
271  def.offset.y = m_context->getTokNumeric(4);
272  def.offset.z = m_context->getTokNumeric(5);
273 
274  def.rotation.x = m_context->getTokNumeric(6);
275  def.rotation.y = m_context->getTokNumeric(7);
276  def.rotation.z = m_context->getTokNumeric(8);
277 
278  def.mesh_name = m_context->getTokString(9);
280 
281  switch (def.special)
282  {
283  case SpecialProp::BEACON:
284  if (n >= 14)
285  {
287  Ogre::StringUtil::trim(def.special_prop_beacon.flare_material_name);
288 
289  def.special_prop_beacon.color = Ogre::ColourValue(
291  }
292  break;
293 
294  case SpecialProp::DASHBOARD_LEFT:
295  case SpecialProp::DASHBOARD_RIGHT:
296  if (n > 10)
297  {
299  }
300  if (n > 13)
301  {
304  }
305  if (n > 14)
306  {
308  }
309  break;
310 
311  default:
312  break;
313  }
314 
315  m_module->props.push_back(def);
316 }
317 
319 {
320  Flexbody def;
321  int n = m_context->countLineArgs();
322  if (n < 10)
323  {
326  fmt::format("Error parsing addonpart file '{}': flexbody has only {} arguments, expected {}", m_addonpart_entry->fname, n, 10));
327  return;
328  }
329 
330  int importflags = Node::Ref::REGULAR_STATE_IS_VALID | Node::Ref::REGULAR_STATE_IS_NUMBERED;
331  def.reference_node = Node::Ref("", (unsigned int)m_context->getTokInt(0), importflags, 0);
332  def.x_axis_node = Node::Ref("", (unsigned int)m_context->getTokInt(1), importflags, 0);
333  def.y_axis_node = Node::Ref("", (unsigned int)m_context->getTokInt(2), importflags, 0);
334 
335  def.offset.x = m_context->getTokNumeric(3);
336  def.offset.y = m_context->getTokNumeric(4);
337  def.offset.z = m_context->getTokNumeric(5);
338 
339  def.rotation.x = m_context->getTokNumeric(6);
340  def.rotation.y = m_context->getTokNumeric(7);
341  def.rotation.z = m_context->getTokNumeric(8);
342 
343  def.mesh_name = m_context->getTokString(9);
344 
346 
347  if (!m_context->isTokString())
348  {
351  fmt::format("Error parsing addonpart file '{}': flexbody is not followed by 'forset'!", m_addonpart_entry->fname));
352  return;
353  }
354 
355  Parser::ProcessForsetLine(def, m_context->getTokString());
356 
357  // Resolve `forset` ranges:
358  for (RigDef::Node::Range const& range: def.node_list_to_import)
359  {
360  for (unsigned int i = range.start.Num(); i <= range.end.Num(); ++i)
361  {
362  Node::Ref ref("", i, Node::Ref::REGULAR_STATE_IS_VALID | Node::Ref::REGULAR_STATE_IS_NUMBERED, 0);
363  def.node_list.push_back(ref);
364  }
365  }
366 
367  m_module->flexbodies.push_back(def);
368 }
369 
371 {
372  int n = m_context->countLineArgs();
373  if (n < 5)
374  {
377  fmt::format("Error parsing addonpart file '{}': flare has only {} arguments, expected {}", m_addonpart_entry->fname, n, 5));
378  return;
379  }
380 
381  Flare2 def; // We auto-import 'flares' as 'flares2', leaving the `offset.z` at 1.
382  int importflags = Node::Ref::REGULAR_STATE_IS_VALID | Node::Ref::REGULAR_STATE_IS_NUMBERED;
383  def.reference_node = Node::Ref("", (unsigned int)m_context->getTokInt(0), importflags, 0);
384  def.node_axis_x = Node::Ref("", (unsigned int)m_context->getTokInt(1), importflags, 0);
385  def.node_axis_y = Node::Ref("", (unsigned int)m_context->getTokInt(2), importflags, 0);
386  def.offset.x = m_context->getTokNumeric(3);
387  def.offset.y = m_context->getTokNumeric(4);
388 
389  if (n > 5) def.type = (FlareType)m_context->getTokString(5)[0];
390 
391  if (n > 6)
392  {
393  switch (def.type)
394  {
395  case FlareType::USER: def.control_number = m_context->getTokInt(6); break;
397  default: break;
398  }
399  }
400 
401  if (n > 7) { def.blink_delay_milis = m_context->getTokInt(7); }
402  if (n > 8) { def.size = m_context->getTokNumeric(8); }
403  if (n > 9) { def.material_name = m_context->getTokString(9); }
404 
405  m_module->flares2.push_back(def);
406 }
407 
409 {
410  int n = m_context->countLineArgs();
411  if (n < 6)
412  {
415  fmt::format("Error parsing addonpart file '{}': flare2 has only {} arguments, expected {}", m_addonpart_entry->fname, n, 6));
416  return;
417  }
418 
419  Flare2 def;
420  int importflags = Node::Ref::REGULAR_STATE_IS_VALID | Node::Ref::REGULAR_STATE_IS_NUMBERED;
421  def.reference_node = Node::Ref("", (unsigned int)m_context->getTokInt(0), importflags, 0);
422  def.node_axis_x = Node::Ref("", (unsigned int)m_context->getTokInt(1), importflags, 0);
423  def.node_axis_y = Node::Ref("", (unsigned int)m_context->getTokInt(2), importflags, 0);
424  def.offset.x = m_context->getTokNumeric(3);
425  def.offset.y = m_context->getTokNumeric(4);
426  def.offset.z = m_context->getTokNumeric(5); // <-- Specific to 'flares2' (the only difference)
427 
428  if (n > 6) def.type = (FlareType)m_context->getTokString(6)[0];
429 
430  if (n > 7)
431  {
432  switch (def.type)
433  {
434  case FlareType::USER: def.control_number = m_context->getTokInt(7); break;
436  default: break;
437  }
438  }
439 
440  if (n > 8) { def.blink_delay_milis = m_context->getTokInt(8); }
441  if (n > 9) { def.size = m_context->getTokNumeric(9); }
442  if (n > 10) { def.material_name = m_context->getTokString(10); }
443 
444  m_module->flares2.push_back(def);
445 }
446 
447 // Helpers of `ResolveUnwantedAndTweakedElements()`, they expect `m_context` to be in position:
448 
450 {
451  ROR_ASSERT(m_context->getTokKeyword() == "addonpart_unwanted_prop"); // also asserts !EOF and TokenType::KEYWORD
452 
453  if (m_context->isTokInt(1))
454  {
456  {
458  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': marking prop '{}' as UNWANTED",
460  }
461  else
462  {
463  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': skipping prop '{}' because it's marked PROTECTED",
465  }
466  }
467  else
468  {
469  this->Log(fmt::format("[RoR|Addonpart] WARNING: file '{}', directive '{}': bad arguments", m_addonpart_entry->fname, m_context->getTokKeyword()));
470  }
471 }
472 
474 {
475  ROR_ASSERT(m_context->getTokKeyword() == "addonpart_unwanted_flexbody"); // also asserts !EOF and TokenType::KEYWORD
476 
477  if (m_context->isTokInt(1))
478  {
480  {
482  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': marking flexbody '{}' as UNWANTED",
484  }
485  else
486  {
487  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': skipping flexbody '{}' because it's marked PROTECTED",
489  }
490  }
491  else
492  {
493  this->Log(fmt::format("[RoR|Addonpart] WARNING: file '{}', directive '{}': bad arguments", m_addonpart_entry->fname, m_context->getTokKeyword()));
494  }
495 }
496 
498 {
499  ROR_ASSERT(m_context->getTokKeyword() == "addonpart_unwanted_flare"); // also asserts !EOF and TokenType::KEYWORD
500 
501  if (m_context->isTokInt(1))
502  {
504  {
506  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': marking flare '{}' as UNWANTED",
508  }
509  else
510  {
511  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': skipping flare '{}' because it's marked PROTECTED",
513  }
514  }
515  else
516  {
517  this->Log(fmt::format("[RoR|Addonpart] WARNING: file '{}', directive '{}': bad arguments", m_addonpart_entry->fname, m_context->getTokKeyword()));
518  }
519 }
520 
522 {
523  ROR_ASSERT(m_context->getTokKeyword() == "addonpart_unwanted_exhaust"); // also asserts !EOF and TokenType::KEYWORD
524 
525  if (m_context->isTokInt(1))
526  {
528  {
530  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': marking exhaust '{}' as UNWANTED",
532  }
533  else
534  {
535  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': skipping exhaust '{}' because it's marked PROTECTED",
537  }
538  }
539  else
540  {
541  this->Log(fmt::format("[RoR|Addonpart] WARNING: file '{}', directive '{}': bad arguments", m_addonpart_entry->fname, m_context->getTokKeyword()));
542  }
543 }
544 
546 {
547  ROR_ASSERT(m_context->getTokKeyword() == "addonpart_unwanted_managedmaterial"); // also asserts !EOF and TokenType::KEYWORD
548 
549  if (m_context->isTokString(1))
550  {
551  std::string mat_name = m_context->getTokString(1);
552  if (!m_tuneup->isManagedMatProtected(mat_name))
553  {
554  m_tuneup->unwanted_managedmats.insert(mat_name);
555  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': marking managedmaterial '{}' as UNWANTED",
557  }
558  else
559  {
560  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': skipping managedmaterial '{}' because it's marked PROTECTED",
562  }
563  }
564  else
565  {
566  this->Log(fmt::format("[RoR|Addonpart] WARNING: file '{}', directive '{}': bad arguments", m_addonpart_entry->fname, m_context->getTokKeyword()));
567  }
568 }
569 
571 {
572  ROR_ASSERT(m_context->getTokKeyword() == "addonpart_tweak_wheel"); // also asserts !EOF and TokenType::KEYWORD
573 
574  if (m_context->isTokInt(1) && m_context->isTokString(2))
575  {
576  const int wheel_id = m_context->getTokInt(1);
577  if (!m_tuneup->isWheelProtected(wheel_id))
578  {
579  if (m_tuneup->wheel_tweaks.find(wheel_id) == m_tuneup->wheel_tweaks.end())
580  {
581  TuneupWheelTweak data;
582  bool stop = false;
584  data.twt_wheel_id = wheel_id;
585  data.twt_media[0] = m_context->getTokString(2);
586  if (!stop && m_context->isTokString(3)) { data.twt_media[1] = m_context->getTokString(3); } else { stop=true; }
587  if (!stop && m_context->isTokString(4)) { data.twt_side = (m_context->getTokString(4)[0] == 'l') ? WheelSide::LEFT : WheelSide::RIGHT; } else { stop=true; }
588  if (!stop && m_context->isTokFloat(5)) { data.twt_tire_radius = m_context->getTokFloat(5); } else { stop=true; }
589  if (!stop && m_context->isTokFloat(6)) { data.twt_rim_radius = m_context->getTokFloat(6); } else { stop=true; }
590  m_tuneup->wheel_tweaks.insert(std::make_pair(wheel_id, data));
591 
592  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': Sheduling tweak for wheel '{}'"
593  " with params {{ media1={}, media2={}, side={}, tire_radius={}, rim_radius={} }}",
595  data.twt_media[0], data.twt_media[1], (char)data.twt_side, data.twt_tire_radius, data.twt_rim_radius));
596  }
597  else if (m_tuneup->wheel_tweaks[wheel_id].twt_origin != m_addonpart_entry->fname)
598  {
599  this->Log(fmt::format("[RoR|Addonpart] WARNING: file '{}', directive '{}': Resetting tweaks for wheel '{}' due to conflict with '{}'",
601  m_tuneup->wheel_tweaks[wheel_id].twt_origin));
602 
603  m_tuneup->wheel_tweaks.erase(wheel_id);
604  }
605  }
606  else
607  {
608  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': skipping wheel '{}' because it's marked PROTECTED",
610  }
611  }
612  else
613  {
614  this->Log(fmt::format("[RoR|Addonpart] WARNING: file '{}', directive '{}': bad arguments", m_addonpart_entry->fname, m_context->getTokKeyword()));
615  }
616 }
617 
619 {
620  ROR_ASSERT(m_context->getTokKeyword() == "addonpart_tweak_node"); // also asserts !EOF and TokenType::KEYWORD
621 
623  {
624  NodeNum_t nodenum = (NodeNum_t)m_context->getTokInt(1);
625  if (!m_tuneup->isNodeProtected(nodenum))
626  {
627  if (m_tuneup->node_tweaks.find(nodenum) == m_tuneup->node_tweaks.end())
628  {
629  TuneupNodeTweak data;
631  data.tnt_nodenum = nodenum;
632  data.tnt_pos.x = m_context->getTokNumeric(2);
633  data.tnt_pos.y = m_context->getTokNumeric(3);
634  data.tnt_pos.z = m_context->getTokNumeric(4);
635  m_tuneup->node_tweaks.insert(std::make_pair(nodenum, data));
636 
637  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': Scheduling tweak for node '{}'"
638  " with params {{ x={}, y={}, z={} }}",
640  data.tnt_pos.x, data.tnt_pos.y, data.tnt_pos.z));
641  }
642  else if (m_tuneup->node_tweaks[nodenum].tnt_origin != m_addonpart_entry->fname)
643  {
644  this->Log(fmt::format("[RoR|Addonpart] WARNING: file '{}', directive '{}': Resetting tweaks for node '{}' due to conflict with '{}'",
646  m_tuneup->node_tweaks[nodenum].tnt_origin));
647 
648  m_tuneup->node_tweaks.erase(nodenum);
649  }
650  }
651  else
652  {
653  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': skipping node '{}' because it's marked PROTECTED",
655  }
656  }
657  else
658  {
659  this->Log(fmt::format("[RoR|Addonpart] WARNING: file '{}', directive '{}': bad arguments", m_addonpart_entry->fname, m_context->getTokKeyword()));
660  }
661 }
662 
664 {
665  ROR_ASSERT(m_context->getTokKeyword() == "addonpart_tweak_cinecam"); // also asserts !EOF and TokenType::KEYWORD
666 
668  {
670  if (!m_tuneup->isCineCameraProtected(cinecamid))
671  {
672  if (m_tuneup->cinecam_tweaks.find(cinecamid) == m_tuneup->cinecam_tweaks.end())
673  {
676  data.tct_cinecam_id = cinecamid;
677  data.tct_pos.x = m_context->getTokNumeric(2);
678  data.tct_pos.y = m_context->getTokNumeric(3);
679  data.tct_pos.z = m_context->getTokNumeric(4);
680  m_tuneup->cinecam_tweaks.insert(std::make_pair(cinecamid, data));
681 
682  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': Scheduling tweak for cinecam '{}'"
683  " with params {{ x={}, y={}, z={} }}",
685  data.tct_pos.x, data.tct_pos.y, data.tct_pos.z));
686  }
687  else if (m_tuneup->cinecam_tweaks[cinecamid].tct_origin != m_addonpart_entry->fname)
688  {
689  this->Log(fmt::format("[RoR|Addonpart] WARNING: file '{}', directive '{}': Resetting tweaks for cinecam '{}' due to conflict with '{}'",
691  m_tuneup->cinecam_tweaks[cinecamid].tct_origin));
692 
693  m_tuneup->cinecam_tweaks.erase(cinecamid);
694  }
695  }
696  else
697  {
698  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': skipping cinecam '{}' because it's marked PROTECTED",
700  }
701  }
702  else
703  {
704  this->Log(fmt::format("[RoR|Addonpart] WARNING: file '{}', directive '{}': bad arguments", m_addonpart_entry->fname, m_context->getTokKeyword()));
705  }
706 }
707 
709 {
710  ROR_ASSERT(m_context->getTokKeyword() == "addonpart_tweak_flexbody"); // also asserts !EOF and TokenType::KEYWORD
711 
712  // TBD: add `null` token type to GenericDocument, so these params can be made optional
713  if (m_context->isTokInt(1) && // ID
714  m_context->isTokNumeric(2) && m_context->isTokNumeric(3) && m_context->isTokNumeric(4) && // offset
715  m_context->isTokNumeric(5) && m_context->isTokNumeric(6) && m_context->isTokNumeric(7) && // rotation
716  m_context->isTokString(8)) // media
717  {
718  const int flexbody_id = m_context->getTokInt(1);
719  if (!m_tuneup->isFlexbodyProtected(flexbody_id))
720  {
721  if (m_tuneup->flexbody_tweaks.find(flexbody_id) == m_tuneup->flexbody_tweaks.end())
722  {
723  TuneupFlexbodyTweak data;
725  data.tft_flexbody_id = flexbody_id;
726  data.tft_offset.x = m_context->getTokNumeric(2);
727  data.tft_offset.y = m_context->getTokNumeric(3);
728  data.tft_offset.z = m_context->getTokNumeric(4);
729  data.tft_rotation.x = m_context->getTokNumeric(5);
730  data.tft_rotation.y = m_context->getTokNumeric(6);
731  data.tft_rotation.z = m_context->getTokNumeric(7);
732  data.tft_media = m_context->getTokString(8);
733  m_tuneup->flexbody_tweaks.insert(std::make_pair(flexbody_id, data));
734 
735  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': Scheduling tweak for flexbody '{}'"
736  " with params {{ offsetX={}, offsetY={}, offsetZ={}, rotX={}, rotY={}, rotZ={}, media={} }}",
737  m_addonpart_entry->fname, m_context->getTokKeyword(), flexbody_id,
738  data.tft_offset.x, data.tft_offset.y, data.tft_offset.z,
739  data.tft_rotation.x, data.tft_rotation.y, data.tft_rotation.z, data.tft_media[0]));
740  }
741  else if (m_tuneup->flexbody_tweaks[flexbody_id].tft_origin != m_addonpart_entry->fname)
742  {
743  this->Log(fmt::format("[RoR|Addonpart] WARNING: file '{}', directive '{}': Resetting tweaks for flexbody '{}' due to conflict with '{}'",
745  m_tuneup->flexbody_tweaks[flexbody_id].tft_origin));
746 
747  m_tuneup->flexbody_tweaks.erase(flexbody_id);
748  }
749  }
750  else
751  {
752  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': skipping flexbody '{}' because it's marked PROTECTED",
754  }
755  }
756  else
757  {
758  this->Log(fmt::format("[RoR|Addonpart] WARNING: file '{}', directive '{}': bad arguments", m_addonpart_entry->fname, m_context->getTokKeyword()));
759  }
760 }
761 
763 {
764  ROR_ASSERT(m_context->getTokKeyword() == "addonpart_tweak_prop"); // also asserts !EOF and TokenType::KEYWORD
765 
766  // TBD: add `null` token type to GenericDocument, so these params can be made optional
767  if (m_context->isTokInt(1) && // ID
768  m_context->isTokNumeric(2) && m_context->isTokNumeric(3) && m_context->isTokNumeric(4) && // offset
769  m_context->isTokNumeric(5) && m_context->isTokNumeric(6) && m_context->isTokNumeric(7) && // rotation
770  m_context->isTokString(8)) // media
771  {
772  const int prop_id = m_context->getTokInt(1);
773  if (!m_tuneup->isPropProtected(prop_id))
774  {
775  if (m_tuneup->prop_tweaks.find(prop_id) == m_tuneup->prop_tweaks.end())
776  {
777  TuneupPropTweak data;
779  data.tpt_prop_id = prop_id;
780 
781  data.tpt_offset.x = m_context->getTokNumeric(2);
782  data.tpt_offset.y = m_context->getTokNumeric(3);
783  data.tpt_offset.z = m_context->getTokNumeric(4);
784  data.tpt_rotation.x = m_context->getTokNumeric(5);
785  data.tpt_rotation.y = m_context->getTokNumeric(6);
786  data.tpt_rotation.z = m_context->getTokNumeric(7);
787  data.tpt_media[0] = m_context->getTokString(8);
788  if (m_context->isTokString(9)) data.tpt_media[1] = m_context->getTokString(9); // <== Optional Media2 is specific for prop
789  m_tuneup->prop_tweaks.insert(std::make_pair(prop_id, data));
790 
791  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': Scheduling tweak for prop '{}'"
792  " with params {{ media1={}, offsetX={}, offsetY={}, offsetZ={}, rotX={}, rotY={}, rotZ={}, media2={} }}",
793  m_addonpart_entry->fname, m_context->getTokKeyword(), prop_id, data.tpt_media[0],
794  data.tpt_offset.x, data.tpt_offset.y, data.tpt_offset.z,
795  data.tpt_rotation.x, data.tpt_rotation.y, data.tpt_rotation.z,
796  data.tpt_media[1]));
797  }
798  else if (m_tuneup->prop_tweaks[prop_id].tpt_origin != m_addonpart_entry->fname)
799  {
800  this->Log(fmt::format("[RoR|Addonpart] WARNING: file '{}', directive '{}': Resetting tweaks for prop '{}' due to conflict with '{}'",
802  m_tuneup->prop_tweaks[prop_id].tpt_origin));
803 
804  m_tuneup->prop_tweaks.erase(prop_id);
805  }
806  }
807  else
808  {
809  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': skipping prop '{}' because it's marked PROTECTED",
811  }
812  }
813  else
814  {
815  this->Log(fmt::format("[RoR|Addonpart] WARNING: file '{}', directive '{}': bad arguments", m_addonpart_entry->fname, m_context->getTokKeyword()));
816  }
817 }
818 
820 {
821  ROR_ASSERT(m_context->getTokKeyword() == "addonpart_tweak_managedmaterial"); // also asserts !EOF and TokenType::KEYWORD
822 
824  {
825  const std::string& mat_name = m_context->getTokString(1);
826  if (!m_tuneup->isManagedMatProtected(mat_name))
827  {
828  if (m_tuneup->managedmat_tweaks.find(mat_name) == m_tuneup->managedmat_tweaks.end())
829  {
831  bool stop=false;
833  data.tmt_name = mat_name;
834  data.tmt_type = m_context->getTokString(2);
835  if (!stop && m_context->isTokString(3)) { data.tmt_media[0] = m_context->getTokString(3); } else {stop=true;}
836  if (!stop && m_context->isTokString(4)) { data.tmt_media[1] = m_context->getTokString(4); } else {stop=true;}
837  if (!stop && m_context->isTokString(5)) { data.tmt_media[2] = m_context->getTokString(5); } else {stop=true;}
838  m_tuneup->managedmat_tweaks.insert(std::make_pair(mat_name, data));
839 
840  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': Scheduling tweak for managed material '{}'"
841  " with params {{ type={}, media1={}, media2={}, media3={} }}",
842  m_addonpart_entry->fname, m_context->getTokKeyword(), mat_name, data.tmt_type, data.tmt_media[0], data.tmt_media[1], data.tmt_media[2]));
843  }
844  else if (m_tuneup->managedmat_tweaks[mat_name].tmt_origin != m_addonpart_entry->fname)
845  {
846  this->Log(fmt::format("[RoR|Addonpart] WARNING: file '{}', directive '{}': Resetting tweaks for managed material '{}' due to conflict with '{}'",
848  m_tuneup->managedmat_tweaks[mat_name].tmt_origin));
849 
850  m_tuneup->managedmat_tweaks.erase(mat_name);
851  }
852  }
853  else
854  {
855  this->Log(fmt::format("[RoR|Addonpart] INFO: file '{}', directive '{}': skipping managed material '{}' because it's marked PROTECTED",
857  }
858  }
859 }
860 
862 {
863  LOG(fmt::format("[RoR|Addonpart] -- Performing `RecordAddonpartConflicts()` between '{}' and '{}' ~ this involves generating dummy tuneups (hence messages below) --", addonpart1->fname, addonpart2->fname));
864 
865  // Make sure both addonparts are loaded and cached.
866  App::GetCacheSystem()->LoadResource(addonpart1);
867  if (!addonpart1->addonpart_data_only)
868  {
869  addonpart1->addonpart_data_only = new TuneupDef();
870  AddonPartUtility util(/*silent mode:*/true);
871  util.ResolveUnwantedAndTweakedElements(addonpart1->addonpart_data_only, addonpart1);
872  }
873 
874  App::GetCacheSystem()->LoadResource(addonpart2);
875  if (!addonpart2->addonpart_data_only)
876  {
877  addonpart2->addonpart_data_only = new TuneupDef();
878  AddonPartUtility util(/*silent mode:*/true);
879  util.ResolveUnwantedAndTweakedElements(addonpart2->addonpart_data_only, addonpart2);
880  }
881 
882  // NODE TWEAKS:
883  for (auto& i_pair: addonpart1->addonpart_data_only->node_tweaks)
884  {
885  NodeNum_t suspect = i_pair.second.tnt_nodenum;
886  TuneupNodeTweak* offender = nullptr;
887  if (TuneupUtil::isNodeTweaked(addonpart2->addonpart_data_only, suspect, offender))
888  {
889  conflicts.push_back(AddonPartConflict{addonpart1, addonpart2, "addonpart_tweak_node", (int)suspect});
890  LOG(fmt::format("[RoR|Addonpart] Found conflict between '{}' and '{}' - node {} is tweaked by both", addonpart1->fname, addonpart2->fname, (int)suspect));
891  }
892  }
893 
894  // WHEEL TWEAKS:
895  for (auto& i_pair: addonpart1->addonpart_data_only->wheel_tweaks)
896  {
897  WheelID_t suspect = i_pair.second.twt_wheel_id;
898  TuneupWheelTweak* offender = nullptr;
899  if (TuneupUtil::isWheelTweaked(addonpart2->addonpart_data_only, suspect, offender))
900  {
901  conflicts.push_back(AddonPartConflict{addonpart1, addonpart2, "addonpart_tweak_wheel", (int)suspect});
902  LOG(fmt::format("[RoR|Addonpart] Found conflict between '{}' and '{}' - wheel {} is tweaked by both", addonpart1->fname, addonpart2->fname, (int)suspect));
903  }
904  }
905 
906  // PROP TWEAKS:
907  for (auto& i_pair:addonpart1->addonpart_data_only->prop_tweaks)
908  {
909  PropID_t suspect = i_pair.second.tpt_prop_id;
910  TuneupPropTweak* offender = nullptr;
911  if (TuneupUtil::isPropTweaked(addonpart2->addonpart_data_only, suspect, offender))
912  {
913  conflicts.push_back(AddonPartConflict{addonpart1, addonpart2, "addonpart_tweak_prop", (int)suspect});
914  LOG(fmt::format("[RoR|Addonpart] Found conflict between '{}' and '{}' - prop {} is tweaked by both", addonpart1->fname, addonpart2->fname, (int)suspect));
915  }
916  }
917 
918  // FLEXBODY TWEAKS:
919  for (auto& i_pair: addonpart1->addonpart_data_only->flexbody_tweaks)
920  {
921  FlexbodyID_t suspect = i_pair.second.tft_flexbody_id;
922  TuneupFlexbodyTweak* offender = nullptr;
923  if (TuneupUtil::isFlexbodyTweaked(addonpart2->addonpart_data_only, suspect, offender))
924  {
925  conflicts.push_back(AddonPartConflict{addonpart1, addonpart2, "addonpart_tweak_flexbody", (int)suspect});
926  LOG(fmt::format("[RoR|Addonpart] Found conflict between '{}' and '{}' - flexbody {} is tweaked by both", addonpart1->fname, addonpart2->fname, (int)suspect));
927  }
928  }
929 
930  LOG(fmt::format("[RoR|Addonpart] -- Done with `RecordAddonpartConflicts()` between '{}' and '{}' --", addonpart1->fname, addonpart2->fname));
931 }
932 
934 {
935  if (!addonpart1 || !addonpart2)
936  {
937  return false;
938  }
939 
940  for (AddonPartConflict& conflict: conflicts)
941  {
942  if ((conflict.atc_addonpart1 == addonpart1 && conflict.atc_addonpart2 == addonpart2) ||
943  (conflict.atc_addonpart1 == addonpart2 && conflict.atc_addonpart2 == addonpart1))
944  {
945  return true;
946  }
947  }
948  return false;
949 }
950 
951 void AddonPartUtility::Log(const std::string& text)
952 {
953  if (!m_silent_mode)
954  {
955  LOG(text);
956  }
957 }
958 
960 {
961  // Re-check conflicts (request may come from 'Browse all' button or script).
962  // -------------------------------------------------------------------------
963 
964  AddonPartConflictVec conflicts;
965  for (const std::string& use_addonpart: target_actor->getWorkingTuneupDef()->use_addonparts)
966  {
967  CacheEntryPtr use_entry = App::GetCacheSystem()->FindEntryByFilename(LT_AddonPart, /*partial=*/false, use_addonpart);
968  AddonPartUtility::RecordAddonpartConflicts(addonpart_entry, use_entry, conflicts);
969  }
970 
971  if (conflicts.size() > 0)
972  {
973  // Messagebox text
975  dialog->mbc_content_width = 700.f;
976  dialog->mbc_title = _LC("Tuning", "Cannot install addon part, conflicts were detected.");
977  dialog->mbc_text = fmt::format(_LC("Tuning", "Requested addon part: '{}' (file '{}')."), addonpart_entry->dname, addonpart_entry->fname);
978  dialog->mbc_text += "\n";
979  dialog->mbc_text += fmt::format(_LC("Tuning", "Total conflicts: {}."), conflicts.size());
980  dialog->mbc_text += "\n";
981  for (size_t i=0; i < conflicts.size(); i++)
982  {
983  dialog->mbc_text += "\n";
984  dialog->mbc_text += fmt::format(_LC("Tuning", "[{}/{}] '{}' (file '{}') conflicts with '{}' #{}."),
985  i+1, conflicts.size(),
986  conflicts[i].atc_addonpart2->dname, conflicts[i].atc_addonpart2->fname,
987  conflicts[i].atc_keyword, conflicts[i].atc_element_id);
988  }
989 
990  // Messagebox OK button
991  GUI::MessageBoxButton ok_btn;
992  ok_btn.mbb_caption = _LC("Tuning", "OK");
994  dialog->mbc_buttons.push_back(ok_btn);
995 
996  // Show the messagebox
998  }
999  return conflicts.size() > 0;
1000 }
RoR::TuneupDef
Dual purpose:
Definition: TuneupFileFormat.h:100
RoR::GUI::MessageBoxConfig::mbc_buttons
std::vector< MessageBoxButton > mbc_buttons
Definition: GUI_MessageBox.h:59
ROR_ASSERT
#define ROR_ASSERT(_EXPR)
Definition: Application.h:40
GameContext.h
Game state manager and message-queue provider.
RoR::AddonPartUtility::ResolveUnwantedAndTweakedElements
void ResolveUnwantedAndTweakedElements(TuneupDefPtr &tuneup, CacheEntryPtr &addonpart_entry)
Evaluates 'addonpart_unwanted_*' elements, respecting 'protected_*' directives in the tuneup.
Definition: AddonPartFileFormat.cpp:133
RoR::AddonPartUtility::m_module
std::shared_ptr< RigDef::Document::Module > m_module
Definition: AddonPartFileFormat.h:107
RoR::MSG_GUI_SHOW_MESSAGE_BOX_REQUESTED
@ MSG_GUI_SHOW_MESSAGE_BOX_REQUESTED
Payload = MessageBoxConfig* (owner)
Definition: Application.h:142
RoR::AddonPartUtility::m_document
GenericDocumentPtr m_document
Definition: AddonPartFileFormat.h:103
RigDef::Prop::DashboardSpecial::offset
Ogre::Vector3 offset
Definition: RigDef_File.h:970
RoR::TuneupWheelTweak::twt_origin
std::string twt_origin
Addonpart filename.
Definition: TuneupFileFormat.h:67
RoR::CacheEntry::dname
Ogre::String dname
name parsed from the file
Definition: CacheSystem.h:70
RigDef::Node::Ref
Legacy parser resolved references on-the-fly and the condition to check named nodes was "are there an...
Definition: RigDef_Node.h:77
RigDef::Prop
Definition: RigDef_File.h:959
RoR::TuneupNodeTweak::tnt_nodenum
NodeNum_t tnt_nodenum
Arg#1, required.
Definition: TuneupFileFormat.h:46
RoR::GenericDocContext::isTokInt
bool isTokInt(int offset=0) const
Definition: GenericFileFormat.h:123
RigDef::Prop::offset
Ogre::Vector3 offset
Definition: RigDef_File.h:990
RoR::TuneupUtil::isWheelTweaked
static bool isWheelTweaked(TuneupDefPtr &tuneup_entry, WheelID_t wheel_id, TuneupWheelTweak *&out_tweak)
Definition: TuneupFileFormat.cpp:233
RoR::TuneupDef::isManagedMatProtected
bool isManagedMatProtected(const std::string &matname) const
Definition: TuneupFileFormat.h:166
RoR::TuneupWheelTweak::twt_tire_radius
float twt_tire_radius
Arg#5, optional.
Definition: TuneupFileFormat.h:65
RigDef::ManagedMaterial::diffuse_map
Ogre::String diffuse_map
Definition: RigDef_File.h:905
RigDef::Flare2::type
RoR::FlareType type
Definition: RigDef_File.h:744
RoR::TuneupDef::unwanted_props
std::set< PropID_t > unwanted_props
'addonpart_unwanted_prop' directives.
Definition: TuneupFileFormat.h:124
RoR::LT_AddonPart
@ LT_AddonPart
Definition: Application.h:470
RoR::TuneupPropTweak
< Data of 'addonpart_tweak_prop <prop ID> <offsetX> <offsetY> <offsetZ> <rotX> <rotY> <rotZ> <media1>...
Definition: TuneupFileFormat.h:71
RoR::TuneupWheelTweak::twt_rim_radius
float twt_rim_radius
Arg#6, optional, only applies to some wheel types.
Definition: TuneupFileFormat.h:66
RoR::TuneupFlexbodyTweak::tft_rotation
Ogre::Vector3 tft_rotation
Definition: TuneupFileFormat.h:85
RoR::GenericDocContext::getTokNumeric
float getTokNumeric(int offset=0) const
Definition: GenericFileFormat.h:116
RoR::GenericDocContext::isTokKeyword
bool isTokKeyword(int offset=0) const
Definition: GenericFileFormat.h:125
GUI_MessageBox.h
Generic UI dialog (not modal). Invocable from scripting. Any number of buttons. Configurable to fire ...
RigDef::Node::Range::start
Node::Ref start
Definition: RigDef_Node.h:134
RoR::AddonPartUtility::ProcessUnwantedFlare
void ProcessUnwantedFlare()
Definition: AddonPartFileFormat.cpp:497
RoR::CineCameraID_t
int CineCameraID_t
Index into Actor::ar_cinecam_node and Actor::ar_camera_node_* arrays; use RoR::CINECAMERAID_INVALID a...
Definition: ForwardDeclarations.h:79
RoR::TuneupUtil::isPropTweaked
static bool isPropTweaked(TuneupDefPtr &tuneup_entry, PropID_t flexbody_id, TuneupPropTweak *&out_tweak)
Definition: TuneupFileFormat.cpp:384
RoR::AddonPartUtility::ProcessUnwantedExhaust
void ProcessUnwantedExhaust()
Definition: AddonPartFileFormat.cpp:521
RoR::TuneupFlexbodyTweak::tft_origin
std::string tft_origin
Addonpart filename.
Definition: TuneupFileFormat.h:86
RoR::TuneupManagedMatTweak::tmt_type
std::string tmt_type
Arg#2, required.
Definition: TuneupFileFormat.h:92
RigDef::Prop::DashboardSpecial::mesh_name
Ogre::String mesh_name
Definition: RigDef_File.h:973
RoR::TuneupFlexbodyTweak::tft_media
std::string tft_media
Definition: TuneupFileFormat.h:83
RoR::TuneupDef::unwanted_managedmats
std::set< std::string > unwanted_managedmats
'addonpart_unwanted_managedmaterial' directives.
Definition: TuneupFileFormat.h:128
RigDef::Prop::rotation
Ogre::Vector3 rotation
Definition: RigDef_File.h:991
RigDef::ManagedMaterial::damaged_diffuse_map
Ogre::String damaged_diffuse_map
Definition: RigDef_File.h:906
RoR::TuneupDef::prop_tweaks
std::map< PropID_t, TuneupPropTweak > prop_tweaks
Mesh name(s), offset and rotation overrides via 'addonpart_tweak_prop'.
Definition: TuneupFileFormat.h:121
format
Truck file format(technical spec)
RoR::TuneupDef::unwanted_flexbodies
std::set< FlexbodyID_t > unwanted_flexbodies
'addonpart_unwanted_flexbody' directives.
Definition: TuneupFileFormat.h:125
RoR::WheelSide::RIGHT
@ RIGHT
RoR::GenericDocument::OPTION_ALLOW_SLASH_COMMENTS
static const BitMask_t OPTION_ALLOW_SLASH_COMMENTS
Allow comments starting with //.
Definition: GenericFileFormat.h:69
RigDef::Flexbody::rotation
Ogre::Vector3 rotation
Definition: RigDef_File.h:779
RoR::GenericDocContext::isTokLineBreak
bool isTokLineBreak(int offset=0) const
Definition: GenericFileFormat.h:127
RigDef::Flexbody::offset
Ogre::Vector3 offset
Definition: RigDef_File.h:778
RigDef::Flare2
Definition: RigDef_File.h:738
RoR::AddonPartUtility::m_context
GenericDocContextPtr m_context
Definition: AddonPartFileFormat.h:104
Console.h
RoR::GenericDocContext::getTokString
std::string getTokString(int offset=0) const
Definition: GenericFileFormat.h:113
RoR::AddonPartUtility::ProcessUnwantedManagedMat
void ProcessUnwantedManagedMat()
Definition: AddonPartFileFormat.cpp:545
RoR::TuneupDef::isFlexbodyProtected
bool isFlexbodyProtected(FlexbodyID_t flexbodyid) const
Definition: TuneupFileFormat.h:160
RoR::Console::putMessage
void putMessage(MessageArea area, MessageType type, std::string const &msg, std::string icon="")
Definition: Console.cpp:103
RigDef::Flare2::node_axis_y
Node::Ref node_axis_y
Definition: RigDef_File.h:742
RoR::GenericDocContext::isTokFloat
bool isTokFloat(int offset=0) const
Definition: GenericFileFormat.h:122
RoR::AddonPartUtility::TransformToRigDefModule
std::shared_ptr< RigDef::Document::Module > TransformToRigDefModule(CacheEntryPtr &addonpart_entry)
transforms the addonpart to RigDef::File::Module (fake 'section/end_section') used for spawning.
Definition: AddonPartFileFormat.cpp:50
RoR::TuneupPropTweak::tpt_prop_id
PropID_t tpt_prop_id
Definition: TuneupFileFormat.h:73
RigDef::Flare2::blink_delay_milis
int blink_delay_milis
Definition: RigDef_File.h:747
RigDef::Document::Module
Definition: RigDef_File.h:1358
RoR::CacheEntry::resource_group
Ogre::String resource_group
Resource group of the loaded bundle. Empty if not loaded yet.
Definition: CacheSystem.h:89
RoR::GUI::MessageBoxButton::mbb_caption
std::string mbb_caption
Definition: GUI_MessageBox.h:43
RoR::GenericDocContext::seekNextLine
bool seekNextLine()
Definition: GenericFileFormat.cpp:1129
TuneupFileFormat.h
The vehicle tuning system; applies addonparts and user overrides to vehicles.
RoR::AddonPartUtility::m_silent_mode
bool m_silent_mode
To block logging during conflict resolution (which works by generating dummy tuneups - would confuse ...
Definition: AddonPartFileFormat.h:111
RoR::TuneupDef::use_addonparts
std::set< std::string > use_addonparts
Addonpart filenames.
Definition: TuneupFileFormat.h:116
RigDef::Node::Range
Definition: RigDef_Node.h:114
RoR::GenericDocContext::getTokFloat
float getTokFloat(int offset=0) const
Definition: GenericFileFormat.h:114
RoR::CacheEntry::addonpart_data_only
TuneupDefPtr addonpart_data_only
Cached addonpart data (dummy tuneup), only used for evaluating conflicts, see AddonPartUtility::Recor...
Definition: CacheSystem.h:94
RoR::AddonPartUtility::ProcessTweakProp
void ProcessTweakProp()
Definition: AddonPartFileFormat.cpp:762
RigDef::Flexbody::reference_node
Node::Ref reference_node
Definition: RigDef_File.h:775
RoR::TuneupPropTweak::tpt_rotation
Ogre::Vector3 tpt_rotation
Definition: TuneupFileFormat.h:76
RoR::AddonPartConflictVec
std::vector< AddonPartConflict > AddonPartConflictVec
Definition: AddonPartFileFormat.h:53
RefCountingObjectPtr< CacheEntry >
RoR::AddonPartUtility::ProcessTweakNode
void ProcessTweakNode()
Definition: AddonPartFileFormat.cpp:618
RoR::AddonPartUtility::ProcessManagedMaterial
void ProcessManagedMaterial()
Definition: AddonPartFileFormat.cpp:214
Actor.h
RoR::ExhaustID_t
int ExhaustID_t
Index into GfxActor::m_exhausts, use RoR::EXHAUSTID_INVALID as empty value.
Definition: ForwardDeclarations.h:73
RoR::TuneupWheelTweak::twt_wheel_id
WheelID_t twt_wheel_id
Arg#1, required.
Definition: TuneupFileFormat.h:60
RoR::AddonPartUtility::m_tuneup
TuneupDefPtr m_tuneup
Definition: AddonPartFileFormat.h:110
RoR::TuneupDef::isPropProtected
bool isPropProtected(PropID_t propid) const
Definition: TuneupFileFormat.h:159
RoR::GenericDocContext::isTokString
bool isTokString(int offset=0) const
Definition: GenericFileFormat.h:121
RoR::AddonPartUtility::ProcessDirectiveSetManagedMaterialsOptions
void ProcessDirectiveSetManagedMaterialsOptions()
Definition: AddonPartFileFormat.cpp:243
RoR::TuneupCineCameraTweak::tct_cinecam_id
CineCameraID_t tct_cinecam_id
Arg#1, required.
Definition: TuneupFileFormat.h:53
RoR::TuneupUtil::isNodeTweaked
static bool isNodeTweaked(TuneupDefPtr &tuneup_entry, NodeNum_t nodenum, TuneupNodeTweak *&out_tweak)
Definition: TuneupFileFormat.cpp:278
RigDef::ManagedMaterial::type
ManagedMaterialType type
Definition: RigDef_File.h:903
RoR::TuneupCineCameraTweak
< Data of 'addonpart_tweak_cinecam <cinecam ID> <posX> <posY> <posZ>'
Definition: TuneupFileFormat.h:51
RoR::GenericDocContext::countLineArgs
int countLineArgs()
Definition: GenericFileFormat.cpp:1147
RoR::TuneupFlexbodyTweak::tft_flexbody_id
FlexbodyID_t tft_flexbody_id
Definition: TuneupFileFormat.h:82
RigDef::ManagedMaterial::options
ManagedMaterialsOptions options
Definition: RigDef_File.h:904
RigDef::ManagedMaterial::name
Ogre::String name
Definition: RigDef_File.h:902
RigDef::Prop::special
SpecialProp special
Definition: RigDef_File.h:995
RoR::AddonPartUtility::ProcessUnwantedProp
void ProcessUnwantedProp()
Definition: AddonPartFileFormat.cpp:449
RoR::AddonPartUtility::ResetUnwantedAndTweakedElements
static void ResetUnwantedAndTweakedElements(TuneupDefPtr &tuneup)
Definition: AddonPartFileFormat.cpp:193
RoR::TuneupDef::managedmat_tweaks
std::map< std::string, TuneupManagedMatTweak > managedmat_tweaks
Managed material overrides via 'addonpart_tweak_managedmaterial'.
Definition: TuneupFileFormat.h:123
RigDef::Flare2::material_name
Ogre::String material_name
Definition: RigDef_File.h:749
RoR::TuneupDef::node_tweaks
std::map< NodeNum_t, TuneupNodeTweak > node_tweaks
Node position overrides via 'addonpart_tweak_node'.
Definition: TuneupFileFormat.h:118
RoR::TuneupDef::unwanted_flares
std::set< FlareID_t > unwanted_flares
'addonpart_unwanted_flare' directives.
Definition: TuneupFileFormat.h:126
RoR::TuneupManagedMatTweak
< Data of 'addonpart_tweak_managedmaterial <name> <type> <media1> <media2> [<media3>]'
Definition: TuneupFileFormat.h:89
RigDef::Flare2::dashboard_link
std::string dashboard_link
Only 'd' type flares.
Definition: RigDef_File.h:746
RoR::TuneupManagedMatTweak::tmt_origin
std::string tmt_origin
Addonpart filename.
Definition: TuneupFileFormat.h:94
RoR::NodeNum_t
uint16_t NodeNum_t
Node position within Actor::ar_nodes; use RoR::NODENUM_INVALID as empty value.
Definition: ForwardDeclarations.h:54
RoR::CacheSystem::FindEntryByFilename
CacheEntryPtr FindEntryByFilename(RoR::LoaderType type, bool partial, const std::string &_filename_maybe_bundlequalified)
Returns NULL if none found; "Bundle-qualified" format also specifies the ZIP/directory in modcache,...
Definition: CacheSystem.cpp:186
RoR::GUI::MessageBoxButton
Definition: GUI_MessageBox.h:41
RoR::TuneupNodeTweak
< Data of 'addonpart_tweak_node <nodenum> <posX> <posY> <posZ>'
Definition: TuneupFileFormat.h:44
RoR::AddonPartUtility::RecordAddonpartConflicts
static void RecordAddonpartConflicts(CacheEntryPtr addonpart1, CacheEntryPtr addonpart2, AddonPartConflictVec &conflicts)
Definition: AddonPartFileFormat.cpp:861
CacheSystem.h
A database of user-installed content alias 'mods' (vehicles, terrains...)
keyword
static int keyword
Definition: Bench_TruckParser_IdentifyKeyword.cpp:1448
RigDef::Parser::IdentifySpecialProp
static SpecialProp IdentifySpecialProp(const std::string &str)
Definition: RigDef_Parser.cpp:3474
RigDef
Definition: Application.cpp:702
RigDef::Node::Range::end
Node::Ref end
Definition: RigDef_Node.h:135
RoR::AddonPartUtility::ProcessTweakCineCamera
void ProcessTweakCineCamera()
Definition: AddonPartFileFormat.cpp:663
RoR::TuneupWheelTweak::twt_side
WheelSide twt_side
Arg#4, optional, default LEFT (Only applicable to mesh/flexbody wheels)
Definition: TuneupFileFormat.h:64
RoR::GenericDocContext::isTokNumeric
bool isTokNumeric(int offset=0) const
Definition: GenericFileFormat.h:128
RoR::TuneupDef::flexbody_tweaks
std::map< FlexbodyID_t, TuneupFlexbodyTweak > flexbody_tweaks
Mesh name, offset and rotation overrides via 'addonpart_tweak_flexbody'.
Definition: TuneupFileFormat.h:122
RoR::AddonPartUtility::ProcessTweakWheel
void ProcessTweakWheel()
Definition: AddonPartFileFormat.cpp:570
RoR::GameContext::PushMessage
void PushMessage(Message m)
Doesn't guarantee order! Use ChainMessage() if order matters.
Definition: GameContext.cpp:66
RigDef::Flare2::reference_node
Node::Ref reference_node
Definition: RigDef_File.h:740
RoR::WheelID_t
int WheelID_t
Index to Actor::ar_wheels, use RoR::WHEELID_INVALID as empty value.
Definition: ForwardDeclarations.h:58
RoR::GUI::MessageBoxConfig::mbc_title
std::string mbc_title
Definition: GUI_MessageBox.h:52
RigDef::ManagedMaterial::specular_map
Ogre::String specular_map
Definition: RigDef_File.h:907
RoR::TuneupNodeTweak::tnt_pos
Ogre::Vector3 tnt_pos
Args#234, required.
Definition: TuneupFileFormat.h:47
RigDef::Flare2::offset
Ogre::Vector3 offset
Definition: RigDef_File.h:743
RigDef::Prop::DashboardSpecial::_offset_is_set
bool _offset_is_set
Definition: RigDef_File.h:971
RoR::AddonPartUtility::m_addonpart_entry
CacheEntryPtr m_addonpart_entry
Definition: AddonPartFileFormat.h:105
RoR::TuneupDef::isWheelProtected
bool isWheelProtected(WheelID_t wheelid) const
Definition: TuneupFileFormat.h:161
RigDef::Flexbody::node_list_to_import
std::vector< Node::Range > node_list_to_import
Definition: RigDef_File.h:782
RigDef::ManagedMaterial
Definition: RigDef_File.h:900
RoR::FlareType::DASHBOARD
@ DASHBOARD
Application.h
Central state/object manager and communications hub.
RoR::App::GetConsole
Console * GetConsole()
Definition: Application.cpp:286
RoR::TuneupPropTweak::tpt_origin
std::string tpt_origin
Addonpart filename.
Definition: TuneupFileFormat.h:77
RoR::FlareType
FlareType
Definition: Application.h:500
RigDef::Flexbody::mesh_name
Ogre::String mesh_name
Definition: RigDef_File.h:780
RoR::AddonPartConflict
< Conflict between two addonparts tweaking the same element
Definition: AddonPartFileFormat.h:38
RoR::AddonPartUtility::DoubleCheckForAddonpartConflict
static bool DoubleCheckForAddonpartConflict(ActorPtr target_actor, CacheEntryPtr addonpart_entry)
Definition: AddonPartFileFormat.cpp:959
RoR::App::GetGameContext
GameContext * GetGameContext()
Definition: Application.cpp:296
RoR::GUI::MessageBoxConfig::mbc_text
std::string mbc_text
Definition: GUI_MessageBox.h:53
RoR::TuneupDef::unwanted_exhausts
std::set< ExhaustID_t > unwanted_exhausts
'addonpart_unwanted_exhaust' directives.
Definition: TuneupFileFormat.h:127
RoR::WheelSide::LEFT
@ LEFT
RigDef::Prop::mesh_name
Ogre::String mesh_name
Definition: RigDef_File.h:992
RoR::AddonPartUtility::Log
void Log(const std::string &text)
Definition: AddonPartFileFormat.cpp:951
RigDef::Flare2::node_axis_x
Node::Ref node_axis_x
Definition: RigDef_File.h:741
_LC
#define _LC(ctx, str)
Definition: Language.h:38
RigDef::Flexbody
Definition: RigDef_File.h:773
RoR::GUI::MessageBoxButton::mbb_mq_message
MsgType mbb_mq_message
Message to queue on click.
Definition: GUI_MessageBox.h:44
RoR::GenericDocContext::getStringData
const char * getStringData(int offset=0) const
Definition: GenericFileFormat.h:154
RoR::GenericDocContext::endOfFile
bool endOfFile(int offset=0) const
Definition: GenericFileFormat.h:110
RoR::AddonPartUtility::ProcessTweakFlexbody
void ProcessTweakFlexbody()
Definition: AddonPartFileFormat.cpp:708
RigDef::Prop::y_axis_node
Node::Ref y_axis_node
Definition: RigDef_File.h:989
RoR::AddonPartUtility::CheckForAddonpartConflict
static bool CheckForAddonpartConflict(CacheEntryPtr addonpart1, CacheEntryPtr addonpart2, AddonPartConflictVec &conflicts)
Definition: AddonPartFileFormat.cpp:933
RoR::TuneupWheelTweak::twt_media
std::array< std::string, 2 > twt_media
twt_media[0] Arg#2, required ('wheels[2]': face material, 'meshwheels[2]/flexbodywheels': rim mesh) t...
Definition: TuneupFileFormat.h:63
RoR::GenericDocContext::getFloatData
float getFloatData(int offset=0) const
Definition: GenericFileFormat.h:155
RoR::App::GetCacheSystem
CacheSystem * GetCacheSystem()
Definition: Application.cpp:288
RigDef::ManagedMaterialsOptions::double_sided
bool double_sided
Definition: RigDef_File.h:897
RoR::TuneupPropTweak::tpt_media
std::array< std::string, 2 > tpt_media
Media1 = prop mesh; Media2: Steering wheel mesh or beacon flare material.
Definition: TuneupFileFormat.h:74
RigDef::Flexbody::node_list
std::vector< Node::Ref > node_list
Definition: RigDef_File.h:783
RoR::TuneupNodeTweak::tnt_origin
std::string tnt_origin
Addonpart filename.
Definition: TuneupFileFormat.h:48
RoR::TuneupPropTweak::tpt_offset
Ogre::Vector3 tpt_offset
Definition: TuneupFileFormat.h:75
RoR::FlareType::USER
@ USER
RoR::GUI::MessageBoxConfig
Definition: GUI_MessageBox.h:50
RigDef::Flare2::size
float size
Definition: RigDef_File.h:748
RoR::CacheSystem::LoadResource
void LoadResource(CacheEntryPtr &t)
Loads the associated resource bundle if not already done.
Definition: CacheSystem.cpp:1538
RoR::GenericDocument
Definition: GenericFileFormat.h:66
RoR::Message
Unified game event system - all requests and state changes are reported using a message.
Definition: GameContext.h:51
RoR::TuneupDef::cinecam_tweaks
std::map< CineCameraID_t, TuneupCineCameraTweak > cinecam_tweaks
Cinecam position overrides via 'addonpart_tweak_cinecam'.
Definition: TuneupFileFormat.h:119
RoR::AddonPartUtility::m_managedmaterials_options
RigDef::ManagedMaterialsOptions m_managedmaterials_options
Definition: AddonPartFileFormat.h:108
RigDef_Parser.h
Checks the rig-def file syntax and loads data to memory.
RoR::FlareID_t
int FlareID_t
Index into Actor::ar_flares, use RoR::FLAREID_INVALID as empty value.
Definition: ForwardDeclarations.h:70
RoR::AddonPartUtility::ProcessFlare2
void ProcessFlare2()
Definition: AddonPartFileFormat.cpp:408
RoR::TuneupDef::isFlareProtected
bool isFlareProtected(FlareID_t flareid) const
Definition: TuneupFileFormat.h:164
RoR::GenericDocContext::getTokKeyword
std::string getTokKeyword(int offset=0) const
Definition: GenericFileFormat.h:118
RigDef::Prop::special_prop_dashboard
DashboardSpecial special_prop_dashboard
Definition: RigDef_File.h:997
RoR::TuneupManagedMatTweak::tmt_name
std::string tmt_name
Arg#1, required.
Definition: TuneupFileFormat.h:91
RoR::TuneupWheelTweak
< Data of 'addonpart_tweak_wheel <wheel ID> <media1> <media2> <side flag> <tire radius> <rim radius>'
Definition: TuneupFileFormat.h:58
RoR::GUI::MessageBoxConfig::mbc_content_width
float mbc_content_width
Parameter to ImGui::SetContentWidth() - hard limit on content size.
Definition: GUI_MessageBox.h:57
RigDef::Flare2::control_number
int control_number
Only 'u' type flares.
Definition: RigDef_File.h:745
BitMask_t
uint32_t BitMask_t
Definition: BitFlags.h:7
RoR::GenericDocContext
Definition: GenericFileFormat.h:89
RoR::AddonPartUtility::ProcessUnwantedFlexbody
void ProcessUnwantedFlexbody()
Definition: AddonPartFileFormat.cpp:473
RoR::AddonPartUtility::ProcessProp
void ProcessProp()
Definition: AddonPartFileFormat.cpp:252
RoR::Console::CONSOLE_MSGTYPE_ACTOR
@ CONSOLE_MSGTYPE_ACTOR
Parsing/spawn/simulation messages for actors.
Definition: Console.h:63
AddonPartFileFormat.h
RoR::GenericDocument::loadFromDataStream
virtual void loadFromDataStream(Ogre::DataStreamPtr datastream, BitMask_t options=0)
Definition: GenericFileFormat.cpp:1007
RoR::Console::CONSOLE_SYSTEM_WARNING
@ CONSOLE_SYSTEM_WARNING
Definition: Console.h:53
RoR::TuneupDef::isExhaustProtected
bool isExhaustProtected(ExhaustID_t exhaustid) const
Definition: TuneupFileFormat.h:165
RoR::AddonPartUtility::AddonPartUtility
AddonPartUtility(bool silent_mode=false)
Definition: AddonPartFileFormat.cpp:39
RoR::AddonPartUtility
NOTE: Modcache processes this format directly using RoR::GenericDocument, see RoR::CacheSystem::FillA...
Definition: AddonPartFileFormat.h:56
RoR::TuneupDef::isCineCameraProtected
bool isCineCameraProtected(CineCameraID_t cinecamid) const
Definition: TuneupFileFormat.h:163
RoR::FlexbodyID_t
int FlexbodyID_t
Index to GfxActor::m_flexbodies, use RoR::FLEXBODYID_INVALID as empty value.
Definition: ForwardDeclarations.h:64
RoR::TuneupCineCameraTweak::tct_origin
std::string tct_origin
Addonpart filename.
Definition: TuneupFileFormat.h:55
RigDef::Prop::reference_node
Node::Ref reference_node
Definition: RigDef_File.h:987
RoR::TuneupUtil::isFlexbodyTweaked
static bool isFlexbodyTweaked(TuneupDefPtr &tuneup_entry, FlexbodyID_t flexbody_id, TuneupFlexbodyTweak *&out_tweak)
Definition: TuneupFileFormat.cpp:475
RigDef::Flexbody::x_axis_node
Node::Ref x_axis_node
Definition: RigDef_File.h:776
RoR::GenericDocContext::isTokComment
bool isTokComment(int offset=0) const
Definition: GenericFileFormat.h:126
RoR::TuneupFlexbodyTweak::tft_offset
Ogre::Vector3 tft_offset
Definition: TuneupFileFormat.h:84
RoR::MSG_GUI_HIDE_MESSAGE_BOX_REQUESTED
@ MSG_GUI_HIDE_MESSAGE_BOX_REQUESTED
Definition: Application.h:143
RoR::AddonPartUtility::~AddonPartUtility
~AddonPartUtility()
Definition: AddonPartFileFormat.cpp:45
GenericFileFormat.h
Generic text file parser.
RoR::TuneupFlexbodyTweak
< Data of 'addonpart_tweak_flexbody <flexbody ID> <offsetX> <offsetY> <offsetZ> <rotX> <rotY> <rotZ> ...
Definition: TuneupFileFormat.h:80
RigDef::Node::Ref::Num
unsigned int Num() const
Definition: RigDef_Node.h:95
RoR::GenericDocument::OPTION_ALLOW_NAKED_STRINGS
static const BitMask_t OPTION_ALLOW_NAKED_STRINGS
Allow strings without quotes, for backwards compatibility.
Definition: GenericFileFormat.h:68
RigDef::Prop::x_axis_node
Node::Ref x_axis_node
Definition: RigDef_File.h:988
RigDef::Prop::DashboardSpecial::rotation_angle
float rotation_angle
Definition: RigDef_File.h:972
RoR::Actor::getWorkingTuneupDef
TuneupDefPtr & getWorkingTuneupDef()
Definition: Actor.cpp:4749
RoR
Definition: AppContext.h:36
RoR::TuneupManagedMatTweak::tmt_media
std::array< std::string, 3 > tmt_media
Arg#3, required, Arg#4, optional, Arg#5, optional.
Definition: TuneupFileFormat.h:93
RoR::TuneupDef::wheel_tweaks
std::map< WheelID_t, TuneupWheelTweak > wheel_tweaks
Mesh name and radius overrides via 'addonpart_tweak_wheel'.
Definition: TuneupFileFormat.h:120
RigDef::Prop::special_prop_beacon
BeaconSpecial special_prop_beacon
Definition: RigDef_File.h:996
RigDef::Flexbody::y_axis_node
Node::Ref y_axis_node
Definition: RigDef_File.h:777
RoR::PropID_t
int PropID_t
Index to GfxActor::m_props, use RoR::PROPID_INVALID as empty value.
Definition: ForwardDeclarations.h:61
RoR::TuneupCineCameraTweak::tct_pos
Ogre::Vector3 tct_pos
Args#234, required.
Definition: TuneupFileFormat.h:54
RoR::AddonPartUtility::ProcessFlexbody
void ProcessFlexbody()
Definition: AddonPartFileFormat.cpp:318
RoR::TuneupDef::isNodeProtected
bool isNodeProtected(NodeNum_t nodenum) const
Definition: TuneupFileFormat.h:162
RigDef::Keyword
Keyword
Definition: Application.h:171
RigDef::Prop::BeaconSpecial::flare_material_name
Ogre::String flare_material_name
Definition: RigDef_File.h:983
RoR::AddonPartUtility::ProcessFlare
void ProcessFlare()
Definition: AddonPartFileFormat.cpp:370
RoR::AddonPartUtility::ProcessTweakManagedMat
void ProcessTweakManagedMat()
Definition: AddonPartFileFormat.cpp:819
RoR::CacheEntry::fname
Ogre::String fname
filename
Definition: CacheSystem.h:67
RoR::GenericDocContext::getTokInt
int getTokInt(int offset=0) const
Definition: GenericFileFormat.h:115
RigDef::Prop::BeaconSpecial::color
Ogre::ColourValue color
Definition: RigDef_File.h:984