Skip to content

Commit 045aebe

Browse files
committed
🚧 Terrain editor: visually moving preloaded actors works.
Rotating still TBD. To do this, 2 new 'types' had to be added to `MSG_SIM_MODIFY_ACTOR_REQUESTED`: * SOFT_RESPAWN, //!< Like hard reset, but positions the actor like spawn process does - using the relative positions from rig-def file (respecting Tuning system tweaks). * REFRESH_VISUALS //!< Forces a synchronous update of visuals from any context - i.e. from terrain editor mode or with sleeping/physicspaused actor. Time spent: 90min
1 parent b954498 commit 045aebe

File tree

8 files changed

+75
-5
lines changed

8 files changed

+75
-5
lines changed

source/main/GameContext.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,15 @@ void GameContext::ModifyActor(ActorModifyRequest& rq)
415415
// Load our actor again, but only after all actors are deleted.
416416
this->ChainMessage(Message(MSG_SIM_SPAWN_ACTOR_REQUESTED, (void*)srq));
417417
}
418+
else if (rq.amr_type == ActorModifyRequest::Type::SOFT_RESPAWN)
419+
{
420+
actor->softRespawn(rq.amr_softrespawn_pos);
421+
}
422+
else if (rq.amr_type == ActorModifyRequest::Type::REFRESH_VISUALS)
423+
{
424+
actor->GetGfxActor()->UpdateSimDataBuffer();
425+
App::GetGfxScene()->ForceUpdateSingleGfxActor(actor->GetGfxActor());
426+
}
418427
}
419428

420429
void GameContext::DeleteActor(ActorPtr actor)

source/main/gfx/GfxScene.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,27 @@ void GfxScene::RemoveGfxActor(RoR::GfxActor* remove_me)
329329
}
330330
}
331331

332+
void GfxScene::ForceUpdateSingleGfxActor(RoR::GfxActor* gfx_actor)
333+
{
334+
// Do the work `UpdateScene()` would, but for a single actor.
335+
// Needed for i.e. terrain editor mode.
336+
// ------------------------------------------------------
337+
338+
// Start threaded stuff
339+
gfx_actor->UpdateFlexbodies(); // Push flexbody tasks to threadpool
340+
gfx_actor->UpdateWheelVisuals(); // Push flexwheel tasks to threadpool
341+
342+
// Do sync stuff
343+
gfx_actor->UpdateRods();
344+
gfx_actor->UpdateCabMesh();
345+
gfx_actor->UpdateWingMeshes();
346+
gfx_actor->UpdateAirbrakes();
347+
348+
// Finish threaded stuff
349+
gfx_actor->FinishWheelUpdates();
350+
gfx_actor->FinishFlexbodyTasks();
351+
}
352+
332353
void GfxScene::RegisterGfxCharacter(RoR::GfxCharacter* gfx_character)
333354
{
334355
m_all_gfx_characters.push_back(gfx_character);

source/main/gfx/GfxScene.h

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class GfxScene
5959
void ClearScene();
6060
void RegisterGfxActor(RoR::GfxActor* gfx_actor);
6161
void RemoveGfxActor(RoR::GfxActor* gfx_actor);
62+
void ForceUpdateSingleGfxActor(RoR::GfxActor* gfx_actor);
6263
void RegisterGfxCharacter(RoR::GfxCharacter* gfx_character);
6364
void RemoveGfxCharacter(RoR::GfxCharacter* gfx_character);
6465
void BufferSimulationData(); //!< Run this when simulation is halted

source/main/physics/Actor.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -1289,6 +1289,22 @@ void Actor::resetPosition(Ogre::Vector3 translation, bool setInitPosition)
12891289
calculateAveragePosition();
12901290
}
12911291

1292+
void Actor::softRespawn(Ogre::Vector3 spawnpos)
1293+
{
1294+
// Perform a hard reset (detach any linked actors etc...)
1295+
this->SyncReset(/*reset_position:*/ false);
1296+
1297+
// Move the actor to position
1298+
ar_origin = spawnpos;
1299+
for (NodeNum_t i = 0; i < ar_num_nodes; i++)
1300+
{
1301+
ar_nodes[i].AbsPosition = spawnpos + ar_nodes_spawn_offsets[i];
1302+
ar_nodes[i].RelPosition = ar_nodes_spawn_offsets[i];
1303+
ar_nodes[i].Forces = Ogre::Vector3::ZERO;
1304+
ar_nodes[i].Velocity = Ogre::Vector3::ZERO;
1305+
}
1306+
}
1307+
12921308
void Actor::mouseMove(NodeNum_t node, Vector3 pos, float force)
12931309
{
12941310
m_mouse_grab_node = node;

source/main/physics/Actor.h

+6-3
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,9 @@ class Actor : public RefCountingObject<Actor>
9898
int getShockNode1(int shock_number);
9999
int getShockNode2(int shock_number);
100100
// not exported to scripting:
101-
void resetPosition(Ogre::Vector3 translation, bool setInitPosition); //!< Moves the actor to given world coords.
102-
void resetPosition(float px, float pz, bool setInitPosition, float miny); //!< Moves the actor to given world coords.
101+
void resetPosition(Ogre::Vector3 translation, bool setInitPosition); //!< Moves the actor to given world coords (pivot point is node 0).
102+
void resetPosition(float px, float pz, bool setInitPosition, float miny); //!< Moves the actor to given world coords (pivot point is node 0).
103+
void softRespawn(Ogre::Vector3 spawnpos); //!< Use `MSG_SIM_MODIFY_ACTOR_REQUESTED` with type `SOFT_RESPAWN`; Resets the actor to given position as if spawned there (pivot point is `spawnpos`).
103104
void requestRotation(float rotation, Ogre::Vector3 center) { m_rotation_request += rotation; m_rotation_request_center = center; };
104105
void requestAngleSnap(int division) { m_anglesnap_request = division; };
105106
void requestTranslation(Ogre::Vector3 translation) { m_translation_request += translation; };
@@ -281,6 +282,7 @@ class Actor : public RefCountingObject<Actor>
281282
int* ar_nodes_id = nullptr; //!< Number in truck file, -1 for nodes generated by wheels/cinecam
282283
std::string* ar_nodes_name = nullptr; //!< Name in truck file, only if defined with 'nodes2'
283284
int ar_nodes_name_top_length = 0; //!< For nicely formatted diagnostic output
285+
Ogre::Vector3* ar_nodes_spawn_offsets = nullptr; //!< Relative positions (incl. Tuning system tweaks) from the definition file, for spawn-like resetting (i.e. with terrain editor on preloaded actor).
284286
int ar_num_nodes = 0;
285287
std::vector<float> ar_minimass; //!< minimum node mass in Kg
286288
bool ar_minimass_skip_loaded_nodes = false;
@@ -308,7 +310,8 @@ class Actor : public RefCountingObject<Actor>
308310
Ogre::AxisAlignedBox ar_predicted_bounding_box;
309311
float ar_initial_total_mass = 0.f;
310312
std::vector<float> ar_initial_node_masses;
311-
std::vector<Ogre::Vector3> ar_initial_node_positions;
313+
std::vector<Ogre::Vector3> ar_initial_node_positions; //!< Absolute world positions, for resetting to pristine state.
314+
std::vector<Ogre::Vector3> ar_rigdef_node_positions;
312315
std::vector<std::pair<float, float>> ar_initial_beam_defaults;
313316
std::vector<wheeldetacher_t> ar_wheeldetachers;
314317
std::vector<std::vector<int>> ar_node_to_node_connections;

source/main/physics/ActorSpawner.cpp

+10-1
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ void ActorSpawner::InitializeRig()
266266
m_actor->ar_nodes_id[i] = -1;
267267
}
268268
m_actor->ar_nodes_name = new std::string[req.num_nodes];
269+
m_actor->ar_nodes_spawn_offsets = new Ogre::Vector3[req.num_nodes];
269270

270271
if (req.num_shocks > 0)
271272
m_actor->ar_shocks = new shock_t[req.num_shocks];
@@ -4743,6 +4744,7 @@ void ActorSpawner::BuildWheelObjectAndNodes(
47434744
{
47444745
/* Outer ring */
47454746
Ogre::Vector3 ray_point = axis_node_1->RelPosition + ray_vector;
4747+
Ogre::Vector3 ray_spawnpoint = m_actor->ar_nodes_spawn_offsets[axis_node_1->pos] + ray_vector;
47464748
ray_vector = ray_rotator * ray_vector;
47474749

47484750
node_t & outer_node = GetFreeNode();
@@ -4753,9 +4755,11 @@ void ActorSpawner::BuildWheelObjectAndNodes(
47534755
AdjustNodeBuoyancy(outer_node, node_defaults);
47544756

47554757
m_actor->m_gfx_actor->m_gfx_nodes.push_back(NodeGfx(outer_node.pos));
4758+
m_actor->ar_nodes_spawn_offsets[outer_node.pos] = ray_spawnpoint;
47564759

47574760
/* Inner ring */
47584761
ray_point = axis_node_2->RelPosition + ray_vector;
4762+
ray_spawnpoint = m_actor->ar_nodes_spawn_offsets[axis_node_2->pos] + ray_vector;
47594763
ray_vector = ray_rotator * ray_vector;
47604764

47614765
node_t & inner_node = GetFreeNode();
@@ -4766,6 +4770,7 @@ void ActorSpawner::BuildWheelObjectAndNodes(
47664770
AdjustNodeBuoyancy(inner_node, node_defaults);
47674771

47684772
m_actor->m_gfx_actor->m_gfx_nodes.push_back(NodeGfx(inner_node.pos));
4773+
m_actor->ar_nodes_spawn_offsets[inner_node.pos] = ray_spawnpoint;
47694774

47704775
/* Wheel object */
47714776
wheel.wh_nodes[i * 2] = & outer_node;
@@ -5927,7 +5932,10 @@ void ActorSpawner::ProcessNode(RigDef::Node & def)
59275932
node.pos = inserted_node.first; /* Node index */
59285933

59295934
/* Positioning */
5930-
Ogre::Vector3 node_position = m_spawn_position + TuneupUtil::getTweakedNodePosition(m_actor->getWorkingTuneupDef(), node.pos, def.position);
5935+
const Ogre::Vector3 spawn_offset = TuneupUtil::getTweakedNodePosition(m_actor->getWorkingTuneupDef(), node.pos, def.position);
5936+
m_actor->ar_nodes_spawn_offsets[inserted_node.first] = spawn_offset;
5937+
5938+
Ogre::Vector3 node_position = m_spawn_position + spawn_offset;
59315939
ROR_ASSERT(!std::isnan(node_position.x));
59325940
ROR_ASSERT(!std::isnan(node_position.y));
59335941
ROR_ASSERT(!std::isnan(node_position.z));
@@ -6080,6 +6088,7 @@ void ActorSpawner::ProcessCinecam(RigDef::Cinecam & def)
60806088
// Node
60816089
Ogre::Vector3 node_pos = m_spawn_position + def.position;
60826090
node_t & camera_node = GetAndInitFreeNode(node_pos);
6091+
m_actor->ar_nodes_spawn_offsets[camera_node.pos] = def.position;
60836092
camera_node.nd_no_ground_contact = true; // Orig: hardcoded in BTS_CINECAM
60846093
camera_node.friction_coef = NODE_FRICTION_COEF_DEFAULT; // Node defaults are ignored here.
60856094
AdjustNodeBuoyancy(camera_node, def.node_defaults);

source/main/physics/SimData.h

+3
Original file line numberDiff line numberDiff line change
@@ -860,9 +860,11 @@ struct ActorModifyRequest
860860
RELOAD, //!< Full reload from filesystem, requested by user
861861
RESET_ON_INIT_POS,
862862
RESET_ON_SPOT,
863+
SOFT_RESPAWN, //!< Like hard reset, but positions the actor like spawn process does - using the relative positions from rig-def file (respecting Tuning system tweaks).
863864
SOFT_RESET,
864865
RESTORE_SAVED,
865866
WAKE_UP,
867+
REFRESH_VISUALS //!< Forces a synchronous update of visuals from any context - i.e. from terrain editor mode or with sleeping/physicspaused actor.
866868
};
867869

868870
ActorInstanceID_t amr_actor = ACTORINSTANCEID_INVALID;// not ActorPtr because it's not thread-safe
@@ -871,6 +873,7 @@ struct ActorModifyRequest
871873
amr_saved_state;
872874
CacheEntryPtr amr_addonpart; //!< Primary method of specifying cache entry.
873875
std::string amr_addonpart_fname; //!< Fallback method in case CacheEntry doesn't exist anymore - that means mod was uninstalled in the meantime. Used by REMOVE_ADDONPART_AND_RELOAD.
876+
Ogre::Vector3 amr_softrespawn_pos; //!< Position to use with `SOFT_RESPAWN`.
874877
};
875878

876879
enum class ActorLinkingRequestType

source/main/terrain/TerrainEditor.cpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -395,9 +395,17 @@ void TerrainEditorObject::setPosition(Ogre::Vector3 const& pos)
395395
actor->requestTranslation(pos - actor->getPosition());
396396

397397
ActorModifyRequest* req = new ActorModifyRequest();
398-
req->amr_type = ActorModifyRequest::Type::RESET_ON_SPOT;
398+
req->amr_type = ActorModifyRequest::Type::SOFT_RESPAWN;
399399
req->amr_actor = actor->ar_instance_id;
400+
req->amr_softrespawn_pos = pos;
400401
App::GetGameContext()->PushMessage(Message(MSG_SIM_MODIFY_ACTOR_REQUESTED, (void*)req));
402+
req = nullptr;
403+
404+
ActorModifyRequest* fxreq = new ActorModifyRequest();
405+
fxreq->amr_type = ActorModifyRequest::Type::REFRESH_VISUALS;
406+
fxreq->amr_actor = actor->ar_instance_id;
407+
App::GetGameContext()->PushMessage(Message(MSG_SIM_MODIFY_ACTOR_REQUESTED, (void*)fxreq));
408+
fxreq = nullptr;
401409
}
402410
}
403411
}

0 commit comments

Comments
 (0)