| 251 | } |
| 252 | |
| 253 | void CPHSkeleton::RestoreNetState(CSE_PHSkeleton* /*po*/) |
| 254 | { |
| 255 | auto obj = PPhysicsShellHolder(); |
| 256 | if (!obj) |
| 257 | return; |
| 258 | auto se_obj = obj->alife_object(); |
| 259 | if (!se_obj) |
| 260 | return; |
| 261 | |
| 262 | auto po = smart_cast<CSE_PHSkeleton*>(se_obj); |
| 263 | VERIFY(po); |
| 264 | if (!po->_flags.test(CSE_PHSkeleton::flSavedData)) |
| 265 | return; |
| 266 | PHNETSTATE_VECTOR& saved_bones = po->saved_bones.bones; |
| 267 | |
| 268 | if (obj->PPhysicsShell() && obj->PPhysicsShell()->isActive()) |
| 269 | { |
| 270 | obj->PPhysicsShell()->Disable(); |
| 271 | } |
| 272 | |
| 273 | if (saved_bones.size() == obj->PHGetSyncItemsNumber()) |
| 274 | { |
| 275 | // если у нас только одна рутовая кость и она fixed - попробуем не грузить состояние костей вообще. пусть будет как после спауна |
| 276 | |
| 277 | const u16 bones_number = obj->PHGetSyncItemsNumber(); |
| 278 | |
| 279 | bool canSkip = obj->PPhysicsShell() != nullptr; |
| 280 | |
| 281 | if (canSkip) |
| 282 | { |
| 283 | for (u16 i = 0; i < bones_number; i++) |
| 284 | { |
| 285 | CPHElement* element = smart_cast<CPHElement*>(obj->PPhysicsShell()->get_ElementByStoreOrder(i)); |
| 286 | |
| 287 | // если рутовая кость и не fixed - может двигаться весь предмет и надо восстановить позицию |
| 288 | if (!element->get_ParentElement() && !element->isFixed()) |
| 289 | { |
| 290 | canSkip = false; |
| 291 | break; |
| 292 | } |
| 293 | } |
| 294 | } |
| 295 | |
| 296 | if (!canSkip) |
| 297 | { |
| 298 | u16 bone = 0; |
| 299 | for (const auto& state : saved_bones) |
| 300 | { |
| 301 | obj->PHGetSyncItem(bone)->set_State(state); |
| 302 | bone++; |
| 303 | } |
| 304 | } |
| 305 | else |
| 306 | { |
| 307 | MsgDbg("! [%s]: [%s] skip load of bone state due to single root bone with fixed position. Visual[%s]", __FUNCTION__, obj->Name_script(), obj->cNameVisual().c_str()); |
| 308 | } |
| 309 | } |
| 310 | else |
nothing calls this directly
no test coverage detected