Advertisement
expired6978

NodeTransformManager

Sep 24th, 2014
369
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.21 KB | None | 0 0
  1. #include "NodeTransformManager.h"
  2. #include "NetImmerseOverride.h"
  3.  
  4. #include "skse/PluginAPI.h"
  5. #include "skse/GameReferences.h"
  6. #include "skse/GameRTTI.h"
  7.  
  8. #include "skse/GameStreams.h"
  9.  
  10. #include "skse/NiNodes.h"
  11. #include "skse/NiSerialization.h"
  12.  
  13. extern OverrideMapHolder            g_overrideMapHolder;
  14. extern SKSETaskInterface            * g_task;
  15.  
  16. void NodeTransformKeys::Save(SKSESerializationInterface * intfc, UInt32 kVersion)
  17. {
  18.     UInt32 numNodes = this->size();
  19.     intfc->WriteRecordData(&numNodes, sizeof(numNodes));
  20.  
  21.     for (NodeTransformKeys::iterator it = this->begin(); it != this->end(); ++it)
  22.     {
  23.         intfc->OpenRecord('NOTM', kVersion);
  24.  
  25.         // Key
  26.         WriteKey<BSFixedString>(intfc, it->first);
  27.  
  28.         // Value
  29.         it->second.Save(intfc, kVersion);
  30.     }
  31. }
  32.  
  33. bool NodeTransformKeys::Load(SKSESerializationInterface * intfc, UInt32 kVersion)
  34. {
  35.     UInt32 type, length, version;
  36.     bool error = false;
  37.  
  38.     // Handle count
  39.     UInt32 numRegs = 0;
  40.     if (!intfc->ReadRecordData(&numRegs, sizeof(numRegs)))
  41.     {
  42.         _MESSAGE("Error loading override registration count");
  43.         error = true;
  44.         return error;
  45.     }
  46.  
  47.     for (UInt32 i = 0; i < numRegs; i++)
  48.     {
  49.         if (intfc->GetNextRecordInfo(&type, &version, &length))
  50.         {
  51.             switch (type)
  52.             {
  53.                 case 'NOTM':
  54.                 {
  55.                     BSFixedString key;
  56.                     if (ReadKey<BSFixedString>(intfc, key)) {
  57.                         _MESSAGE("Error loading node entry key");
  58.                         error = true;
  59.                         return error;
  60.                     }
  61.  
  62.                     // operator[] not working for some odd reason
  63.                     bool loadError = false;
  64.                     NodeTransformKeys::iterator iter = this->find(key); // Find existing first
  65.                     if (iter != this->end()) {
  66.                         error = iter->second.Load(intfc, version);
  67.                     }
  68.                     else { // No existing, create
  69.                         OverrideRegistration<BSFixedString> set;
  70.                         error = set.Load(intfc, version);
  71.                         insert(std::pair<BSFixedString, OverrideRegistration<BSFixedString>>(key, set));
  72.                     }
  73.                     if (loadError)
  74.                     {
  75.                         _MESSAGE("Error loading node overrides");
  76.                         error = true;
  77.                         return error;
  78.                     }
  79.                     break;
  80.                 }
  81.                 default:
  82.                 {
  83.                     _MESSAGE("Error loading unexpected chunk type %08X (%.4s)", type, &type);
  84.                     error = true;
  85.                     return error;
  86.                 }
  87.             }
  88.         }
  89.     }
  90.  
  91.     return error;
  92. }
  93.  
  94. void NodeTransformRegistrationMapHolder::Save(SKSESerializationInterface* intfc, UInt32 kVersion)
  95. {
  96.     for (NodeTransformRegistrationMapHolder::RegMap::iterator it = m_data.begin(); it != m_data.end(); ++it) {
  97.         intfc->OpenRecord('ACTM', kVersion);
  98.  
  99.         // Key
  100.         UInt64 handle = it->first;
  101.         intfc->WriteRecordData(&handle, sizeof(handle));
  102.  
  103. #ifdef _DEBUG
  104.         _MESSAGE("%s - Saving Handle %016llX", __FUNCTION__, handle);
  105. #endif
  106.  
  107.         // Value
  108.         it->second.Save(intfc, kVersion);
  109.     }
  110. }
  111.  
  112. bool NodeTransformRegistrationMapHolder::Load(SKSESerializationInterface* intfc, UInt32 kVersion, UInt64 * outHandle)
  113. {
  114.     bool error = false;
  115.  
  116.     UInt64 handle = 0;
  117.     // Key
  118.     if (!intfc->ReadRecordData(&handle, sizeof(handle)))
  119.     {
  120.         _MESSAGE("Error loading reg key");
  121.         error = true;
  122.         return error;
  123.     }
  124.  
  125.     MultiRegistration<MultiRegistration<NodeTransformKeys, 2>,2> reg;
  126.     if (reg.Load(intfc, kVersion))
  127.     {
  128.         _MESSAGE("Error loading transform gender registrations");
  129.         error = true;
  130.         return error;
  131.     }
  132.  
  133.     UInt64 newHandle = 0;
  134.  
  135.     // Skip if handle is no longer valid.
  136.     if (!intfc->ResolveHandle(handle, &newHandle)) {
  137.         *outHandle = 0;
  138.         return error;
  139.     }
  140.  
  141.     if (reg.empty()) {
  142.         *outHandle = 0;
  143.         return error;
  144.     }
  145.  
  146.     *outHandle = newHandle;
  147.  
  148.     Lock();
  149.     m_data[newHandle] = reg;
  150.     Release();
  151.  
  152. #ifdef _DEBUG
  153.     _MESSAGE("%s - Loaded Handle %016llX", __FUNCTION__, newHandle);
  154. #endif
  155.  
  156.     //SetHandleProperties(newHandle, false);
  157.     return error;
  158. }
  159.  
  160. void NodeTransformManager::Save(SKSESerializationInterface * intfc, UInt32 kVersion)
  161. {
  162.     transformData.Save(intfc, kVersion);
  163. }
  164. bool NodeTransformManager::Load(SKSESerializationInterface* intfc, UInt32 kVersion)
  165. {
  166.     UInt64 handle = 0;
  167.     if (!transformData.Load(intfc, kVersion, &handle))
  168.     {
  169.         //
  170.         SetHandleNodeTransforms(handle);
  171.     }
  172.  
  173.     return false;
  174. }
  175.  
  176. bool NodeTransformManager::AddNodeTransform(TESObjectREFR * refr, bool firstPerson, bool isFemale, BSFixedString node, BSFixedString name, OVRValue & value)
  177. {
  178.     UInt64 handle = g_overrideMapHolder.GetHandle(refr, refr->formType);
  179.     transformData.Lock();
  180.     transformData.m_data[handle][isFemale ? 1 : 0][firstPerson ? 1 : 0][node][name].erase(value);
  181.     transformData.m_data[handle][isFemale ? 1 : 0][firstPerson ? 1 : 0][node][name].insert(value);
  182.     transformData.Release();
  183.     return true;
  184. }
  185.  
  186.  
  187. bool NodeTransformManager::RemoveNodeTransform(TESObjectREFR * refr, bool firstPerson, bool isFemale, BSFixedString node, BSFixedString name)
  188. {
  189.     UInt8 gender = isFemale ? 1 : 0;
  190.     UInt8 fp = firstPerson ? 1 : 0;
  191.     UInt64 handle = g_overrideMapHolder.GetHandle(refr, refr->formType);
  192.     auto it = transformData.m_data.find(handle);
  193.     if (it != transformData.m_data.end())
  194.     {
  195.         auto ait = it->second[gender][fp].find(node);
  196.         if (ait != it->second[gender][fp].end())
  197.         {
  198.             auto oit = ait->second.find(name);
  199.             if (oit != ait->second.end())
  200.             {
  201.                 ait->second.erase(oit);
  202.                 return true;
  203.             }
  204.         }
  205.     }
  206.  
  207.     return false;
  208. }
  209.  
  210. bool NodeTransformManager::RemoveNodeTransformComponent(TESObjectREFR * refr, bool firstPerson, bool isFemale, BSFixedString node, BSFixedString name, UInt16 key, UInt16 index)
  211. {
  212.     UInt8 gender = isFemale ? 1 : 0;
  213.     UInt8 fp = firstPerson ? 1 : 0;
  214.     UInt64 handle = g_overrideMapHolder.GetHandle(refr, refr->formType);
  215.     auto it = transformData.m_data.find(handle);
  216.     if (it != transformData.m_data.end())
  217.     {
  218.         auto ait = it->second[gender][fp].find(node);
  219.         if (ait != it->second[gender][fp].end())
  220.         {
  221.             auto oit = ait->second.find(name);
  222.             if (oit != ait->second.end())
  223.             {
  224.                 OVRValue ovr;
  225.                 ovr.key = key;
  226.                 ovr.index = index;
  227.                 auto ost = oit->second.find(ovr);
  228.                 if (ost != oit->second.end())
  229.                 {
  230.                     oit->second.erase(ost);
  231.                     return true;
  232.                 }
  233.             }
  234.         }
  235.     }
  236.  
  237.     return false;
  238. }
  239.  
  240. bool NodeTransformManager::VisitNodeTransforms(TESObjectREFR * refr, bool firstPerson, bool isFemale, BSFixedString node, std::function<bool(NiAVObject*, NiTransform*, OverrideRegistration<BSFixedString>*)> functor)
  241. {
  242.     bool ret = false;
  243.     UInt8 gender = isFemale ? 1 : 0;
  244.     UInt8 fp = firstPerson ? 1 : 0;
  245.     UInt64 handle = g_overrideMapHolder.GetHandle(refr, refr->formType);
  246.     auto it = transformData.m_data.find(handle); // Find ActorHandle
  247.     if (it != transformData.m_data.end())
  248.     {
  249.         NiNode * root = refr->GetNiRootNode(fp);
  250.         if (root) {
  251.             root->IncRef();
  252.             NiAVObject * foundNode = root->GetObjectByName(&node.data);
  253.             if (foundNode) {
  254.                 auto nodeIt = it->second[gender][fp].find(node);
  255.                 if (nodeIt != it->second[gender][fp].end()) {
  256.                     NiTransform * baseTransform = transformCache.GetBaseTransform(GetRootModelPath(refr, firstPerson, isFemale), node);
  257.                     if (baseTransform)
  258.                         ret = functor(foundNode, baseTransform, &nodeIt->second);
  259.                 }
  260.             }
  261.             root->DecRef();
  262.         }
  263.     }
  264.  
  265.     return ret;
  266. }
  267.  
  268. void NodeTransformManager::UpdateNodeTransforms(TESObjectREFR * ref, bool firstPerson, bool isFemale, BSFixedString node)
  269. {
  270.     VisitNodeTransforms(ref, firstPerson, isFemale, node, [&](NiAVObject* foundNode, NiTransform* baseTransform, OverrideRegistration<BSFixedString>* keys)
  271.     {
  272.         NiTransform combinedTransform;
  273.         for (auto dit = keys->begin(); dit != keys->end(); ++dit) {// Loop Keys
  274.             NiTransform localTransform;
  275.             GetOverrideTransform(&dit->second, OVRValue::kParam_NodeTransformPosition, &localTransform);
  276.             GetOverrideTransform(&dit->second, OVRValue::kParam_NodeTransformScale, &localTransform);
  277.             GetOverrideTransform(&dit->second, OVRValue::kParam_NodeTransformRotation, &localTransform);
  278.             combinedTransform = combinedTransform * localTransform;
  279.         }
  280.  
  281.         foundNode->m_localTransform = (*baseTransform) * combinedTransform;
  282.  
  283.         if (g_task)
  284.             g_task->AddTask(new NIOVTaskUpdateWorldData(foundNode));
  285.  
  286.         return false;
  287.     });
  288. }
  289.  
  290. bool NodeTransformManager::GetOverrideNodeTransform(TESObjectREFR * refr, bool firstPerson, bool isFemale, BSFixedString node, BSFixedString name, UInt16 key, NiTransform * result)
  291. {
  292.     return VisitNodeTransforms(refr, firstPerson, isFemale, node, [&](NiAVObject* foundNode, NiTransform* baseTransform, OverrideRegistration<BSFixedString>* keys)
  293.     {
  294.         auto it = keys->find(name);
  295.         if (it != keys->end()) {
  296.             GetOverrideTransform(&it->second, key, result);
  297.             return true;
  298.         }
  299.        
  300.         return false;
  301.     });
  302. }
  303.  
  304. void NodeTransformManager::UpdateNodeAllTransforms(TESObjectREFR * refr)
  305. {
  306.     UInt64 handle = g_overrideMapHolder.GetHandle(refr, refr->formType);
  307.     SetHandleNodeTransforms(handle);
  308. }
  309.  
  310. void NodeTransformManager::SetHandleNodeTransforms(UInt64 handle)
  311. {
  312.     TESObjectREFR * refr = (TESObjectREFR *)g_overrideMapHolder.GetObject(handle, TESObjectREFR::kTypeID);
  313.     if (!refr) {
  314.         transformData.Lock();
  315.         transformData.m_data.erase(handle);
  316.         transformData.Release();
  317.         return;
  318.     }
  319.  
  320.     UInt8 gender = 0;
  321.     TESNPC * actorBase = DYNAMIC_CAST(refr->baseForm, TESForm, TESNPC);
  322.     if (actorBase)
  323.         gender = CALL_MEMBER_FN(actorBase, GetSex)();
  324.  
  325.  
  326.     auto it = transformData.m_data.find(handle); // Find ActorHandle
  327.     if (it != transformData.m_data.end())
  328.     {
  329.         NiNode * lastNode = NULL;
  330.         for (UInt8 i = 0; i <= 1; i++)
  331.         {
  332.             NiNode * root = refr->GetNiRootNode(i);
  333.             if (root == lastNode) // First and Third are the same, skip
  334.                 continue;
  335.  
  336.             if (root)
  337.             {
  338.                 root->IncRef();
  339.                 for (auto ait = it->second[gender][i].begin(); ait != it->second[gender][i].end(); ++ait) // Loop Nodes
  340.                 {
  341.                     NiTransform * baseTransform = transformCache.GetBaseTransform(GetRootModelPath(refr, i >= 1 ? true : false, gender >= 1 ? true : false), ait->first);
  342.                     if (baseTransform)
  343.                     {
  344.                         NiTransform combinedTransform;
  345.                         for (auto dit = ait->second.begin(); dit != ait->second.end(); ++dit) {// Loop Keys
  346.                             NiTransform localTransform;
  347.                             GetOverrideTransform(&dit->second, OVRValue::kParam_NodeTransformPosition, &localTransform);
  348.                             GetOverrideTransform(&dit->second, OVRValue::kParam_NodeTransformScale, &localTransform);
  349.                             GetOverrideTransform(&dit->second, OVRValue::kParam_NodeTransformRotation, &localTransform);
  350.                             combinedTransform = combinedTransform * localTransform;
  351.                         }
  352.  
  353.                         BSFixedString nodeName = ait->first;
  354.                         NiAVObject * transformable = root->GetObjectByName(&nodeName.data);
  355.                         if (transformable) {
  356.                             transformable->m_localTransform = (*baseTransform) * combinedTransform;
  357.                         }
  358.                     }
  359.                 }
  360.                 root->DecRef();
  361.             }
  362.  
  363.             lastNode = root;
  364.  
  365.             if (g_task)
  366.                 g_task->AddTask(new NIOVTaskUpdateWorldData(root));
  367.         }
  368.     }
  369. }
  370.  
  371. void NodeTransformManager::GetOverrideTransform(OverrideSet * set, UInt16 key, NiTransform * result)
  372. {
  373.     OVRValue value;
  374.     OverrideSet::iterator it;
  375.     switch (key) {
  376.         case OVRValue::kParam_NodeTransformPosition:
  377.         {
  378.             value.key = OVRValue::kParam_NodeTransformPosition;
  379.             value.index = 0;
  380.             it = set->find(value);
  381.             if (it != set->end()) {
  382.                 result->pos.x = it->data.f;
  383.             }
  384.             value.index = 1;
  385.             it = set->find(value);
  386.             if (it != set->end()) {
  387.                 result->pos.y = it->data.f;
  388.             }
  389.             value.index = 2;
  390.             it = set->find(value);
  391.             if (it != set->end()) {
  392.                 result->pos.y = it->data.f;
  393.             }
  394.             break;
  395.         }
  396.         case OVRValue::kParam_NodeTransformScale:
  397.         {
  398.             value.key = OVRValue::kParam_NodeTransformScale;
  399.             value.index = 0;
  400.             it = set->find(value);
  401.             if (it != set->end()) {
  402.                 result->scale = it->data.f;
  403.             }
  404.         }
  405.         break;
  406.         case OVRValue::kParam_NodeTransformRotation:
  407.         {
  408.             value.key = OVRValue::kParam_NodeTransformRotation;
  409.             value.index = 0;
  410.             it = set->find(value);
  411.             if (it != set->end()) {
  412.                 result->rot.data[0][0] = it->data.f;
  413.             }
  414.             value.index = 1;
  415.             it = set->find(value);
  416.             if (it != set->end()) {
  417.                 result->rot.data[0][1] = it->data.f;
  418.             }
  419.             value.index = 2;
  420.             it = set->find(value);
  421.             if (it != set->end()) {
  422.                 result->rot.data[0][2] = it->data.f;
  423.             }
  424.             value.index = 3;
  425.             it = set->find(value);
  426.             if (it != set->end()) {
  427.                 result->rot.data[1][0] = it->data.f;
  428.             }
  429.             value.index = 4;
  430.             it = set->find(value);
  431.             if (it != set->end()) {
  432.                 result->rot.data[1][1] = it->data.f;
  433.             }
  434.             value.index = 5;
  435.             it = set->find(value);
  436.             if (it != set->end()) {
  437.                 result->rot.data[1][2] = it->data.f;
  438.             }
  439.             value.index = 6;
  440.             it = set->find(value);
  441.             if (it != set->end()) {
  442.                 result->rot.data[2][0] = it->data.f;
  443.             }
  444.             value.index = 7;
  445.             it = set->find(value);
  446.             if (it != set->end()) {
  447.                 result->rot.data[2][1] = it->data.f;
  448.             }
  449.             value.index = 8;
  450.             it = set->find(value);
  451.             if (it != set->end()) {
  452.                 result->rot.data[2][2] = it->data.f;
  453.             }
  454.         }
  455.         break;
  456.     }
  457. }
  458.  
  459.  
  460. NiTransform * NodeTransformCache::GetBaseTransform(BSFixedString rootModel, BSFixedString nodeName)
  461. {
  462.     SimpleLocker<std::unordered_map<BSFixedString, std::unordered_map<BSFixedString, NiTransform>>> lock(this);
  463.     auto it = m_data.find(rootModel);
  464.     if (it != m_data.end()) {
  465.         auto nodeIt = it->second.find(nodeName);
  466.         if (nodeIt != it->second.end()) {
  467.             return &nodeIt->second;
  468.         }
  469.     } else {
  470.         char pathBuffer[MAX_PATH];
  471.         memset(pathBuffer, 0, MAX_PATH);
  472.         sprintf_s(pathBuffer, MAX_PATH, "meshes\\%s", rootModel.data);
  473.  
  474.         BSFixedString newPath(pathBuffer);
  475.  
  476.         // No skeleton path found, why is this?
  477.         BSResourceNiBinaryStream binaryStream(newPath.data);
  478.         if (!binaryStream.IsValid()) {
  479.             return NULL;
  480.         }
  481.  
  482.         std::unordered_map<BSFixedString, NiTransform> transformMap;
  483.         NiTransform * foundTransform = NULL;
  484.  
  485.         UInt8 niStreamMemory[0x5B4];
  486.         memset(niStreamMemory, 0, 0x5B4);
  487.         NiStream * niStream = (NiStream *)niStreamMemory;
  488.         CALL_MEMBER_FN(niStream, ctor)();
  489.  
  490.         niStream->LoadStream(&binaryStream);
  491.         if (niStream->m_rootObjects.m_data)
  492.         {
  493.             for (UInt32 i = 0; i < niStream->m_rootObjects.m_size; i++) {
  494.                 NiObject * object = niStream->m_rootObjects.m_data[i];
  495.                 if (object) {
  496.                     NiAVObject * node = ni_cast(object, NiAVObject);
  497.                     if (node) {
  498.                         VisitObjects(node, [&](NiAVObject* child)
  499.                         {
  500.                             BSFixedString localName(node->m_name);
  501.                             auto ret = transformMap.insert(std::make_pair(localName, node->m_localTransform));
  502.                             if (ret.second && localName == nodeName) {
  503.                                 foundTransform = &ret.first->second;
  504.                             }
  505.                             return false;
  506.                         });
  507.                     }
  508.                 }
  509.             }
  510.         }
  511.  
  512.         CALL_MEMBER_FN(niStream, dtor)();
  513.         m_data.insert(std::make_pair(rootModel, transformMap));
  514.         return foundTransform;
  515.     }
  516.  
  517.     return NULL;
  518. }
  519.  
  520. BSFixedString NodeTransformManager::GetRootModelPath(TESObjectREFR * refr, bool firstPerson, bool isFemale)
  521. {
  522.     TESModel * model = NULL;
  523.     Character * character = DYNAMIC_CAST(refr, TESObjectREFR, Character);
  524.     if (character) {
  525.         if (firstPerson) {
  526.             Setting * setting = (*g_gameSettingCollection)->Get("sFirstPersonSkeleton");
  527.             if (setting && setting->GetType() == Setting::kType_String)
  528.                 return BSFixedString(setting->data.s);
  529.         }
  530.  
  531.         TESRace * race = character->race;
  532.         if (!race) {
  533.             TESNPC * actorBase = DYNAMIC_CAST(refr->baseForm, TESForm, TESNPC);
  534.             if (actorBase)
  535.                 race = actorBase->race.race;
  536.         }
  537.  
  538.         if (race)
  539.             model = &race->models[isFemale ? 1 : 0];
  540.     }
  541.     else
  542.         model = DYNAMIC_CAST(refr->baseForm, TESForm, TESModel);
  543.  
  544.     if (model)
  545.         return BSFixedString(model->GetModelName());
  546.  
  547.     return BSFixedString("");
  548. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement