RigsofRods
Soft-body Physics Simulation
TerrainObjectManager.cpp
Go to the documentation of this file.
1 /*
2  This source file is part of Rigs of Rods
3  Copyright 2005-2012 Pierre-Michel Ricordel
4  Copyright 2007-2012 Thomas Fischer
5  Copyright 2013-2020 Petr Ohlidal
6 
7  For more information, see http://www.rigsofrods.org/
8 
9  Rigs of Rods is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License version 3, as
11  published by the Free Software Foundation.
12 
13  Rigs of Rods is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with Rigs of Rods. If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 #include "TerrainObjectManager.h"
23 
24 #include "Actor.h"
25 #include "Application.h"
26 #include "AutoPilot.h"
27 #include "CacheSystem.h"
28 #include "Collisions.h"
29 #include "Console.h"
30 #include "ErrorUtils.h"
31 #include "Language.h"
32 #include "GameContext.h"
33 #include "GfxScene.h"
34 #include "GUIManager.h"
35 #include "GUI_LoadingWindow.h"
36 #include "MeshObject.h"
37 #include "ODefFileFormat.h"
38 #include "PlatformUtils.h"
39 #include "ProceduralRoad.h"
40 #include "ScriptEngine.h"
41 #include "SoundScriptManager.h"
42 #include "TerrainGeometryManager.h"
43 #include "Terrain.h"
44 #include "TObjFileFormat.h"
45 #include "Utils.h"
46 #include "WriteTextToTexture.h"
47 
48 #include <RTShaderSystem/OgreRTShaderSystem.h>
49 #include <Overlay/OgreFontManager.h>
50 
51 #ifdef USE_ANGELSCRIPT
53 #endif // USE_ANGELSCRIPT
54 
55 using namespace Ogre;
56 using namespace RoR;
57 #ifdef USE_PAGED
58 using namespace Forests;
59 #endif //USE_PAGED
60 
61 //workaround for pagedgeometry
62 inline float getTerrainHeight(Real x, Real z, void* unused = 0)
63 {
65 }
66 
67 TerrainObjectManager::TerrainObjectManager(Terrain* terrainManager) :
68  terrainManager(terrainManager)
69 {
70  m_terrn2_grouping_node = App::GetGfxScene()->GetSceneManager()->getRootSceneNode()->createChildSceneNode(fmt::format("Terrain: {}", terrainManager->GetDef().name));
71 
72  m_procedural_manager = new ProceduralManager(m_terrn2_grouping_node->createChildSceneNode("Procedural Roads"));
73 }
74 
76 {
77  for (MeshObject* mo : m_mesh_objects)
78  {
79  if (mo)
80  delete mo;
81  }
82 #ifdef USE_PAGED
83  for (auto geom : m_paged_geometry)
84  {
85  delete geom->getPageLoader();
86  delete geom;
87  }
88 #endif //USE_PAGED
89 
90  App::GetGfxScene()->GetSceneManager()->destroyAllEntities();
91 
93 }
94 
95 void GenerateGridAndPutToScene(Ogre::Vector3 position)
96 {
97  Ogre::ColourValue background_color(Ogre::ColourValue::White);
98  Ogre::ColourValue grid_color(0.2f, 0.2f, 0.2f, 1.0f);
99 
100  Ogre::ManualObject* mo = new Ogre::ManualObject("ReferenceGrid");
101 
102  mo->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_LIST);
103 
104  const float step = 1.0f;
105  const size_t count = 50;
106  unsigned int halfCount = count / 2;
107  const float half = (step * count) / 2;
108  const float y = 0;
109  Ogre::ColourValue c;
110  for (size_t i=0; i < count+1; i++)
111  {
112  if (i == halfCount)
113  c = Ogre::ColourValue(1.f, 0.f, 0.f, 1.f);
114  else
115  c = grid_color;
116 
117  mo->position(-half, y, -half+(step*i));
118  mo->colour(background_color);
119  mo->position(0, y, -half+(step*i));
120  mo->colour(c);
121  mo->position(0, y, -half+(step*i));
122  mo->colour(c);
123  mo->position(half, y, -half+(step*i));
124  mo->colour(background_color);
125 
126  if (i == halfCount)
127  c = Ogre::ColourValue(0,0,1,1.0f);
128  else
129  c = grid_color;
130 
131  mo->position(-half+(step*i), y, -half);
132  mo->colour(background_color);
133  mo->position(-half+(step*i), y, 0);
134  mo->colour(c);
135  mo->position(-half+(step*i), y, 0);
136  mo->colour(c);
137  mo->position(-half+(step*i), y, half);
138  mo->colour(background_color);
139  }
140 
141  mo->end();
142  mo->setCastShadows(false);
143  Ogre::SceneNode *n = App::GetGameContext()->GetTerrain()->getObjectManager()->getGroupingSceneNode()->createChildSceneNode();
144  n->setPosition(position);
145  n->attachObject(mo);
146  n->setVisible(true);
147 }
148 
149 void TerrainObjectManager::LoadTObjFile(Ogre::String tobj_name)
150 {
151  ROR_ASSERT(this->terrainManager);
154 
155  std::shared_ptr<TObjFile> tobj;
156  try
157  {
158  DataStreamPtr stream_ptr = ResourceGroupManager::getSingleton().openResource(
159  tobj_name, this->terrainManager->getCacheEntry()->resource_group);
160  TObjParser parser;
161  parser.Prepare();
162  parser.ProcessOgreStream(stream_ptr.get());
163  tobj = parser.Finalize();
164  }
165  catch (Ogre::Exception& e)
166  {
167  LOG("[RoR|Terrain] Error reading TObj file: " + tobj_name + "\nMessage" + e.getFullDescription());
168  return;
169  }
170  catch (std::exception& e)
171  {
172  LOG("[RoR|Terrain] Error reading TObj file: " + tobj_name + "\nMessage" + e.what());
173  return;
174  }
175 
177  m_tobj_grouping_node = m_terrn2_grouping_node->createChildSceneNode(tobj_name);
178 
179  int mapsizex = terrainManager->getGeometryManager()->getMaxTerrainSize().x;
180  int mapsizez = terrainManager->getGeometryManager()->getMaxTerrainSize().z;
181 
182  // Section 'grid'
183  if (tobj->grid_enabled)
184  {
185  GenerateGridAndPutToScene(tobj->grid_position);
186  }
187 
188  // Section 'trees'
189  if (App::gfx_vegetation_mode->getEnum<GfxVegetation>() != GfxVegetation::NONE)
190  {
191  for (TObjTree tree : tobj->trees)
192  {
193  try
194  {
195  this->ProcessTree(
196  tree.yaw_from, tree.yaw_to,
197  tree.scale_from, tree.scale_to,
198  tree.color_map, tree.density_map, tree.tree_mesh, tree.collision_mesh,
199  tree.grid_spacing, tree.high_density,
200  tree.min_distance, tree.max_distance, mapsizex, mapsizez);
201  }
202  catch (...)
203  {
204  RoR::HandleGenericException(fmt::format("Error processing 'trees' line (mesh: {}) from TOBJ file {}", tree.tree_mesh, tobj_name));
205  }
206  }
207  }
208 
209  // Section 'grass' / 'grass2'
210  if (App::gfx_vegetation_mode->getEnum<GfxVegetation>() != GfxVegetation::NONE)
211  {
212  for (TObjGrass grass : tobj->grass)
213  {
214  try
215  {
216  this->ProcessGrass(
217  grass.sway_speed, grass.sway_length, grass.sway_distrib, grass.density,
218  grass.min_x, grass.min_y, grass.min_h,
219  grass.max_x, grass.max_y, grass.max_h,
221  grass.grow_techniq, grass.technique, grass.range, mapsizex, mapsizez);
222  }
223  catch (...)
224  {
225  RoR::HandleGenericException(fmt::format("Error processing 'grass' line (material: {}) from TOBJ file {}", grass.material_name, tobj_name));
226  }
227  }
228  }
229 
230  // Procedural roads
231  for (ProceduralObjectPtr& po : tobj->proc_objects)
232  {
233  try
234  {
236  }
237  catch (...)
238  {
239  RoR::HandleGenericException(fmt::format("Error processing procedural road {} from TOBJ file {}", po->name, tobj_name));
240  }
241  }
242 
243  // Vehicles
244  for (TObjVehicle veh : tobj->vehicles)
245  {
246  if ((veh.type == TObj::SpecialObject::BOAT) && (terrainManager->getWater() == nullptr))
247  {
248  continue; // Don't spawn boats if there's no water.
249  }
250 
251  Ogre::String group;
252  Ogre::String filename(veh.name);
253  if (!RoR::App::GetCacheSystem()->CheckResourceLoaded(filename, group))
254  {
255  LOG(std::string("[RoR|Terrain] Vehicle ") + veh.name + " not found. ignoring.");
256  continue;
257  }
258 
259  PredefinedActor p;
260  p.px = veh.position.x;
261  p.py = veh.position.y;
262  p.pz = veh.position.z;
265  p.rotation = veh.rotation;
266  p.name = veh.name;
267  m_predefined_actors.push_back(p);
268  }
269 
270  // Entries
271  for (TObjEntry entry : tobj->objects)
272  {
273  try
274  {
275  this->LoadTerrainObject(entry.odef_name, entry.position, entry.rotation, entry.instance_name, entry.type, entry.rendering_distance);
276  }
277  catch (...)
278  {
279  RoR::HandleGenericException(fmt::format("Error processing object line (ODEF: {}) from TOBJ file {}", entry.odef_name, tobj_name));
280  }
281  }
282 
283  if (App::diag_terrn_log_roads->getBool())
284  {
286  }
287 
288  m_tobj_grouping_node = nullptr;
289 }
290 
292  float yawfrom, float yawto,
293  float scalefrom, float scaleto,
294  char* ColorMap, char* DensityMap, char* treemesh, char* treeCollmesh,
295  float gridspacing, float highdens,
296  int minDist, int maxDist, int mapsizex, int mapsizez)
297 {
298 #ifdef USE_PAGED
299  if (strnlen(ColorMap, 3) == 0)
300  {
301  LOG("tree ColorMap map zero!");
302  return;
303  }
304  if (strnlen(DensityMap, 3) == 0)
305  {
306  LOG("tree DensityMap zero!");
307  return;
308  }
309  Forests::DensityMap *densityMap = Forests::DensityMap::load(DensityMap, Forests::CHANNEL_COLOR);
310  if (!densityMap)
311  {
312  LOG("could not load densityMap: "+String(DensityMap));
313  return;
314  }
315  densityMap->setFilter(Forests::MAPFILTER_BILINEAR);
316  //densityMap->setMapBounds(TRect(0, 0, mapsizex, mapsizez));
317 
318  PagedGeometry* geom = new PagedGeometry();
319  geom->setTempDir(App::sys_cache_dir->getStr() + PATH_SLASH);
320  geom->setCamera(App::GetCameraManager()->GetCamera());
321  geom->setPageSize(50);
322  geom->setInfinite();
323  Ogre::TRect<Ogre::Real> bounds = TBounds(0, 0, mapsizex, mapsizez);
324  geom->setBounds(bounds);
325 
326  //Set up LODs
327  //trees->addDetailLevel<EntityPage>(50);
328  float min = minDist * terrainManager->getPagedDetailFactor();
329  if (min < 10)
330  min = 10;
331  geom->addDetailLevel<BatchPage>(min, min / 2);
332  float max = maxDist * terrainManager->getPagedDetailFactor();
333  if (max < 10)
334  max = 10;
335 
336  // Check if farther details level is greater than closer
337  if (max / 10 > min / 2)
338  {
339  geom->addDetailLevel<ImpostorPage>(max, max / 10);
340  }
341 
342  TreeLoader2D *treeLoader = new TreeLoader2D(geom, TBounds(0, 0, mapsizex, mapsizez));
343  treeLoader->setMinimumScale(scalefrom);
344  treeLoader->setMaximumScale(scaleto);
345  geom->setPageLoader(treeLoader);
346  treeLoader->setHeightFunction(&getTerrainHeight);
347  if (String(ColorMap) != "none")
348  {
349  treeLoader->setColorMap(ColorMap);
350  }
351 
352  Entity* curTree = App::GetGfxScene()->GetSceneManager()->createEntity(String("paged_") + treemesh + TOSTRING(m_paged_geometry.size()), treemesh);
353 
354  if (gridspacing > 0)
355  {
356  // grid style
357  for (float x=0; x < mapsizex; x += gridspacing)
358  {
359  for (float z=0; z < mapsizez; z += gridspacing)
360  {
361  float density = densityMap->_getDensityAt_Unfiltered(x, z, bounds);
362  if (density < 0.8f) continue;
363  float nx = x + gridspacing * 0.5f;
364  float nz = z + gridspacing * 0.5f;
365  float yaw = Math::RangeRandom(yawfrom, yawto);
366  float scale = Math::RangeRandom(scalefrom, scaleto);
367  Vector3 pos = Vector3(nx, 0, nz);
368  treeLoader->addTree(curTree, pos, Degree(yaw), (Ogre::Real)scale);
369  if (strlen(treeCollmesh))
370  {
371  pos.y = terrainManager->GetHeightAt(pos.x, pos.z);
372  scale *= 0.1f;
373  terrainManager->GetCollisions()->addCollisionMesh(curTree->getName(), String(treeCollmesh), pos, Quaternion(Degree(yaw), Vector3::UNIT_Y), Vector3(scale, scale, scale));
374  }
375  }
376  }
377  }
378  else
379  {
380  float gridsize = 10;
381  if (gridspacing < 0 && gridspacing != 0)
382  {
383  gridsize = -gridspacing;
384  }
385  float hd = highdens;
386  // normal style, random
387  for (float x=0; x < mapsizex; x += gridsize)
388  {
389  for (float z=0; z < mapsizez; z += gridsize)
390  {
391  if (highdens < 0) hd = Math::RangeRandom(0, -highdens);
392  float density = densityMap->_getDensityAt_Unfiltered(x, z, bounds);
393  int numTreesToPlace = (int)((float)(hd) * density * terrainManager->getPagedDetailFactor());
394  float nx=0, nz=0;
395  while(numTreesToPlace-->0)
396  {
397  nx = Math::RangeRandom(x, x + gridsize);
398  nz = Math::RangeRandom(z, z + gridsize);
399  float yaw = Math::RangeRandom(yawfrom, yawto);
400  float scale = Math::RangeRandom(scalefrom, scaleto);
401  Vector3 pos = Vector3(nx, 0, nz);
402  treeLoader->addTree(curTree, pos, Degree(yaw), (Ogre::Real)scale);
403  if (strlen(treeCollmesh))
404  {
405  pos.y = terrainManager->GetHeightAt(pos.x, pos.z);
406  terrainManager->GetCollisions()->addCollisionMesh(treemesh, String(treeCollmesh),pos, Quaternion(Degree(yaw), Vector3::UNIT_Y), Vector3(scale, scale, scale));
407  }
408  }
409  }
410  }
411  }
412  m_paged_geometry.push_back(geom);
413 #endif //USE_PAGED
414 }
415 
417  float SwaySpeed, float SwayLength, float SwayDistribution, float Density,
418  float minx, float miny, float minH, float maxx, float maxy, float maxH,
419  char* grassmat, char* colorMapFilename, char* densityMapFilename,
420  int growtechnique, int techn, int range,
421  int mapsizex, int mapsizez)
422 {
423 #ifdef USE_PAGED
424  //Initialize the PagedGeometry engine
425  try
426  {
427  PagedGeometry *grass = new PagedGeometry(App::GetCameraManager()->GetCamera(), 30);
428  //Set up LODs
429 
430  grass->addDetailLevel<GrassPage>(range * terrainManager->getPagedDetailFactor()); // original value: 80
431 
432  //Set up a GrassLoader for easy use
433  GrassLoader *grassLoader = new GrassLoader(grass);
434  grass->setPageLoader(grassLoader);
435  grassLoader->setHeightFunction(&getTerrainHeight);
436 
437  // render grass at first
438  grassLoader->setRenderQueueGroup(RENDER_QUEUE_MAIN-1);
439 
440  GrassLayer* grassLayer = grassLoader->addLayer(grassmat);
441  grassLayer->setHeightRange(minH, maxH);
442  grassLayer->setLightingEnabled(true);
443 
444  grassLayer->setAnimationEnabled((SwaySpeed>0));
445  grassLayer->setSwaySpeed(SwaySpeed);
446  grassLayer->setSwayLength(SwayLength);
447  grassLayer->setSwayDistribution(SwayDistribution);
448 
449  grassLayer->setDensity(Density * terrainManager->getPagedDetailFactor());
450  if (techn>10)
451  grassLayer->setRenderTechnique(static_cast<GrassTechnique>(techn-10), true);
452  else
453  grassLayer->setRenderTechnique(static_cast<GrassTechnique>(techn), false);
454 
455  grassLayer->setMapBounds(TBounds(0, 0, mapsizex, mapsizez));
456 
457  if (strcmp(colorMapFilename,"none") != 0)
458  {
459  grassLayer->setColorMap(colorMapFilename);
460  grassLayer->setColorMapFilter(MAPFILTER_BILINEAR);
461  }
462 
463  if (strcmp(densityMapFilename,"none") != 0)
464  {
465  grassLayer->setDensityMap(densityMapFilename);
466  grassLayer->setDensityMapFilter(MAPFILTER_BILINEAR);
467  }
468 
469  grassLayer->setMinimumSize(minx, miny);
470  grassLayer->setMaximumSize(maxx, maxy);
471 
472  // growtechnique
473  if (growtechnique == 0)
474  grassLayer->setFadeTechnique(FADETECH_GROW);
475  else if (growtechnique == 1)
476  grassLayer->setFadeTechnique(FADETECH_ALPHAGROW);
477  else if (growtechnique == 2)
478  grassLayer->setFadeTechnique(FADETECH_ALPHA);
479 
480  m_paged_geometry.push_back(grass);
481  }
482  catch(...)
483  {
484  LOG("error loading grass!");
485  }
486 #endif //USE_PAGED
487 }
488 
489 void TerrainObjectManager::MoveObjectVisuals(const String& instancename, const Ogre::Vector3& pos)
490 {
491  if (m_static_objects.find(instancename) == m_static_objects.end())
492  {
493  LOG(instancename+ " not found!");
494  return;
495  }
496 
497  StaticObject obj = m_static_objects[instancename];
498 
499  if (!obj.enabled)
500  return;
501 
502  obj.sceneNode->setPosition(pos);
503 }
504 
505 void TerrainObjectManager::unloadObject(const String& instancename)
506 {
507  if (m_static_objects.find(instancename) == m_static_objects.end())
508  {
509  LOG("unable to unload object: " + instancename);
510  return;
511  }
512 
513  StaticObject obj = m_static_objects[instancename];
514 
515  if (!obj.enabled)
516  return;
517 
518  for (auto tri : obj.collTris)
519  {
521  }
522  for (auto box : obj.collBoxes)
523  {
525  }
526 
527  obj.sceneNode->detachAllObjects();
528  obj.sceneNode->setVisible(false);
529  obj.enabled = false;
530 
531  m_editor_objects.erase(std::remove_if(m_editor_objects.begin(), m_editor_objects.end(),
532  [instancename](EditorObject& e) { return e.instance_name == instancename; }), m_editor_objects.end());
533 }
534 
535 ODefFile* TerrainObjectManager::FetchODef(std::string const & odef_name)
536 {
537  // Consult cache first
538  auto search_res = m_odef_cache.find(odef_name);
539  if (search_res != m_odef_cache.end())
540  {
541  return search_res->second.get();
542  }
543 
544  // Search for the file
545  const std::string filename = odef_name + ".odef";
546  std::string group_name;
547  try
548  {
549  group_name = Ogre::ResourceGroupManager::getSingleton().findGroupContainingResource(filename);
550  }
551  catch (...) // This means "not found"
552  {
553  LOG(fmt::format("[ODEF] Could not find {} in any resource group", filename));
554  return nullptr;
555  }
556 
557  try
558  {
559  // Load and parse the file
560  Ogre::DataStreamPtr ds = ResourceGroupManager::getSingleton().openResource(filename, group_name);
561  ODefParser parser;
562  parser.Prepare();
563  parser.ProcessOgreStream(ds.get());
564  std::shared_ptr<ODefFile> odef = parser.Finalize();
565 
566  // Add to cache and return
567  m_odef_cache.insert(std::make_pair(odef_name, odef));
568  return odef.get();
569  }
570  catch (...)
571  {
572  LOG(fmt::format("[ODEF] An exception occurred when loading or parsing {}", filename));
573  return nullptr;
574  }
575 }
576 
577 bool TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogre::Vector3& pos, const Ogre::Vector3& rot, const Ogre::String& instancename, const Ogre::String& type, float rendering_distance /* = 0 */, bool enable_collisions /* = true */, int scripthandler /* = -1 */, bool uniquifyMaterial /* = false */)
578 {
579  if (type == "grid")
580  {
581  // some fast grid object hacks :)
582  for (int x = 0; x < 500; x += 50)
583  {
584  for (int z = 0; z < 500; z += 50)
585  {
586  const String notype = "";
587  LoadTerrainObject(name, pos + Vector3(x, 0.0f, z), rot, name, notype, /*rendering_distance:*/0, enable_collisions, scripthandler, uniquifyMaterial);
588  }
589  }
590  return true;
591  }
592 
593  const std::string odefname = name + ".odef"; // for logging
594  ODefFile* odef = this->FetchODef(name);
595  if (odef == nullptr)
596  {
597  // Only log to console if requested from Console UI or script (debug message to RoR.log is written anyway).
598  if (App::app_state->getEnum<AppState>() == AppState::SIMULATION)
599  {
601  fmt::format(_L("Could not load file '{}'"), odefname));
602  }
603  return false;
604  }
605 
606  SceneNode* tenode = this->getGroupingSceneNode()->createChildSceneNode();
607 
608  MeshObject* mo = nullptr;
609  if (odef->header.mesh_name != "none")
610  {
611  Str<100> ebuf; ebuf << m_entity_counter++ << "-" << odef->header.mesh_name;
612  mo = new MeshObject(odef->header.mesh_name, terrainManager->getTerrainFileResourceGroup(), ebuf.ToCStr(), tenode);
613  if (mo->getEntity())
614  {
615  mo->getEntity()->setCastShadows(odef->header.cast_shadows);
616  mo->getEntity()->setRenderingDistance(rendering_distance);
617  m_mesh_objects.push_back(mo);
618  }
619  else
620  {
621  delete mo;
622  // Only log to console if requested from Console UI or script (debug message to RoR.log is written anyway).
623  if (App::app_state->getEnum<AppState>() == AppState::SIMULATION)
624  {
626  fmt::format(_L("Could not load mesh '{}' (used by object '{}')"), odef->header.mesh_name, odefname));
627  }
628  }
629  }
630 
631  tenode->setScale(odef->header.scale);
632  tenode->setPosition(pos);
633  Quaternion rotation = Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * Quaternion(Degree(rot.z), Vector3::UNIT_Z);
634  tenode->rotate(rotation);
635  tenode->pitch(Degree(-90));
636  tenode->setVisible(true);
637 
638  // register in map
639  StaticObject* obj = &m_static_objects[instancename];
640  obj->instanceName = instancename;
641  obj->enabled = true;
642  obj->sceneNode = tenode;
643  obj->collTris.clear();
644 
645  EditorObject object;
646  object.name = name;
647  object.instance_name = instancename;
648  object.type = type;
649  object.position = pos;
650  object.rotation = rot;
651  object.initial_position = pos;
652  object.initial_rotation = rot;
653  object.node = tenode;
654  object.enable_collisions = enable_collisions;
655  object.script_handler = scripthandler;
656  m_editor_objects.push_back(object);
657 
658  if (mo && uniquifyMaterial && !instancename.empty())
659  {
660  for (unsigned int i = 0; i < mo->getEntity()->getNumSubEntities(); i++)
661  {
662  SubEntity* se = mo->getEntity()->getSubEntity(i);
663  String matname = se->getMaterialName();
664  String newmatname = matname + "/" + instancename;
665  se->getMaterial()->clone(newmatname);
666  se->setMaterialName(newmatname);
667  }
668  }
669 
670  for (LocalizerType type : odef->localizers)
671  {
672  localizer_t loc;
673  loc.position = Vector3(pos.x, pos.y, pos.z);
674  loc.rotation = rotation;
675  loc.type = type;
676  localizers.push_back(loc);
677  }
678 
679  if (odef->mode_standard)
680  {
681  tenode->pitch(Degree(90));
682  }
683 
684 #ifdef USE_OPENAL
685  if (!App::GetSoundScriptManager()->isDisabled())
686  {
687  for (std::string& snd_name : odef->sounds)
688  {
690  sound->setPosition(tenode->getPosition());
691  sound->start();
692  }
693  }
694 #endif //USE_OPENAL
695 
696  for (std::string& gmodel_file: odef->groundmodel_files)
697  {
699  }
700 
701  bool race_event = !object.instance_name.compare(0, 10, "checkpoint") ||
702  !object.instance_name.compare(0, 4, "race");
703 
704  if (race_event)
705  {
706  String type = "checkpoint";
707  auto res = StringUtil::split(object.instance_name, "|");
708  if ((res.size() == 4 && res[2] == "0") || !object.instance_name.compare(0, 4, "race"))
709  {
710  type = "racestart";
711  }
712  int race_id = res.size() > 1 ? StringConverter::parseInt(res[1], -1) : -1;
713  m_map_entities.push_back(SurveyMapEntity(type, /*caption:*/type, fmt::format("icon_{}.dds", type), /*resource_group:*/"", object.position, Ogre::Radian(0), race_id));
714  }
715  else if (!object.type.empty())
716  {
717  String caption = "";
718  if (object.type == "station" || object.type == "hotel" || object.type == "village" ||
719  object.type == "observatory" || object.type == "farm" || object.type == "ship" || object.type == "sign")
720  {
721  caption = object.instance_name + " " + object.type;
722  }
723  m_map_entities.push_back(SurveyMapEntity(object.type, caption, fmt::format("icon_{}.dds", object.type), /*resource_group:*/"", object.position, Ogre::Radian(0), -1));
724  }
725 
726  this->ProcessODefCollisionBoxes(obj, odef, object, race_event);
727 
728  for (ODefCollisionMesh& cmesh : odef->collision_meshes)
729  {
730  if (cmesh.mesh_name == "")
731  {
732  LOG("[ODEF] Skipping collision mesh with empty name. Object: " + odefname);
733  continue;
734  }
735 
738  odefname,
739  cmesh.mesh_name, pos, tenode->getOrientation(),
740  cmesh.scale, gm, &(obj->collTris));
741  }
742 
743  for (ODefParticleSys& psys : odef->particle_systems)
744  {
745 
746  // hacky: prevent duplicates
747  String paname = String(psys.instance_name);
748  while (App::GetGfxScene()->GetSceneManager()->hasParticleSystem(paname))
749  paname += "_";
750 
751  // create particle system
752  ParticleSystem* pParticleSys = App::GetGfxScene()->GetSceneManager()->createParticleSystem(paname, String(psys.template_name));
753  pParticleSys->setCastShadows(false);
754  pParticleSys->setVisibilityFlags(DEPTHMAP_DISABLED); // disable particles in depthmap
755 
756  // Some affectors may need its instance name (e.g. for script feedback purposes)
757 #ifdef USE_ANGELSCRIPT
758  unsigned short affCount = pParticleSys->getNumAffectors();
759  ParticleAffector* pAff;
760  for (unsigned short i = 0; i < affCount; ++i)
761  {
762  pAff = pParticleSys->getAffector(i);
763  if (pAff->getType() == "ExtinguishableFire")
764  {
765  ((ExtinguishableFireAffector*)pAff)->setInstanceName(obj->instanceName);
766  }
767  }
768 #endif // USE_ANGELSCRIPT
769 
770  SceneNode* sn = tenode->createChildSceneNode();
771  sn->attachObject(pParticleSys);
772  sn->pitch(Degree(90));
773  }
774 
775  if (!odef->mat_name.empty())
776  {
777  if (mo->getEntity())
778  {
779  mo->getEntity()->setMaterialName(odef->mat_name);
780  }
781  }
782 
783  if (odef->mat_name_generate != "")
784  {
785  Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().create(odef->mat_name_generate,"generatedMaterialShaders");
786  Ogre::RTShader::ShaderGenerator::getSingleton().createShaderBasedTechnique(*mat, Ogre::MaterialManager::DEFAULT_SCHEME_NAME, Ogre::RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME);
787  Ogre::RTShader::ShaderGenerator::getSingleton().invalidateMaterial(RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME, String(odef->mat_name_generate));
788  }
789 
790  for (ODefAnimation& anim : odef->animations)
791  {
792  if (tenode && mo->getEntity())
793  {
794  AnimationStateSet *s = mo->getEntity()->getAllAnimationStates();
795  String anim_name_str(anim.name);
796  if (!s->hasAnimationState(anim_name_str))
797  {
798  LOG("[ODEF] animation '" + anim_name_str + "' for mesh: '" + odef->header.mesh_name + "' in odef file '" + name + ".odef' not found!");
799  //continue;
800  }
801  AnimatedObject ao;
802  ao.node = tenode;
803  ao.ent = mo->getEntity();
804  ao.speedfactor = anim.speed_min;
805  if (anim.speed_min != anim.speed_max)
806  ao.speedfactor = Math::RangeRandom(anim.speed_min, anim.speed_max);
807  ao.anim = 0;
808  try
809  {
810  ao.anim = mo->getEntity()->getAnimationState(anim_name_str);
811  } catch (...)
812  {
813  ao.anim = 0;
814  }
815  if (!ao.anim)
816  {
817  LOG("[ODEF] animation '" + anim_name_str + "' for mesh: '" + odef->header.mesh_name + "' in odef file '" + name + ".odef' not found!");
818  continue;
819  }
820  ao.anim->setEnabled(true);
821  m_animated_objects.push_back(ao);
822  }
823  }
824 
825  for (ODefTexPrint& tex_print : odef->texture_prints)
826  {
827  if (!mo->getEntity())
828  continue;
829  String matName = mo->getEntity()->getSubEntity(0)->getMaterialName();
830  MaterialPtr m = MaterialManager::getSingleton().getByName(matName);
831  if (m.getPointer() == 0)
832  {
833  LOG("[ODEF] problem with drawTextOnMeshTexture command: mesh material not found: "+odefname+" : "+matName);
834  continue;
835  }
836  String texName = m->getTechnique(0)->getPass(0)->getTextureUnitState(0)->getTextureName();
837  Texture* background = (Texture *)TextureManager::getSingleton().getByName(texName).getPointer();
838  if (!background)
839  {
840  LOG("[ODEF] problem with drawTextOnMeshTexture command: mesh texture not found: "+odefname+" : "+texName);
841  continue;
842  }
843 
844  static int textureNumber = 0;
845  textureNumber++;
846  char tmpTextName[256] = "", tmpMatName[256] = "";
847  sprintf(tmpTextName, "TextOnTexture_%d_Texture", textureNumber);
848  sprintf(tmpMatName, "TextOnTexture_%d_Material", textureNumber); // Make sure the texture is not WRITE_ONLY, we need to read the buffer to do the blending with the font (get the alpha for example)
849  TexturePtr texture = TextureManager::getSingleton().createManual(tmpTextName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, (Ogre::uint)background->getWidth(), (Ogre::uint)background->getHeight(), MIP_UNLIMITED, PF_X8R8G8B8, Ogre::TU_STATIC | Ogre::TU_AUTOMIPMAP);
850  if (texture.getPointer() == 0)
851  {
852  LOG("[ODEF] problem with drawTextOnMeshTexture command: could not create texture: "+odefname+" : "+tmpTextName);
853  continue;
854  }
855 
856  Str<200> text_buf; text_buf << tex_print.text;
857 
858  // check if we got a template argument
859  if (!strncmp(text_buf.GetBuffer(), "{{argument1}}", 13))
860  {
861  text_buf.Clear();
862  text_buf << instancename;
863  }
864 
865  // replace '_' with ' '
866  char *text_pointer = text_buf.GetBuffer();
867  while (*text_pointer!=0) {if (*text_pointer=='_') *text_pointer=' ';text_pointer++;};
868 
869  String font_name_str(tex_print.font_name);
870  Ogre::Font* font = (Ogre::Font *)FontManager::getSingleton().getByName(font_name_str).getPointer();
871  if (!font)
872  {
873  LOG("[ODEF] problem with drawTextOnMeshTexture command: font not found: "+odefname+" : "+font_name_str);
874  continue;
875  }
876 
877  //Draw the background to the new texture
878  texture->getBuffer()->blit(background->getBuffer());
879 
880  float x = background->getWidth() * tex_print.x;
881  float y = background->getHeight() * tex_print.y;
882  float w = background->getWidth() * tex_print.w;
883  float h = background->getHeight() * tex_print.h;
884 
885  ColourValue color(tex_print.r, tex_print.g, tex_print.b, tex_print.a);
886  Ogre::Box box = Ogre::Box((size_t)x, (size_t)y, (size_t)(x+w), (size_t)(y+h));
887  WriteToTexture(text_buf.ToCStr(), texture, box, font, color, tex_print.font_size, tex_print.font_dpi, tex_print.option);
888 
889  // we can save it to disc for debug purposes:
890  //SaveImage(texture, "test.png");
891 
892  m->clone(tmpMatName);
893  MaterialPtr mNew = MaterialManager::getSingleton().getByName(tmpMatName);
894  mNew->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(tmpTextName);
895 
896  mo->getEntity()->setMaterialName(String(tmpMatName));
897  }
898 
899  for (ODefSpotlight& spotl: odef->spotlights)
900  {
901  Light* spotLight = App::GetGfxScene()->GetSceneManager()->createLight();
902 
903  spotLight->setType(Light::LT_SPOTLIGHT);
904  spotLight->setPosition(spotl.pos);
905  spotLight->setDirection(spotl.dir);
906  spotLight->setAttenuation(spotl.range, 1.0, 0.3, 0.0);
907  spotLight->setDiffuseColour(spotl.color);
908  spotLight->setSpecularColour(spotl.color);
909  spotLight->setSpotlightRange(Degree(spotl.angle_inner), Degree(spotl.angle_outer));
910 
911  BillboardSet* lflare = App::GetGfxScene()->GetSceneManager()->createBillboardSet(1);
912  lflare->createBillboard(spotl.pos, spotl.color);
913  lflare->setMaterialName("tracks/flare");
914  lflare->setVisibilityFlags(DEPTHMAP_DISABLED);
915 
916  float fsize = Math::Clamp(spotl.range / 10, 0.2f, 2.0f);
917  lflare->setDefaultDimensions(fsize, fsize);
918 
919  SceneNode *sn = tenode->createChildSceneNode();
920  sn->attachObject(spotLight);
921  sn->attachObject(lflare);
922  }
923 
924  for (ODefPointLight& plight : odef->point_lights)
925  {
926  Light* pointlight = App::GetGfxScene()->GetSceneManager()->createLight();
927 
928  pointlight->setType(Light::LT_POINT);
929  pointlight->setPosition(plight.pos);
930  pointlight->setDirection(plight.dir);
931  pointlight->setAttenuation(plight.range, 1.0, 0.3, 0.0);
932  pointlight->setDiffuseColour(plight.color);
933  pointlight->setSpecularColour(plight.color);
934 
935  BillboardSet* lflare = App::GetGfxScene()->GetSceneManager()->createBillboardSet(1);
936  lflare->createBillboard(plight.pos, plight.color);
937  lflare->setMaterialName("tracks/flare");
938  lflare->setVisibilityFlags(DEPTHMAP_DISABLED);
939 
940  float fsize = Math::Clamp(plight.range / 10, 0.2f, 2.0f);
941  lflare->setDefaultDimensions(fsize, fsize);
942 
943  SceneNode *sn = tenode->createChildSceneNode();
944  sn->attachObject(pointlight);
945  sn->attachObject(lflare);
946  }
947 
948  return true;
949 }
950 
951 bool TerrainObjectManager::LoadTerrainScript(const Ogre::String& filename)
952 {
954 
955  m_angelscript_grouping_node = m_terrn2_grouping_node->createChildSceneNode(filename);
956  ScriptUnitId_t result = App::GetScriptEngine()->loadScript(filename);
957  m_angelscript_grouping_node = nullptr;
958 
959  return result != SCRIPTUNITID_INVALID;
960 }
961 
963 {
964  if (m_animated_objects.size() == 0)
965  return true;
966 
967  std::vector<AnimatedObject>::iterator it;
968 
969  for (it = m_animated_objects.begin(); it != m_animated_objects.end(); it++)
970  {
971  if (it->anim && it->speedfactor != 0)
972  {
973  Real time = dt * it->speedfactor;
974  it->anim->addTime(time);
975  }
976  }
977  return true;
978 }
979 
981 {
982  for (Terrn2Telepoint& telepoint: terrainManager->GetDef().telepoints)
983  {
984  m_map_entities.push_back(SurveyMapEntity("telepoint", telepoint.name, "icon_telepoint.dds", /*resource_group:*/"", telepoint.position, Ogre::Radian(0), -1));
985  }
986 }
987 
989 {
990  // in netmode, don't load other actors!
991  if (RoR::App::mp_state->getEnum<MpState>() == RoR::MpState::CONNECTED)
992  {
993  return;
994  }
995 
996  for (unsigned int i = 0; i < m_predefined_actors.size(); i++)
997  {
999  rq->asr_position = Vector3(m_predefined_actors[i].px, m_predefined_actors[i].py, m_predefined_actors[i].pz);
1000  rq->asr_filename = m_predefined_actors[i].name;
1001  rq->asr_rotation = m_predefined_actors[i].rotation;
1003  rq->asr_free_position = m_predefined_actors[i].freePosition;
1004  rq->asr_terrn_machine = m_predefined_actors[i].ismachine;
1006  }
1007 }
1008 
1010 {
1011 #ifdef USE_PAGED
1012  for (auto geom : m_paged_geometry)
1013  {
1014  geom->update();
1015  }
1016 #endif //USE_PAGED
1017  this->UpdateAnimatedObjects(dt);
1018 
1019  return true;
1020 }
1021 
1023 {
1024  for (ODefCollisionBox& cbox : odef->collision_boxes)
1025  {
1026  if (params.enable_collisions && (App::sim_races_enabled->getBool() || !race_event))
1027  {
1028  // Validate AABB (minimum corners must be less or equal to maximum corners)
1029  if (cbox.aabb_min.x > cbox.aabb_max.x || cbox.aabb_min.y > cbox.aabb_max.y || cbox.aabb_min.z > cbox.aabb_max.z)
1030  {
1031  // Only log to console if invoked from Console UI or script.
1032  std::string msg = "Skipping invalid collision box, min: " + TOSTRING(cbox.aabb_min) + ", max: " + TOSTRING(cbox.aabb_max);
1033  if (App::app_state->getEnum<AppState>() == AppState::SIMULATION)
1034  {
1036  }
1037  else
1038  {
1039  LOG(fmt::format("[ODEF] {}", msg));
1040  }
1041  continue;
1042  }
1043 
1044  int boxnum = terrainManager->GetCollisions()->addCollisionBox(
1045  cbox.is_rotating, cbox.is_virtual, params.position, params.rotation,
1046  cbox.aabb_min, cbox.aabb_max, cbox.box_rot, cbox.event_name,
1047  params.instance_name, cbox.force_cam_pos, cbox.cam_pos,
1048  cbox.scale, cbox.direction, cbox.event_filter, params.script_handler);
1049 
1050  obj->collBoxes.push_back(boxnum);
1051  }
1052  }
1053 }
1054 
1056 {
1057  // This has no effect on rendering, it just helps users to diagnose the scene graph.
1058  // --------------------------------------------------------------------------------
1059 
1062  else if (m_tobj_grouping_node)
1063  return m_tobj_grouping_node;
1064  else if (m_terrn2_grouping_node)
1065  return m_terrn2_grouping_node;
1066  else
1067  return App::GetGfxScene()->GetSceneManager()->getRootSceneNode();
1068 }
RoR::TObj::SpecialObject::BOAT
@ BOAT
ROR_ASSERT
#define ROR_ASSERT(_EXPR)
Definition: Application.h:40
GameContext.h
Game state manager and message-queue provider.
RoR::ODefSpotlight::range
float range
Definition: ODefFileFormat.h:104
RoR::ProceduralManager::addObject
void addObject(ProceduralObjectPtr po)
Generates road mesh and adds to internal list.
Definition: ProceduralManager.cpp:174
RoR::TerrainObjectManager::EditorObject::rotation
Ogre::Vector3 rotation
Definition: TerrainObjectManager.h:60
RoR::TObj::SpecialObject::MACHINE
@ MACHINE
RoR::ODefFile::mode_standard
bool mode_standard
Definition: ODefFileFormat.h:127
RoR::App::GetSoundScriptManager
SoundScriptManager * GetSoundScriptManager()
Definition: Application.cpp:277
RoR::SoundScriptInstance::start
void start()
Definition: SoundScriptManager.cpp:1386
RoR::TerrainObjectManager::localizer_t::type
LocalizerType type
Definition: TerrainObjectManager.h:97
RoR::ODefTexPrint::option
char option
Definition: ODefFileFormat.h:94
RoR::ActorSpawnRequest::asr_free_position
bool asr_free_position
Disables the automatic spawn position adjustment.
Definition: SimData.h:863
RoR::ODefAnimation::name
std::string name
Definition: ODefFileFormat.h:85
y
float y
Definition: (ValueTypes) quaternion.h:6
RoR::ODefTexPrint::y
float y
Definition: ODefFileFormat.h:96
RoR::TerrainObjectManager::UpdateAnimatedObjects
bool UpdateAnimatedObjects(float dt)
Definition: TerrainObjectManager.cpp:962
RoR::TObjGrass::density
float density
Definition: TObjFileFormat.h:114
RoR::TerrainObjectManager::PredefinedActor::freePosition
bool freePosition
Definition: TerrainObjectManager.h:135
RoR::ODefTexPrint
Definition: ODefFileFormat.h:88
RoR::TObjVehicle::type
TObj::SpecialObject type
Definition: TObjFileFormat.h:130
RoR::TerrainObjectManager::localizer_t::position
Ogre::Vector3 position
Definition: TerrainObjectManager.h:98
RoR::Terrain::getPagedDetailFactor
float getPagedDetailFactor() const
Definition: Terrain.h:67
RoR::ODefSpotlight::dir
Ogre::Vector3 dir
Definition: ODefFileFormat.h:103
RoR::TerrainObjectManager::StaticObject::sceneNode
Ogre::SceneNode * sceneNode
Definition: TerrainObjectManager.h:140
RoR::ODefParser::ProcessOgreStream
void ProcessOgreStream(Ogre::DataStream *stream)
Definition: ODefFileFormat.cpp:30
RoR::MpState::CONNECTED
@ CONNECTED
RoR::TObjGrass::min_y
float min_y
Definition: TObjFileFormat.h:116
RoR::TObjParser
Definition: TObjFileFormat.h:171
RoR::Console::CONSOLE_MSGTYPE_TERRN
@ CONSOLE_MSGTYPE_TERRN
Parsing/spawn/simulation messages for terrain.
Definition: Console.h:64
RoR::TObjGrass::range
int range
Definition: TObjFileFormat.h:108
RoR::Str::GetBuffer
char * GetBuffer()
Definition: Str.h:48
RoR::TerrainObjectManager::LoadTelepoints
void LoadTelepoints()
Definition: TerrainObjectManager.cpp:980
RoR::ODefFile::texture_prints
std::list< ODefTexPrint > texture_prints
Section 'drawTextOnMeshTexture'.
Definition: ODefFileFormat.h:135
RoR::App::GetCameraManager
CameraManager * GetCameraManager()
Definition: Application.cpp:275
RoR::ActorSpawnRequest::asr_origin
Origin asr_origin
Definition: SimData.h:857
RoR::TObjGrass::max_y
float max_y
Definition: TObjFileFormat.h:117
RoR::ODefParser::Finalize
std::shared_ptr< ODefFile > Finalize()
Passes ownership.
Definition: ODefFileFormat.cpp:61
RoR::Collisions::addCollisionBox
int addCollisionBox(bool rotating, bool virt, Ogre::Vector3 pos, Ogre::Vector3 rot, Ogre::Vector3 l, Ogre::Vector3 h, Ogre::Vector3 sr, const Ogre::String &eventname, const Ogre::String &instancename, bool forcecam, Ogre::Vector3 campos, Ogre::Vector3 sc=Ogre::Vector3::UNIT_SCALE, Ogre::Vector3 dr=Ogre::Vector3::ZERO, CollisionEventFilter event_filter=EVENT_ALL, int scripthandler=-1)
Definition: Collisions.cpp:401
RoR::SoundScriptInstance::ACTOR_ID_TERRAIN_OBJECT
static const int ACTOR_ID_TERRAIN_OBJECT
Definition: SoundScriptManager.h:270
RoR::TObjVehicle::rotation
Ogre::Quaternion rotation
Definition: TObjFileFormat.h:128
RoR::ODefTexPrint::r
float r
Definition: ODefFileFormat.h:97
RoR::TerrainObjectManager::m_map_entities
SurveyMapEntityVec m_map_entities
Definition: TerrainObjectManager.h:165
z
float z
Definition: (ValueTypes) quaternion.h:7
RoR::TerrainObjectManager::PredefinedActor::ismachine
bool ismachine
Definition: TerrainObjectManager.h:134
RoR::TObjGrass::sway_distrib
float sway_distrib
Definition: TObjFileFormat.h:113
RoR::TObjParser::Prepare
void Prepare()
Definition: TObjFileFormat.cpp:58
RoR::TerrainObjectManager::LoadTObjFile
void LoadTObjFile(Ogre::String filename)
Definition: TerrainObjectManager.cpp:149
MeshObject::getEntity
Ogre::Entity * getEntity()
Definition: MeshObject.h:43
RoR::TerrainObjectManager::EditorObject::name
Ogre::String name
Definition: TerrainObjectManager.h:56
RoR::TObjTree::yaw_to
float yaw_to
Definition: TObjFileFormat.h:76
RoR::Terrain::getTerrainFileResourceGroup
std::string getTerrainFileResourceGroup()
Definition: Terrain.cpp:555
format
Truck file format(technical spec)
RoR::ODefCollisionBox::cam_pos
Ogre::Vector3 cam_pos
Definition: ODefFileFormat.h:51
RoR::TObj::SpecialObject::TRUCK2
@ TRUCK2
RoR::Terrain::getObjectManager
TerrainObjectManager * getObjectManager()
Definition: Terrain.h:77
RoR::TObjGrass::min_x
float min_x
Definition: TObjFileFormat.h:116
AutoPilot.h
RoR::ODefCollisionBox::is_virtual
bool is_virtual
Definition: ODefFileFormat.h:59
GenerateGridAndPutToScene
void GenerateGridAndPutToScene(Ogre::Vector3 position)
Definition: TerrainObjectManager.cpp:95
RoR::ODefTexPrint::a
float a
Definition: ODefFileFormat.h:97
RoR::TerrainObjectManager::m_editor_objects
std::vector< EditorObject > m_editor_objects
Definition: TerrainObjectManager.h:161
ExtinguishableFireAffector.h
RoR::HandleGenericException
void HandleGenericException(const std::string &from, BitMask_t flags)
Definition: Application.cpp:369
RoR::TerrainObjectManager::EditorObject
Definition: TerrainObjectManager.h:54
TerrainGeometryManager.h
RoR::TObjEntry::rendering_distance
float rendering_distance
Definition: TObjFileFormat.h:150
RoR::CVar::getBool
bool getBool() const
Definition: CVar.h:98
TObjFileFormat.h
Parser and data structures for TOBJ (Terrain Objects) file format.
RoR::ODefParticleSys::template_name
std::string template_name
Definition: ODefFileFormat.h:77
RoR::TObjEntry::instance_name
char instance_name[TObj::STR_LEN]
Definition: TObjFileFormat.h:148
RoR::ODefPointLight
Definition: ODefFileFormat.h:110
RoR::Terrain::GetDef
Terrn2Def & GetDef()
Definition: Terrain.h:63
MeshObject.h
RoR::TerrainObjectManager::terrainManager
Terrain * terrainManager
Definition: TerrainObjectManager.h:166
Console.h
RoR::TerrainObjectManager::ProcessODefCollisionBoxes
void ProcessODefCollisionBoxes(StaticObject *obj, ODefFile *odef, const EditorObject &params, bool race_event)
Definition: TerrainObjectManager.cpp:1022
RoR::Console::putMessage
void putMessage(MessageArea area, MessageType type, std::string const &msg, std::string icon="")
Definition: Console.cpp:97
RoR::TerrainObjectManager::getGroupingSceneNode
Ogre::SceneNode * getGroupingSceneNode()
Definition: TerrainObjectManager.cpp:1055
RoR::CacheEntry::resource_group
Ogre::String resource_group
Resource group of the loaded bundle. Empty if not loaded yet.
Definition: CacheSystem.h:89
RoR::Collisions::addCollisionMesh
void addCollisionMesh(Ogre::String const &srcname, Ogre::String const &meshname, Ogre::Vector3 const &pos, Ogre::Quaternion const &q, Ogre::Vector3 const &scale, ground_model_t *gm=0, std::vector< int > *collTris=0)
generate collision tris from existing mesh resource
Definition: Collisions.cpp:1408
RoR::ODefTexPrint::x
float x
Definition: ODefFileFormat.h:96
RoR::ODefCollisionBox::scale
Ogre::Vector3 scale
Definition: ODefFileFormat.h:53
RoR::ODefTexPrint::font_dpi
int font_dpi
Definition: ODefFileFormat.h:92
RoR::ODefCollisionBox::is_rotating
bool is_rotating
Definition: ODefFileFormat.h:58
RoR::TObjTree::min_distance
float min_distance
Definition: TObjFileFormat.h:78
RoR::ScriptEngine::loadScript
ScriptUnitId_t loadScript(Ogre::String scriptname, ScriptCategory category=ScriptCategory::TERRAIN, ActorPtr associatedActor=nullptr, std::string buffer="")
Loads a script.
Definition: ScriptEngine.cpp:759
RoR::TerrainObjectManager::LoadTerrainObject
bool LoadTerrainObject(const Ogre::String &name, const Ogre::Vector3 &pos, const Ogre::Vector3 &rot, const Ogre::String &instancename, const Ogre::String &type, float rendering_distance=0, bool enable_collisions=true, int scripthandler=-1, bool uniquifyMaterial=false)
Definition: TerrainObjectManager.cpp:577
RoR::TObjEntry::odef_name
char odef_name[TObj::STR_LEN]
Definition: TObjFileFormat.h:149
RoR::TerrainObjectManager::AnimatedObject
Definition: TerrainObjectManager.h:119
Utils.h
RoR::TerrainObjectManager::LoadTerrainScript
bool LoadTerrainScript(const Ogre::String &filename)
Definition: TerrainObjectManager.cpp:951
RoR::ActorSpawnRequest::asr_filename
std::string asr_filename
Definition: SimData.h:849
RoR::ODefCollisionMesh::groundmodel_name
std::string groundmodel_name
Definition: ODefFileFormat.h:71
RoR::TerrainObjectManager::m_mesh_objects
std::vector< MeshObject * > m_mesh_objects
Definition: TerrainObjectManager.h:164
RoR::ODefFile::collision_boxes
std::list< ODefCollisionBox > collision_boxes
Definition: ODefFileFormat.h:131
Language.h
RoR::ODefCollisionBox::aabb_max
Ogre::Vector3 aabb_max
Definition: ODefFileFormat.h:49
RoR::TerrainObjectManager::EditorObject::enable_collisions
bool enable_collisions
Definition: TerrainObjectManager.h:64
RoR::TObjGrass::material_name
char material_name[TObj::STR_LEN]
Definition: TObjFileFormat.h:119
TerrainObjectManager.h
RefCountingObjectPtr< ProceduralObject >
RoR::TerrainObjectManager::LoadPredefinedActors
void LoadPredefinedActors()
Definition: TerrainObjectManager.cpp:988
RoR::Console::CONSOLE_SYSTEM_ERROR
@ CONSOLE_SYSTEM_ERROR
Definition: Console.h:52
RoR::TerrainObjectManager::localizer_t::rotation
Ogre::Quaternion rotation
Definition: TerrainObjectManager.h:99
GUIManager.h
RoR::Collisions::removeCollisionTri
void removeCollisionTri(int number)
Definition: Collisions.cpp:356
RoR::Terrn2Telepoint
< Teleport drop location
Definition: Terrn2FileFormat.h:42
RoR::ODefFile::header
struct RoR::ODefFile::ODefFileHeader header
Actor.h
RoR::TerrainObjectManager::MoveObjectVisuals
void MoveObjectVisuals(const Ogre::String &instancename, const Ogre::Vector3 &pos)
Definition: TerrainObjectManager.cpp:489
RoR::ProceduralManager
Definition: ProceduralManager.h:79
RoR::App::GetScriptEngine
ScriptEngine * GetScriptEngine()
Definition: Application.cpp:279
RoR::TerrainObjectManager::FetchODef
RoR::ODefFile * FetchODef(std::string const &odef_name)
Definition: TerrainObjectManager.cpp:535
RoR::GfxScene::GetSceneManager
Ogre::SceneManager * GetSceneManager()
Definition: GfxScene.h:64
w
float w
Definition: (ValueTypes) quaternion.h:4
RoR::TerrainObjectManager::EditorObject::instance_name
Ogre::String instance_name
Definition: TerrainObjectManager.h:57
RoR::ActorSpawnRequest
Definition: SimData.h:832
RoR::TObjGrass::max_h
float max_h
Definition: TObjFileFormat.h:117
RoR::TerrainObjectManager::AnimatedObject::ent
Ogre::Entity * ent
Definition: TerrainObjectManager.h:121
RoR::ODefParticleSys::instance_name
std::string instance_name
Definition: ODefFileFormat.h:76
RoR::Terrain::GetHeightAt
float GetHeightAt(float x, float z)
Definition: Terrain.cpp:503
RoR::App::mp_state
CVar * mp_state
Definition: Application.cpp:115
RoR::TObjTree::density_map
char density_map[TObj::STR_LEN]
Definition: TObjFileFormat.h:84
RoR::TObjEntry
Definition: TObjFileFormat.h:134
RoR::SCRIPTUNITID_INVALID
static const ScriptUnitId_t SCRIPTUNITID_INVALID
Definition: ForwardDeclarations.h:41
RoR::Collisions::loadGroundModelsConfigFile
int loadGroundModelsConfigFile(Ogre::String filename)
Definition: Collisions.cpp:150
ProceduralRoad.h
TOSTRING
#define TOSTRING(x)
Definition: Application.h:56
RoR::TObjGrass::sway_length
float sway_length
Definition: TObjFileFormat.h:112
RoR::PATH_SLASH
char PATH_SLASH
Definition: PlatformUtils.cpp:161
RoR::TObjEntry::rotation
Ogre::Vector3 rotation
Definition: TObjFileFormat.h:145
RoR::TerrainObjectManager::m_entity_counter
int m_entity_counter
Definition: TerrainObjectManager.h:168
RoR::ODefTexPrint::g
float g
Definition: ODefFileFormat.h:97
RoR::TerrainGeometryManager::getMaxTerrainSize
Ogre::Vector3 getMaxTerrainSize()
Definition: TerrainGeometryManager.cpp:689
RoR::TerrainObjectManager::StaticObject::instanceName
Ogre::String instanceName
Definition: TerrainObjectManager.h:141
RoR::ODefCollisionMesh
Definition: ODefFileFormat.h:63
RoR::ODefFile::groundmodel_files
std::list< std::string > groundmodel_files
Definition: ODefFileFormat.h:130
RoR::Str
Wrapper for classic c-string (local buffer) Refresher: strlen() excludes '\0' terminator; strncat() A...
Definition: Str.h:35
RoR::Collisions::removeCollisionBox
void removeCollisionBox(int number)
Definition: Collisions.cpp:343
RoR::Collisions::getGroundModelByString
ground_model_t * getGroundModelByString(const Ogre::String name)
Definition: Collisions.cpp:365
RoR::ODefSpotlight::angle_outer
float angle_outer
Degrees.
Definition: ODefFileFormat.h:106
RoR::TerrainObjectManager::ProcessGrass
void ProcessGrass(float SwaySpeed, float SwayLength, float SwayDistribution, float Density, float minx, float miny, float minH, float maxx, float maxy, float maxH, char *grassmat, char *colorMapFilename, char *densityMapFilename, int growtechnique, int techn, int range, int mapsizex, int mapsizez)
Definition: TerrainObjectManager.cpp:416
GUI_LoadingWindow.h
CacheSystem.h
A database of user-installed content alias 'mods' (vehicles, terrains...)
RoR::TObjGrass::technique
int technique
Definition: TObjFileFormat.h:109
ErrorUtils.h
RoR::GfxVegetation::NONE
@ NONE
ScriptEngine.h
RoR::TerrainObjectManager::AnimatedObject::node
Ogre::SceneNode * node
Definition: TerrainObjectManager.h:122
RoR::TObjGrass::density_map_filename
char density_map_filename[TObj::STR_LEN]
Definition: TObjFileFormat.h:121
RoR::TerrainObjectManager::m_terrn2_grouping_node
Ogre::SceneNode * m_terrn2_grouping_node
For a readable scene graph (via inspector script)
Definition: TerrainObjectManager.h:169
RoR::GameContext::PushMessage
void PushMessage(Message m)
Doesn't guarantee order! Use ChainMessage() if order matters.
Definition: GameContext.cpp:65
strnlen
#define strnlen(str, len)
Definition: InputEngine.cpp:397
RoR::App::app_state
CVar * app_state
Definition: Application.cpp:79
RoR::Terrain::getGeometryManager
TerrainGeometryManager * getGeometryManager()
Definition: Terrain.h:75
RoR::ScriptUnitId_t
int ScriptUnitId_t
Unique sequentially generated ID of a loaded and running scriptin session. Use ScriptEngine::getScrip...
Definition: ForwardDeclarations.h:40
RoR::ODefFile::collision_meshes
std::list< ODefCollisionMesh > collision_meshes
Definition: ODefFileFormat.h:132
RoR::ODefFile::animations
std::list< ODefAnimation > animations
Definition: ODefFileFormat.h:134
RoR::Str::ToCStr
const char * ToCStr() const
Definition: Str.h:46
ODefFileFormat.h
RoR::Terrain::GetCollisions
Collisions * GetCollisions()
Definition: Terrain.h:83
RoR::App::sys_cache_dir
CVar * sys_cache_dir
Definition: Application.cpp:165
RoR::ODefParticleSys
Definition: ODefFileFormat.h:74
GfxScene.h
RoR::TerrainObjectManager::m_predefined_actors
std::vector< PredefinedActor > m_predefined_actors
Definition: TerrainObjectManager.h:162
PlatformUtils.h
Platform-specific utilities. We use narrow UTF-8 encoded strings as paths. Inspired by http://utf8eve...
RoR::ODefFile::ODefFileHeader::scale
Ogre::Vector3 scale
Definition: ODefFileFormat.h:123
RoR::TerrainObjectManager::StaticObject::collTris
std::vector< int > collTris
Definition: TerrainObjectManager.h:144
RoR::SoundScriptManager::createInstance
SoundScriptInstancePtr createInstance(Ogre::String templatename, int actor_id, int soundLinkType=SL_DEFAULT, int soundLinkItemId=-1)
Definition: SoundScriptManager.cpp:356
RoR::App::sim_races_enabled
CVar * sim_races_enabled
Definition: Application.cpp:105
MeshObject
Definition: MeshObject.h:35
RoR::TObjVehicle::position
Ogre::Vector3 position
Definition: TObjFileFormat.h:127
Application.h
Central state/object manager and communications hub.
RoR::TerrainObjectManager::m_procedural_manager
ProceduralManagerPtr m_procedural_manager
Definition: TerrainObjectManager.h:167
RoR::App::GetConsole
Console * GetConsole()
Definition: Application.cpp:270
RoR::TerrainObjectManager::m_animated_objects
std::vector< AnimatedObject > m_animated_objects
Definition: TerrainObjectManager.h:163
RoR::TerrainObjectManager::PredefinedActor::py
float py
Definition: TerrainObjectManager.h:130
RoR::Terrn2Def::telepoints
std::list< Terrn2Telepoint > telepoints
Definition: Terrn2FileFormat.h:67
SoundScriptManager.h
RoR::App::GetGameContext
GameContext * GetGameContext()
Definition: Application.cpp:280
RoR::ODefCollisionBox::box_rot
Ogre::Vector3 box_rot
Definition: ODefFileFormat.h:50
RoR::AppState::SIMULATION
@ SIMULATION
RoR::ODefCollisionBox::force_cam_pos
bool force_cam_pos
Definition: ODefFileFormat.h:60
RoR::TerrainObjectManager::PredefinedActor::name
std::string name
Definition: TerrainObjectManager.h:133
RoR::TObjTree::tree_mesh
char tree_mesh[TObj::STR_LEN]
Definition: TObjFileFormat.h:82
RoR::ActorSpawnRequest::Origin::TERRN_DEF
@ TERRN_DEF
Preloaded with terrain.
getTerrainHeight
float getTerrainHeight(Real x, Real z, void *unused=0)
Definition: TerrainObjectManager.cpp:62
RoR::ActorSpawnRequest::asr_terrn_machine
bool asr_terrn_machine
This is a fixed machinery.
Definition: SimData.h:865
RoR::TObjGrass::sway_speed
float sway_speed
Definition: TObjFileFormat.h:111
RoR::ODefFile::spotlights
std::list< ODefSpotlight > spotlights
Definition: ODefFileFormat.h:136
RoR::TObjEntry::type
char type[TObj::STR_LEN]
Definition: TObjFileFormat.h:147
RoR::TerrainObjectManager::AnimatedObject::anim
Ogre::AnimationState * anim
Definition: TerrainObjectManager.h:123
RoR::ODefPointLight::pos
Ogre::Vector3 pos
Definition: ODefFileFormat.h:112
Ogre::ExtinguishableFireAffector
This class defines a ParticleAffector which deflects particles.
Definition: ExtinguishableFireAffector.h:45
RoR::TerrainObjectManager::localizers
std::vector< localizer_t > localizers
Definition: TerrainObjectManager.h:158
RoR::TObjTree::scale_from
float scale_from
Definition: TObjFileFormat.h:77
RoR::ODefFile::point_lights
std::list< ODefPointLight > point_lights
Definition: ODefFileFormat.h:137
RoR::TObjTree::max_distance
float max_distance
Definition: TObjFileFormat.h:78
RoR::ODefPointLight::dir
Ogre::Vector3 dir
Definition: ODefFileFormat.h:113
RoR::ODefPointLight::range
float range
Definition: ODefFileFormat.h:114
RoR::Terrain
Definition: Terrain.h:40
RoR::App::GetCacheSystem
CacheSystem * GetCacheSystem()
Definition: Application.cpp:272
RoR::ODefCollisionBox
Definition: ODefFileFormat.h:37
RoR::ODefTexPrint::font_name
std::string font_name
Definition: ODefFileFormat.h:90
RoR::TObjParser::ProcessOgreStream
void ProcessOgreStream(Ogre::DataStream *stream)
Definition: TObjFileFormat.cpp:203
RoR::TObjTree::grid_spacing
float grid_spacing
Definition: TObjFileFormat.h:80
RoR::TerrainObjectManager::m_static_objects
std::map< std::string, StaticObject > m_static_objects
Definition: TerrainObjectManager.h:160
RoR::ODefSpotlight::color
Ogre::ColourValue color
Definition: ODefFileFormat.h:107
RoR::ODefSpotlight::pos
Ogre::Vector3 pos
Definition: ODefFileFormat.h:102
WriteToTexture
void WriteToTexture(const String &str, TexturePtr destTexture, Ogre::Box destRectangle, Ogre::Font *Reffont, const ColourValue &color, int fontSize, int fontDPI, char justify, bool wordwrap)
Definition: WriteTextToTexture.cpp:52
RoR::TerrainObjectManager::UpdateTerrainObjects
bool UpdateTerrainObjects(float dt)
Definition: TerrainObjectManager.cpp:1009
RoR::TerrainObjectManager::ProcessTree
void ProcessTree(float yawfrom, float yawto, float scalefrom, float scaleto, char *ColorMap, char *DensityMap, char *treemesh, char *treeCollmesh, float gridspacing, float highdens, int minDist, int maxDist, int mapsizex, int mapsizez)
Definition: TerrainObjectManager.cpp:291
RoR::TerrainObjectManager::PredefinedActor::pz
float pz
Definition: TerrainObjectManager.h:131
RoR::ODefCollisionBox::direction
Ogre::Vector3 direction
Definition: ODefFileFormat.h:52
RoR::Message
Unified game event system - all requests and state changes are reported using a message.
Definition: GameContext.h:51
RoR::TerrainObjectManager::PredefinedActor
Definition: TerrainObjectManager.h:127
RoR::TerrainObjectManager::PredefinedActor::px
float px
Definition: TerrainObjectManager.h:129
_L
#define _L
Definition: ErrorUtils.cpp:34
RoR::ODefPointLight::color
Ogre::ColourValue color
Definition: ODefFileFormat.h:115
RoR::TObjGrass::color_map_filename
char color_map_filename[TObj::STR_LEN]
Definition: TObjFileFormat.h:120
RoR::TObjTree::high_density
float high_density
Definition: TObjFileFormat.h:79
RoR::ODefParser::Prepare
void Prepare()
Definition: ODefFileFormat.cpp:53
RoR::ODefFile::particle_systems
std::list< ODefParticleSys > particle_systems
Definition: ODefFileFormat.h:133
RoR::TObjVehicle::name
char name[TObj::STR_LEN]
Definition: TObjFileFormat.h:129
RoR::TerrainObjectManager::m_odef_cache
std::unordered_map< std::string, std::shared_ptr< RoR::ODefFile > > m_odef_cache
Definition: TerrainObjectManager.h:159
RoR::TObjGrass::max_x
float max_x
Definition: TObjFileFormat.h:117
RoR::ODefTexPrint::b
float b
Definition: ODefFileFormat.h:97
RoR::ODefAnimation::speed_min
float speed_min
Definition: ODefFileFormat.h:84
RoR::Terrain::getCacheEntry
CacheEntryPtr getCacheEntry()
Definition: Terrain.cpp:575
RoR::TObjGrass
Unified 'grass' and 'grass2'.
Definition: TObjFileFormat.h:90
RoR::MSG_SIM_SPAWN_ACTOR_REQUESTED
@ MSG_SIM_SPAWN_ACTOR_REQUESTED
Payload = RoR::ActorSpawnRequest* (owner)
Definition: Application.h:119
RoR::LocalizerType
LocalizerType
Definition: SimData.h:251
RoR::TerrainObjectManager::~TerrainObjectManager
~TerrainObjectManager()
Definition: TerrainObjectManager.cpp:75
RoR::ODefCollisionMesh::scale
Ogre::Vector3 scale
Definition: ODefFileFormat.h:70
RoR::TObjGrass::grow_techniq
int grow_techniq
Definition: TObjFileFormat.h:110
RoR::ProceduralManager::logDiagnostics
void logDiagnostics()
Definition: ProceduralManager.cpp:180
RoR::TerrainObjectManager::unloadObject
void unloadObject(const Ogre::String &instancename)
Definition: TerrainObjectManager.cpp:505
RoR::TObjTree::color_map
char color_map[TObj::STR_LEN]
Definition: TObjFileFormat.h:83
RoR::TObjTree
Definition: TObjFileFormat.h:61
RoR::ODefCollisionBox::aabb_min
Ogre::Vector3 aabb_min
Definition: ODefFileFormat.h:48
RoR::ODefFile::mat_name_generate
std::string mat_name_generate
Section 'generateMaterialShaders'.
Definition: ODefFileFormat.h:139
RoR::TerrainObjectManager::localizer_t
Definition: TerrainObjectManager.h:95
Terrain.h
RoR::ODefCollisionMesh::mesh_name
std::string mesh_name
Definition: ODefFileFormat.h:69
RoR::ProceduralObject::name
std::string name
Definition: ProceduralManager.h:73
Ogre
Definition: ExtinguishableFireAffector.cpp:35
WriteTextToTexture.h
RoR::TObjTree::scale_to
float scale_to
Definition: TObjFileFormat.h:77
RoR::TerrainObjectManager::m_angelscript_grouping_node
Ogre::SceneNode * m_angelscript_grouping_node
For even more readable scene graph (via inspector script)
Definition: TerrainObjectManager.h:171
RoR::Console::CONSOLE_SYSTEM_WARNING
@ CONSOLE_SYSTEM_WARNING
Definition: Console.h:53
RoR::ODefTexPrint::font_size
int font_size
Definition: ODefFileFormat.h:91
RoR::TObjEntry::position
Ogre::Vector3 position
Definition: TObjFileFormat.h:144
RoR::TObjParser::Finalize
std::shared_ptr< TObjFile > Finalize()
Passes ownership.
Definition: TObjFileFormat.cpp:185
RoR::ODefParser
Definition: ODefFileFormat.h:143
RoR::ODefAnimation::speed_max
float speed_max
Definition: ODefFileFormat.h:84
RoR::ODefFile::ODefFileHeader::mesh_name
std::string mesh_name
Definition: ODefFileFormat.h:122
RoR::TerrainObjectManager::EditorObject::position
Ogre::Vector3 position
Definition: TerrainObjectManager.h:59
RoR::App::gfx_vegetation_mode
CVar * gfx_vegetation_mode
Definition: Application.cpp:223
RoR::ODefFile
Definition: ODefFileFormat.h:118
RoR::TObjVehicle
Definition: TObjFileFormat.h:125
RoR::ActorSpawnRequest::asr_position
Ogre::Vector3 asr_position
Definition: SimData.h:851
RoR::ODefTexPrint::w
float w
Definition: ODefFileFormat.h:96
RoR::TerrainObjectManager::StaticObject::collBoxes
std::vector< int > collBoxes
Definition: TerrainObjectManager.h:143
Collisions.h
RoR::App::diag_terrn_log_roads
CVar * diag_terrn_log_roads
Definition: Application.cpp:157
RoR::TerrainObjectManager::EditorObject::script_handler
int script_handler
Definition: TerrainObjectManager.h:65
RoR::TerrainObjectManager::StaticObject
Definition: TerrainObjectManager.h:138
RoR::DEPTHMAP_DISABLED
@ DEPTHMAP_DISABLED
Definition: Application.h:285
RoR::Terrn2Def::name
std::string name
Definition: Terrn2FileFormat.h:52
RoR::TerrainObjectManager::PredefinedActor::rotation
Ogre::Quaternion rotation
Definition: TerrainObjectManager.h:132
RoR::SurveyMapEntity
Definition: SurveyMapEntity.h:35
RoR::TObjGrass::min_h
float min_h
Definition: TObjFileFormat.h:116
RoR::ODefFile::sounds
std::list< std::string > sounds
Definition: ODefFileFormat.h:129
RoR::ODefTexPrint::text
std::string text
Definition: ODefFileFormat.h:93
RoR::TerrainObjectManager::AnimatedObject::speedfactor
float speedfactor
Definition: TerrainObjectManager.h:124
RoR::ODefFile::localizers
std::vector< LocalizerType > localizers
Definition: ODefFileFormat.h:128
RoR::ODefFile::ODefFileHeader::cast_shadows
bool cast_shadows
Definition: ODefFileFormat.h:124
Forests
Definition: RandomTreeLoader.h:32
RoR::ActorSpawnRequest::asr_rotation
Ogre::Quaternion asr_rotation
Definition: SimData.h:852
RoR
Definition: AppContext.h:36
RoR::ODefFile::mat_name
std::string mat_name
Section 'setMeshMaterial'.
Definition: ODefFileFormat.h:138
RoR::Str::Clear
Str & Clear()
Definition: Str.h:54
RoR::TerrainObjectManager::m_tobj_grouping_node
Ogre::SceneNode * m_tobj_grouping_node
For even more readable scene graph (via inspector script)
Definition: TerrainObjectManager.h:170
x
float x
Definition: (ValueTypes) quaternion.h:5
RoR::SoundScriptInstance::setPosition
void setPosition(Ogre::Vector3 pos)
Definition: SoundScriptManager.cpp:1310
RoR::ODefAnimation
Definition: ODefFileFormat.h:82
RoR::App::GetGfxScene
GfxScene * GetGfxScene()
Definition: Application.cpp:276
RoR::TerrainObjectManager::StaticObject::enabled
bool enabled
Definition: TerrainObjectManager.h:142
RoR::ODefSpotlight
Definition: ODefFileFormat.h:100
RoR::Terrain::getWater
IWater * getWater()
Definition: Terrain.h:84
RoR::ODefCollisionBox::event_name
std::string event_name
Definition: ODefFileFormat.h:54
RoR::ODefCollisionBox::event_filter
CollisionEventFilter event_filter
Definition: ODefFileFormat.h:55
RoR::TObjTree::collision_mesh
char collision_mesh[TObj::STR_LEN]
Definition: TObjFileFormat.h:85
RoR::TObjTree::yaw_from
float yaw_from
Definition: TObjFileFormat.h:76
RoR::ODefTexPrint::h
float h
Definition: ODefFileFormat.h:96
RoR::GameContext::GetTerrain
const TerrainPtr & GetTerrain()
Definition: GameContext.h:117
RoR::ODefSpotlight::angle_inner
float angle_inner
Degrees.
Definition: ODefFileFormat.h:105