Rigs of Rods 2023.09
Soft-body Physics Simulation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
TerrainEditor.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 "TerrainEditor.h"
23
24#include "AppContext.h"
25#include "Actor.h"
26#include "CameraManager.h"
27#include "Console.h"
28#include "ContentManager.h"
29#include "GameContext.h"
30#include "GfxScene.h"
31#include "InputEngine.h"
32#include "OgreImGui.h"
33#include "Terrain.h"
35#include "TObjFileFormat.h"
36#include "PlatformUtils.h"
37
38using namespace RoR;
39using namespace Ogre;
40
41const TerrainEditorObjectPtr TerrainEditor::TERRAINEDITOROBJECTPTR_NULL; // Dummy value to be returned as const reference.
42
44{
46
47 if (ImGui::IsMouseClicked(2)) // Middle button
48 {
49 ImVec2 mouse_screen = ImGui::GetIO().MousePos / ImGui::GetIO().DisplaySize;
50 Ogre::Ray terrain_editor_mouse_ray = App::GetCameraManager()->GetCamera()->getCameraToViewportRay(mouse_screen.x, mouse_screen.y);
51
52 float min_dist = std::numeric_limits<float>::max();
53 Vector3 origin = terrain_editor_mouse_ray.getOrigin();
54 Vector3 direction = terrain_editor_mouse_ray.getDirection();
55 for (int i = 0; i < (int)object_list.size(); i++)
56 {
57 Real ray_object_distance = direction.crossProduct(object_list[i]->getPosition() - origin).length();
58 if (ray_object_distance < min_dist)
59 {
60 min_dist = ray_object_distance;
61 this->SetSelectedObjectByID(i);
62 }
63 }
64 }
65 if (m_selected_object_id != -1)
66 {
67 m_last_object_name = object_list[m_selected_object_id]->name;
68 }
69 if (App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_ENTER_OR_EXIT_TRUCK))
70 {
71 if (m_selected_object_id == -1)
72 {
73 // Select nearest object
75 ? App::GetCameraManager()->GetCameraNode()->getPosition()
77 float min_dist = std::numeric_limits<float>::max();
78 for (int i = 0; i < (int)object_list.size(); i++)
79 {
80 float dist = ref_pos.squaredDistance(object_list[i]->getPosition());
81 if (dist < min_dist)
82 {
83 this->SetSelectedObjectByID(i);
84 min_dist = dist;
85 }
86 }
87 }
88 else
89 {
91 }
92 }
93 else if (App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_RESPAWN_LAST_TRUCK) &&
95 {
97
98 try
99 {
100 App::GetGameContext()->GetTerrain()->getObjectManager()->LoadTerrainObject(m_last_object_name, pos, Vector3::ZERO, "Console", "");
101
102 App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_REPLY, _L("Spawned object at position: ") + String("x: ") + TOSTRING(pos.x) + String("z: ") + TOSTRING(pos.z), "world.png");
103 }
104 catch (std::exception& e)
105 {
107 }
108 }
109 else if (App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_ENTER_NEXT_TRUCK, 0.25f))
110 {
111 if (object_list.size() > 0)
112 {
113 TerrainEditorObjectID_t i = (m_selected_object_id + 1 + (int)object_list.size()) % object_list.size();
114 this->SetSelectedObjectByID(i);
115 }
116 }
117 else if (App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_ENTER_PREVIOUS_TRUCK, 0.25f))
118 {
119 if (object_list.size() > 0)
120 {
121 TerrainEditorObjectID_t i = (m_selected_object_id - 1 + (int)object_list.size()) % object_list.size();
122 this->SetSelectedObjectByID(i);
123 }
124 }
125 if (App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_RESCUE_TRUCK))
126 {
127 std::string axis = _L("ry");
128 if (m_rotation_axis == 0)
129 {
130 axis = _L("ry");
131 m_rotation_axis = 1;
132 }
133 else if (m_rotation_axis == 1)
134 {
135 axis = _L("rz");
136 m_rotation_axis = 2;
137 }
138 else if (m_rotation_axis == 2)
139 {
140 axis = _L("rx");
141 m_rotation_axis = 0;
142 }
143 std::string ssmsg = _L("Rotating: ") + axis;
145 }
146 if (App::GetInputEngine()->isKeyDownValueBounce(OIS::KC_SPACE))
147 {
149 std::string ssmsg = m_object_tracking ? _L("Enabled object tracking") : _L("Disabled object tracking");
151 }
152 if (m_selected_object_id != -1 && App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_RESET_TRUCK))
153 {
154 object_list[m_selected_object_id]->setPosition(object_list[m_selected_object_id]->initial_position);
155 object_list[m_selected_object_id]->setRotation(object_list[m_selected_object_id]->initial_rotation);
156 }
158 {
159 Vector3 translation = Vector3::ZERO;
160 float rotation = 0.0f;
161
162 if (App::GetInputEngine()->getEventBoolValue(EV_TRUCK_STEER_LEFT))
163 {
164 rotation += 2.0f;
165 }
166 else if (App::GetInputEngine()->getEventBoolValue(EV_TRUCK_STEER_RIGHT))
167 {
168 rotation -= 2.0f;
169 }
170 if (App::GetInputEngine()->getEventBoolValue(EV_TRUCK_ACCELERATE))
171 {
172 translation.y += 0.5f;
173 }
174 else if (App::GetInputEngine()->getEventBoolValue(EV_TRUCK_BRAKE))
175 {
176 translation.y -= 0.5f;
177 }
178 if (App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_FORWARD))
179 {
180 translation.x += 0.5f;
181 }
182 else if (App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_BACKWARDS))
183 {
184 translation.x -= 0.5f;
185 }
186 if (App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_SIDESTEP_RIGHT))
187 {
188 translation.z += 0.5f;
189 }
190 else if (App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_SIDESTEP_LEFT))
191 {
192 translation.z -= 0.5f;
193 }
194
195 if (translation != Vector3::ZERO || rotation != 0.0f)
196 {
197 float scale = App::GetInputEngine()->isKeyDown(OIS::KC_LMENU) ? 0.1f : 1.0f;
198 scale *= App::GetInputEngine()->isKeyDown(OIS::KC_LSHIFT) ? 3.0f : 1.0f;
199 scale *= App::GetInputEngine()->isKeyDown(OIS::KC_LCONTROL) ? 10.0f : 1.0f;
200
201 Ogre::Vector3 new_position = object_list[m_selected_object_id]->getPosition();
202 new_position += translation * scale * dt;
203 object_list[m_selected_object_id]->setPosition(new_position);
204
205 Ogre::Vector3 new_rotation = object_list[m_selected_object_id]->getRotation();
206 new_rotation[m_rotation_axis] += rotation * scale * dt;
207 object_list[m_selected_object_id]->setRotation(new_rotation);
208
210 {
212 }
213 }
214 else if (m_object_tracking && App::GetGameContext()->GetPlayerCharacter()->getPosition() != object_list[m_selected_object_id]->getPosition())
215 {
216 object_list[m_selected_object_id]->setPosition(App::GetGameContext()->GetPlayerCharacter()->getPosition());
217 }
218 if (App::GetInputEngine()->getEventBoolValue(EV_COMMON_REMOVE_CURRENT_TRUCK))
219 {
221 }
222 }
223 else
224 {
226 }
227
228 if (App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_TOGGLE_TERRAIN_EDITOR))
229 {
231 }
232}
233
235{
236 // FIXME: This code was originally removed in favor of `TObjFileFormat::WriteToStream()`
237 // but later brought back due to bugs - there is duplication.
238 // ====================================================================================
239
240
241 const char* filename = "editor_out.log";
242 std::string editor_logpath = PathCombine(App::sys_logs_dir->getStr(), filename);
243 try
244 {
245 Ogre::DataStreamPtr stream
246 = Ogre::ResourceGroupManager::getSingleton().createResource(
247 editor_logpath, RGN_CONFIG, /*overwrite=*/true);
248
250 {
251 SceneNode* sn = object->static_object_node;
252 if (sn != nullptr)
253 {
254 String pos = StringUtil::format("%8.3f, %8.3f, %8.3f", object->position.x, object->position.y, object->position.z);
255 String rot = StringUtil::format("% 6.1f, % 6.1f, % 6.1f", object->rotation.x, object->rotation.y, object->rotation.z);
256
257 String line = pos + ", " + rot + ", " + object->name + "\n";
258 stream->write(line.c_str(), line.length());
259 }
260 }
261
262 // Export procedural roads
264 for (int i = 0; i < num_roads; i++)
265 {
267 int num_points = obj->getNumPoints();
268 if (num_points > 0)
269 {
270 stream->write("\nbegin_procedural_roads\n", 24);
271 for (int j = 0; j < num_points; j++)
272 {
273 ProceduralPointPtr point = obj->getPoint(j);
274 std::string type_str;
275 switch (point->type)
276 {
277 case RoadType::ROAD_AUTOMATIC: type_str = "auto"; break;
278 case RoadType::ROAD_FLAT: type_str = "flat"; break;
279 case RoadType::ROAD_LEFT: type_str = "left"; break;
280 case RoadType::ROAD_RIGHT: type_str = "right"; break;
281 case RoadType::ROAD_BOTH: type_str = "both"; break;
282 case RoadType::ROAD_BRIDGE: type_str = (point->pillartype == 1) ? "bridge" : "bridge_no_pillars"; break;
283 case RoadType::ROAD_MONORAIL: type_str = (point->pillartype == 2) ? "monorail" : "monorail2"; break;
284 }
285
286 Ogre::Matrix3 point_rot_matrix;
287 point->rotation.ToRotationMatrix(point_rot_matrix);
288 Ogre::Radian yaw, pitch, roll;
289 point_rot_matrix.ToEulerAnglesYXZ(yaw, pitch, roll);
290
291 std::string line = fmt::format(
292 "\t{:13f}, {:13f}, {:13f}, 0, {:13f}, 0, {:13f}, {:13f}, {:13f}, {}\n",
293 point->position.x, point->position.y, point->position.z,
294 yaw.valueDegrees(),
295 point->width, point->bwidth, point->bheight, type_str);
296 stream->write(line.c_str(), line.length());
297 }
298 stream->write("end_procedural_roads\n", 21);
299 }
300 }
301 }
302 catch (std::exception& e)
303 {
304 RoR::LogFormat("[RoR|MapEditor]"
305 "Error saving file '%s' (resource group '%s'), message: '%s'",
306 filename, RGN_CONFIG, e.what());
307 }
308}
309
311{
313
314 // Assert on Debug, minimize harm on Release
315 ROR_ASSERT(terrain);
316 if (!terrain)
317 {
318 return;
319 }
320
321 // If not a project (unzipped), do nothing
322 if (terrain->getCacheEntry()->resource_bundle_type != "FileSystem")
323 {
325 fmt::format("Cannot export terrain editor changes - terrain is not a project"));
326 return;
327 }
328
329 // Loop over TOBJ files in cache, update editable elements and serialize.
330 for (size_t i = 0; i < terrain->getObjectManager()->GetTobjCache().size(); i++)
331 {
332 // Dump original elements and rebuild them from live data.
333 TObjDocumentPtr tobj = terrain->getObjectManager()->GetTobjCache()[i];
334 tobj->objects.clear();
335 tobj->vehicles.clear();
337 {
338 if (src->tobj_cache_id == i)
339 {
340 if (src->special_object_type == TObjSpecialObject::NONE)
341 {
342 TObjEntry dst;
343 strncpy(dst.odef_name, src->name.c_str(), TObj::STR_LEN);
344 strncpy(dst.instance_name, src->instance_name.c_str(), TObj::STR_LEN);
345 strncpy(dst.type, src->type.c_str(), TObj::STR_LEN);
346 // TBD: reconstruct 'set_default_rendering_distance'.
347 dst.position = src->position;
348 dst.rotation = src->rotation;
349 dst.comments = src->tobj_comments;
350
351 tobj->objects.push_back(dst);
352 }
353 else
354 {
355 TObjVehicle dst;
356 strncpy(dst.name, src->name.c_str(), TObj::STR_LEN);
357 dst.position = src->position;
358 dst.tobj_rotation = src->rotation;
359 dst.type = src->special_object_type;
360
361 tobj->vehicles.push_back(dst);
362 }
363 }
364 }
365
366 try
367 {
368 Ogre::DataStreamPtr stream
369 = Ogre::ResourceGroupManager::getSingleton().createResource(
370 tobj->document_name, terrain->getTerrainFileResourceGroup(), /*overwrite=*/true);
371 TObj::WriteToStream(tobj, stream);
372 }
373 catch (...)
374 {
376 fmt::format("Error saving file '{}' to resource group '{}'",
377 tobj->document_name, terrain->getTerrainFileResourceGroup()), HANDLEGENERICEXCEPTION_CONSOLE);
378 }
379 }
380}
381
386
388{
389 // Do nothing if already selected.
390 if (id == m_selected_object_id)
391 {
392 return;
393 }
394
396
398 {
399 return; // Nothing more to do.
400 }
401
402 // Notify user
404 String ssmsg = _L("Selected object: [") + TOSTRING(m_selected_object_id) + "/" + TOSTRING(object_list.size()) + "] (" + object_list[m_selected_object_id]->name + ")";
407 {
409 }
410
411 // If setting special object, make sure the actor instance exists, otherwise spawn it again.
412 const TerrainEditorObjectPtr object = this->FetchSelectedObject();
414 if (object != TERRAINEDITOROBJECTPTR_NULL && object->special_object_type != TObjSpecialObject::NONE)
415 {
417 }
418}
419
424
426{
428 {
430 }
431
433 ROR_ASSERT(m_selected_object_id < (int)object_list.size());
434 if (m_selected_object_id >= (int)object_list.size())
435 {
436 LOG(fmt::format("[RoR|TerrainEditor] INTERNAL ERROR - `m_selected_object_id` '{}' >= `(int)object_list.size()` '{}'",
437 m_selected_object_id, (int)object_list.size()));
439 }
440
441 return object_list[m_selected_object_id];
442}
443
444// -------------------
445// TerrainEditorObject
446
448{
449 return position;
450}
451
453{
454 return rotation;
455}
456
458{
459 ROR_ASSERT(obj->actor_instance_id != ACTORINSTANCEID_INVALID);
460 const ActorPtr& actor = App::GetGameContext()->GetActorManager()->GetActorById(obj->actor_instance_id);
462 if (actor != ActorManager::ACTORPTR_NULL)
463 {
465
468 req->amr_actor = actor->ar_instance_id;
469 req->amr_softrespawn_position = obj->position;
470 req->amr_softrespawn_rotation = TObjParser::CalcRotation(obj->rotation, rot_yxz);
472 req = nullptr;
473
476 fxreq->amr_actor = actor->ar_instance_id;
478 fxreq = nullptr;
479 }
480}
481
482void TerrainEditorObject::setPosition(Ogre::Vector3 const& pos)
483{
484 position = pos;
486 {
487 static_object_node->setPosition(pos);
488 }
490 {
492 }
493}
494
495void TerrainEditorObject::setRotation(Ogre::Vector3 const& rot)
496{
497 rotation = rot;
499 {
500 static_object_node->setOrientation(Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * Quaternion(Degree(rot.z), Vector3::UNIT_Z));
501 static_object_node->pitch(Degree(-90));
502 }
504 {
506 }
507}
508
510{
511 return name;
512}
513
515{
516 return instance_name;
517}
518
520{
521 return type;
522}
523
528
533
538
System integration layer; inspired by OgreBites::ApplicationContext.
#define ROR_ASSERT(_EXPR)
Definition Application.h:40
#define RGN_CONFIG
Definition Application.h:49
#define TOSTRING(x)
Definition Application.h:57
void LOG(const char *msg)
Legacy alias - formerly a macro.
#define _L
Game state manager and message-queue provider.
Handles controller inputs from player.
Platform-specific utilities. We use narrow UTF-8 encoded strings as paths. Inspired by http://utf8eve...
void TerrainEditorObjectRefreshActorVisual(TerrainEditorObjectPtr obj)
ActorInstanceID_t ar_instance_id
Static attr; session-unique ID.
Definition Actor.h:429
const ActorPtr & GetActorById(ActorInstanceID_t actor_id)
static const ActorPtr ACTORPTR_NULL
std::string resource_bundle_type
Archive type recognized by OGRE resource system: 'FileSystem' or 'Zip'.
Definition CacheSystem.h:80
Ogre::SceneNode * GetCameraNode()
CameraBehaviors GetCurrentBehavior() const
Ogre::Camera * GetCamera()
void setPosition(Ogre::Vector3 position)
Definition Character.cpp:85
Ogre::Vector3 getPosition()
Definition Character.cpp:92
@ CONSOLE_MSGTYPE_INFO
Generic message.
Definition Console.h:60
@ CONSOLE_MSGTYPE_TERRN
Parsing/spawn/simulation messages for terrain.
Definition Console.h:64
void putMessage(MessageArea area, MessageType type, std::string const &msg, std::string icon="")
Definition Console.cpp:103
@ CONSOLE_SYSTEM_ERROR
Definition Console.h:52
@ CONSOLE_SYSTEM_NOTICE
Definition Console.h:51
@ CONSOLE_SYSTEM_WARNING
Definition Console.h:53
@ CONSOLE_SYSTEM_REPLY
Success.
Definition Console.h:54
CharacterFactory * GetCharacterFactory()
Character * GetPlayerCharacter()
const TerrainPtr & GetTerrain()
void PushMessage(Message m)
Doesn't guarantee order! Use ChainMessage() if order matters.
ActorManager * GetActorManager()
bool isKeyDown(OIS::KeyCode mod)
Asks OIS directly.
ProceduralObjectPtr getObject(int pos)
static Ogre::Quaternion CalcRotation(Ogre::Vector3 const &rot, bool rot_yxz)
void WriteSeparateOutputFile()
Writes 'editor_out.log' to 'config' directory - original solution, still used for zipped terrains.
void UpdateInputEvents(float dt)
TerrainEditorObjectID_t GetSelectedObjectID() const
void SetSelectedObjectByID(TerrainEditorObjectID_t id)
std::string m_last_object_name
const TerrainEditorObjectPtr & FetchSelectedObject()
TerrainEditorObjectID_t m_selected_object_id
int m_rotation_axis
0=X, 1=Y, 2=Z
static const TerrainEditorObjectPtr TERRAINEDITOROBJECTPTR_NULL
void WriteEditsToTobjFiles()
Updates existing TOBJ files - new solution, only for projects (unzipped terrains).
ActorInstanceID_t getActorInstanceId()
std::string const & getType()
Ogre::Vector3 const & getPosition()
ActorInstanceID_t actor_instance_id
void setSpecialObjectType(TObjSpecialObject type)
void setActorInstanceId(ActorInstanceID_t instance_id)
std::string const & getName()
TObjSpecialObject special_object_type
void setPosition(Ogre::Vector3 const &pos)
std::string const & getInstanceName()
Ogre::SceneNode * static_object_node
void setRotation(Ogre::Vector3 const &rot)
TObjSpecialObject getSpecialObjectType()
std::string type
Accepts "-" as placeholder, otherwise a surveymap icon is registered.
Ogre::Vector3 const & getRotation()
std::string getTerrainFileResourceGroup()
Definition Terrain.cpp:564
TerrainObjectManager * getObjectManager()
Definition Terrain.h:80
CacheEntryPtr getCacheEntry()
Definition Terrain.cpp:592
ProceduralManagerPtr getProceduralManager()
Definition Terrain.cpp:554
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)
TerrainEditorObjectPtrVec & GetEditorObjects()
bool GetEditorObjectFlagRotYXZ(TerrainEditorObjectPtr const &object)
std::vector< TObjDocumentPtr > & GetTobjCache()
void SpawnSinglePredefinedActor(TerrainEditorObjectPtr const &object)
void destroyObject(const Ogre::String &instancename)
std::string PathCombine(std::string a, std::string b)
@ EV_TRUCK_ACCELERATE
accelerate the truck
@ EV_COMMON_REMOVE_CURRENT_TRUCK
remove current truck
@ EV_CHARACTER_SIDESTEP_LEFT
sidestep to the left
@ EV_CHARACTER_FORWARD
step forward with the character
@ EV_COMMON_RESCUE_TRUCK
teleport to rescue truck
@ EV_TRUCK_STEER_LEFT
steer left
@ EV_COMMON_RESET_TRUCK
reset truck to original starting position
@ EV_COMMON_ENTER_PREVIOUS_TRUCK
enter previous truck
@ EV_TRUCK_BRAKE
brake
@ EV_COMMON_ENTER_NEXT_TRUCK
enter next truck
@ EV_TRUCK_STEER_RIGHT
steer right
@ EV_CHARACTER_SIDESTEP_RIGHT
sidestep to the right
@ EV_COMMON_RESPAWN_LAST_TRUCK
respawn last truck
@ EV_CHARACTER_BACKWARDS
step backwards with the character
@ EV_COMMON_ENTER_OR_EXIT_TRUCK
enter or exit a truck
@ EV_COMMON_TOGGLE_TERRAIN_EDITOR
toggle terrain editor
@ MSG_EDI_LEAVE_TERRN_EDITOR_REQUESTED
@ MSG_SIM_MODIFY_ACTOR_REQUESTED
Payload = RoR::ActorModifyRequest* (owner)
InputEngine * GetInputEngine()
CVar * sys_logs_dir
CameraManager * GetCameraManager()
GameContext * GetGameContext()
Console * GetConsole()
const int STR_LEN
void WriteToStream(TObjDocumentPtr doc, Ogre::DataStreamPtr stream)
std::shared_ptr< TObjDocument > TObjDocumentPtr
void HandleGenericException(const std::string &from, BitMask_t flags)
int ActorInstanceID_t
Unique sequentially generated ID of an actor in session. Use ActorManager::GetActorById()
int TerrainEditorObjectID_t
Offset into RoR::TerrainObjectManager::m_editor_objects, use RoR::TERRAINEDITOROBJECTID_INVALID as em...
void LogFormat(const char *format,...)
Improved logging utility. Uses fixed 2Kb buffer.
static const ActorInstanceID_t ACTORINSTANCEID_INVALID
TObjSpecialObject
@ HANDLEGENERICEXCEPTION_CONSOLE
static const TerrainEditorObjectID_t TERRAINEDITOROBJECTID_INVALID
ActorInstanceID_t amr_actor
Definition SimData.h:875
Ogre::Quaternion amr_softrespawn_rotation
Rotation to use with SOFT_RESPAWN; use TObjParser::CalcRotation() to calculate quaternion from XYZ li...
Definition SimData.h:882
Ogre::Vector3 amr_softrespawn_position
Position to use with SOFT_RESPAWN.
Definition SimData.h:881
@ SOFT_RESPAWN
Like hard reset, but positions the actor like spawn process does - using the relative positions from ...
@ REFRESH_VISUALS
Forces a synchronous update of visuals from any context - i.e. from terrain editor mode or with sleep...
Unified game event system - all requests and state changes are reported using a message.
Definition GameContext.h:52
ProceduralPointPtr getPoint(int pos)
char instance_name[TObj::STR_LEN]
Ogre::Vector3 rotation
Ogre::Vector3 position
char type[TObj::STR_LEN]
char odef_name[TObj::STR_LEN]
std::string comments
Comment line(s) preceding the object-line in the .TOBJ file.
Ogre::Vector3 position
Ogre::Vector3 tobj_rotation
Original rotation specified in .TOBJ file.
char name[TObj::STR_LEN]
TObjSpecialObject type