@@ -1204,6 +1204,174 @@ void test_sync_mode_reset() {
1204
1204
NS_ASSERT_COND (NS::MathFunc::is_equal_approx(controlled_obj_1_peer_1->position.data.f32, frame_count * delta * one_meter * 2 .0f , delta * 2 .0f ));
1205
1205
}
1206
1206
1207
+ class TestProcessingSceneObject : public NS ::LocalSceneObject {
1208
+ public:
1209
+ // NOTE, this property isn't sync.
1210
+ TestProcessingSceneObject *deactivate_processing_on_object = nullptr ;
1211
+ ProcessPhase deactivate_processing_phase;
1212
+
1213
+ NS::ObjectLocalId local_id = NS::ObjectLocalId::NONE;
1214
+ NS::VarData var_1;
1215
+ NS::VarData var_2;
1216
+
1217
+ NS::PHandler processing_handler = NS::NullPHandler;
1218
+
1219
+ virtual void on_scene_entry () override {
1220
+ get_scene ()->scene_sync ->register_app_object (get_scene ()->scene_sync ->to_handle (this ));
1221
+ }
1222
+
1223
+ virtual void setup_synchronizer (NS::LocalSceneSynchronizer &p_scene_sync, NS::ObjectLocalId p_id) override {
1224
+ local_id = p_id;
1225
+
1226
+ p_scene_sync.register_variable (
1227
+ p_id,
1228
+ " var_1" ,
1229
+ [](NS::SynchronizerManager &p_synchronizer_manager, NS::ObjectHandle p_handle, const std::string &p_var_name, const NS::VarData &p_value) {
1230
+ static_cast <TestProcessingSceneObject *>(NS::LocalSceneSynchronizer::from_handle (p_handle))->var_1 .copy (p_value);
1231
+ },
1232
+ [](const NS::SynchronizerManager &p_synchronizer_manager, NS::ObjectHandle p_handle, const std::string &p_var_name, NS::VarData &r_value) {
1233
+ r_value.copy (static_cast <TestProcessingSceneObject *>(NS::LocalSceneSynchronizer::from_handle (p_handle))->var_1 );
1234
+ });
1235
+
1236
+ p_scene_sync.register_variable (
1237
+ p_id,
1238
+ " var_2" ,
1239
+ [](NS::SynchronizerManager &p_synchronizer_manager, NS::ObjectHandle p_handle, const std::string &p_var_name, const NS::VarData &p_value) {
1240
+ static_cast <TestProcessingSceneObject *>(NS::LocalSceneSynchronizer::from_handle (p_handle))->var_2 .copy (p_value);
1241
+ },
1242
+ [](const NS::SynchronizerManager &p_synchronizer_manager, NS::ObjectHandle p_handle, const std::string &p_var_name, NS::VarData &r_value) {
1243
+ r_value.copy (static_cast <TestProcessingSceneObject *>(NS::LocalSceneSynchronizer::from_handle (p_handle))->var_2 );
1244
+ });
1245
+ }
1246
+
1247
+ void activate_processing (ProcessPhase Phase) {
1248
+ if (processing_handler == NS::NullPHandler) {
1249
+ processing_handler = get_scene ()->scene_sync ->register_process (local_id, Phase, [this ](float p_delta) {
1250
+ this ->sync_process (p_delta);
1251
+ });
1252
+ }
1253
+ }
1254
+
1255
+ void deactivate_processing (ProcessPhase Phase) {
1256
+ if (processing_handler != NS::NullPHandler) {
1257
+ get_scene ()->scene_sync ->unregister_process (local_id, Phase, processing_handler);
1258
+ processing_handler = NS::NullPHandler;
1259
+ }
1260
+ }
1261
+
1262
+ virtual void on_scene_exit () override {
1263
+ get_scene ()->scene_sync ->on_app_object_removed (get_scene ()->scene_sync ->to_handle (this ));
1264
+ }
1265
+
1266
+ void sync_process (float p_delta) {
1267
+ if (deactivate_processing_on_object) {
1268
+ deactivate_processing_on_object->deactivate_processing (deactivate_processing_phase);
1269
+ deactivate_processing_on_object = nullptr ;
1270
+ }
1271
+ var_1.data .f32 += var_2.data .f32 * p_delta;
1272
+ }
1273
+ };
1274
+
1275
+ void test_registering_and_deregistering_process () {
1276
+ NS::LocalScene server_scene;
1277
+ server_scene.start_as_no_net ();
1278
+
1279
+ NS::LocalScene peer_1_scene;
1280
+ peer_1_scene.start_as_no_net ();
1281
+
1282
+ // Add the scene sync
1283
+ server_scene.scene_sync =
1284
+ server_scene.add_object <NS::LocalSceneSynchronizer>(" sync" , server_scene.get_peer ());
1285
+
1286
+ peer_1_scene.scene_sync =
1287
+ peer_1_scene.add_object <NS::LocalSceneSynchronizer>(" sync" , server_scene.get_peer ());
1288
+
1289
+ server_scene.scene_sync ->set_frame_confirmation_timespan (0.0 );
1290
+
1291
+ TestProcessingSceneObject *processing_object_1_server = server_scene.add_object <TestProcessingSceneObject>(" obj_1" , server_scene.get_peer ());
1292
+ TestProcessingSceneObject *processing_object_1_peer = peer_1_scene.add_object <TestProcessingSceneObject>(" obj_1" , server_scene.get_peer ());
1293
+
1294
+ TestProcessingSceneObject *processing_object_2_server = server_scene.add_object <TestProcessingSceneObject>(" obj_2" , server_scene.get_peer ());
1295
+ TestProcessingSceneObject *processing_object_2_peer = peer_1_scene.add_object <TestProcessingSceneObject>(" obj_2" , server_scene.get_peer ());
1296
+
1297
+ processing_object_1_server->var_1 .data .f32 = 0.0 ;
1298
+ processing_object_1_server->var_2 .data .f32 = 2.0 ;
1299
+ processing_object_1_peer->var_1 .data .f32 = 0.0 ;
1300
+ processing_object_1_peer->var_2 .data .f32 = 2.0 ;
1301
+
1302
+ processing_object_2_server->var_1 .data .f32 = -10.0 ;
1303
+ processing_object_2_server->var_2 .data .f32 = 4.0 ;
1304
+ processing_object_2_peer->var_1 .data .f32 = -10.0 ;
1305
+ processing_object_2_peer->var_2 .data .f32 = 4.0 ;
1306
+
1307
+ // Process the scene 10 times and ensure the processing was never executed.
1308
+ for (int i = 0 ; i < 10 ; i++) {
1309
+ server_scene.process (delta);
1310
+ peer_1_scene.process (delta);
1311
+
1312
+ NS_ASSERT_COND (processing_object_1_server->var_1.data.f32 == 0 .0f );
1313
+ NS_ASSERT_COND (processing_object_1_peer->var_1.data.f32 == 0 .0f );
1314
+ NS_ASSERT_COND (processing_object_2_server->var_1.data.f32 == -10 .0f );
1315
+ NS_ASSERT_COND (processing_object_2_peer->var_1.data.f32 == -10 .0f );
1316
+ }
1317
+
1318
+ processing_object_1_server->activate_processing (PROCESS_PHASE_PROCESS);
1319
+ processing_object_1_peer->activate_processing (PROCESS_PHASE_PROCESS);
1320
+ processing_object_2_server->activate_processing (PROCESS_PHASE_LATE); // EXECUTES AFTER OBJECT 1
1321
+ processing_object_2_peer->activate_processing (PROCESS_PHASE_LATE); // EXECUTES AFTER OBJECT 1
1322
+
1323
+ // Now process another 10 times and ensure the processing was correctly executed
1324
+ float expected_object_1 = 0.0 ;
1325
+ float expected_object_2 = -10.0 ;
1326
+ for (int i = 0 ; i < 10 ; i++) {
1327
+ server_scene.process (delta);
1328
+ peer_1_scene.process (delta);
1329
+
1330
+ expected_object_1 += delta * 2.0 ;
1331
+ expected_object_2 += delta * 4.0 ;
1332
+
1333
+ NS_ASSERT_COND (processing_object_1_server->var_1.data.f32 == expected_object_1);
1334
+ NS_ASSERT_COND (processing_object_1_peer->var_1.data.f32 == expected_object_1);
1335
+ NS_ASSERT_COND (processing_object_2_server->var_1.data.f32 == expected_object_2);
1336
+ NS_ASSERT_COND (processing_object_2_peer->var_1.data.f32 == expected_object_2);
1337
+ }
1338
+
1339
+ // Now, deactivate the execution for the object 2 from object 1 (that
1340
+ // executes sooner thanks to the different processing phase), to ensure
1341
+ // it doesn't cause any crash and the deactivation is executed only the following frame.
1342
+ processing_object_1_server->deactivate_processing_on_object = processing_object_2_server;
1343
+ processing_object_1_peer->deactivate_processing_on_object = processing_object_2_peer;
1344
+ processing_object_1_server->deactivate_processing_phase = PROCESS_PHASE_LATE;
1345
+ processing_object_1_peer->deactivate_processing_phase = PROCESS_PHASE_LATE;
1346
+
1347
+ // Process one time. NOTE Here the object 2 processing is deactivated.
1348
+ server_scene.process (delta);
1349
+ peer_1_scene.process (delta);
1350
+
1351
+ expected_object_1 += delta * 2.0 ;
1352
+ expected_object_2 += delta * 4.0 ;
1353
+
1354
+ // However ensure that in the above frame the processing happened anyway.
1355
+ NS_ASSERT_COND (processing_object_1_server->var_1.data.f32 == expected_object_1);
1356
+ NS_ASSERT_COND (processing_object_1_peer->var_1.data.f32 == expected_object_1);
1357
+ NS_ASSERT_COND (processing_object_2_server->var_1.data.f32 == expected_object_2);
1358
+ NS_ASSERT_COND (processing_object_2_peer->var_1.data.f32 == expected_object_2);
1359
+
1360
+ // Now process another 10 times and ensure the processing keep going only on the object 1.
1361
+ for (int i = 0 ; i < 10 ; i++) {
1362
+ server_scene.process (delta);
1363
+ peer_1_scene.process (delta);
1364
+
1365
+ expected_object_1 += delta * 2.0 ;
1366
+ // expected_object_2 += delta * 4.0;
1367
+
1368
+ NS_ASSERT_COND (processing_object_1_server->var_1.data.f32 == expected_object_1);
1369
+ NS_ASSERT_COND (processing_object_1_peer->var_1.data.f32 == expected_object_1);
1370
+ NS_ASSERT_COND (processing_object_2_server->var_1.data.f32 == expected_object_2);
1371
+ NS_ASSERT_COND (processing_object_2_peer->var_1.data.f32 == expected_object_2);
1372
+ }
1373
+ }
1374
+
1207
1375
void test_scene_synchronizer () {
1208
1376
test_ids ();
1209
1377
test_client_and_server_initialization ();
@@ -1218,5 +1386,6 @@ void test_scene_synchronizer() {
1218
1386
test_streaming ();
1219
1387
test_no_network ();
1220
1388
test_sync_mode_reset ();
1389
+ test_registering_and_deregistering_process ();
1221
1390
}
1222
1391
}; // namespace NS_Test
0 commit comments