bool Cmd_SKSETestFunc_Eval(COMMAND_ARGS_EVAL) { NiNode * node = (*g_thePlayer)->GetNiNode(); UInt8 niStreamMemory[0x5B4]; NiStream * niStream = (NiStream *)niStreamMemory; CALL_MEMBER_FN(niStream, ctor)(); node->IncRef(); niStream->m_rootObjects.Append(node); niStream->SavePath("head.nif"); CALL_MEMBER_FN(niStream, dtor)(); return true; }
void SKSETaskExportHead::Run() { if (!m_formId) return; TESForm * form = LookupFormByID(m_formId); Actor * actor = DYNAMIC_CAST(form, TESForm, Actor); if (!actor) return; BSFaceGenNiNode * faceNode = actor->GetFaceGenNiNode(); TESNPC * actorBase = DYNAMIC_CAST(actor->baseForm, TESForm, TESNPC); if (!actorBase || !faceNode) return; BSFaceGenAnimationData * animationData = actor->GetFaceGenAnimationData(); if (animationData) { FaceGen::GetSingleton()->isReset = 0; for (UInt32 t = BSFaceGenAnimationData::kKeyframeType_Expression; t <= BSFaceGenAnimationData::kKeyframeType_Phoneme; t++) { BSFaceGenKeyframeMultiple * keyframe = &animationData->keyFrames[t]; for (UInt32 i = 0; i < keyframe->count; i++) keyframe->values[i] = 0.0; keyframe->isUpdated = 0; } UpdateModelFace(faceNode); } IFileStream::MakeAllDirs(m_nifPath.data); BSFadeNode * rootNode = BSFadeNode::Create(); rootNode->IncRef(); NiNode * skinnedNode = NiNode::Create(0); skinnedNode->m_name = BSFixedString("BSFaceGenNiNodeSkinned").data; std::map<NiAVObject*, NiAVObject*> boneMap; for (UInt32 i = 0; i < faceNode->m_children.m_size; i++) { NiAVObject * object = faceNode->m_children.m_data[i]; if (!object) continue; if (NiGeometry * geometry = object->GetAsNiGeometry()) { NiGeometryData * geometryData = niptr_cast<NiGeometryData>(geometry->m_spModelData); NiGeometryData * newGeometryData = NULL; if (geometryData) CALL_MEMBER_FN(geometryData, DeepCopy)((NiObject **)&newGeometryData); NiProperty * trishapeEffect = niptr_cast<NiProperty>(geometry->m_spEffectState); NiProperty * newTrishapeEffect = NULL; if (trishapeEffect) CALL_MEMBER_FN(trishapeEffect, DeepCopy)((NiObject **)&newTrishapeEffect); NiProperty * trishapeProperty = niptr_cast<NiProperty>(geometry->m_spPropertyState); NiProperty * newTrishapeProperty = NULL; if (trishapeProperty) CALL_MEMBER_FN(trishapeProperty, DeepCopy)((NiObject **)&newTrishapeProperty); NiSkinInstance * skinInstance = niptr_cast<NiSkinInstance>(geometry->m_spSkinInstance); NiSkinInstance * newSkinInstance = NULL; if (skinInstance) { newSkinInstance = skinInstance->Clone(false); newSkinInstance->m_pkRootParent = skinnedNode; UInt32 numBones = 0; NiSkinData * skinData = niptr_cast<NiSkinData>(skinInstance->m_spSkinData); NiSkinData * newSkinData = NULL; if (skinData) { numBones = skinData->m_uiBones; CALL_MEMBER_FN(skinData, DeepCopy)((NiObject **)&newSkinData); } NiSkinPartition * skinPartition = niptr_cast<NiSkinPartition>(skinInstance->m_spSkinPartition); NiSkinPartition * newSkinPartition = NULL; if (skinPartition) CALL_MEMBER_FN(skinPartition, DeepCopy)((NiObject **)&newSkinPartition); newSkinInstance->m_spSkinData = newSkinData; newSkinData->DecRef(); newSkinInstance->m_spSkinPartition = newSkinPartition; newSkinPartition->DecRef(); // Remap the bones to new NiNode instances if (numBones > 0) { newSkinInstance->m_ppkBones = (NiAVObject**)NiAllocate(numBones * sizeof(NiAVObject*)); for (UInt32 i = 0; i < numBones; i++) { NiAVObject * bone = skinInstance->m_ppkBones[i]; if (bone) { auto it = boneMap.find(bone); if (it == boneMap.end()) { NiNode * newBone = NiNode::Create(); newBone->m_name = bone->m_name; newBone->m_flags = bone->m_flags; boneMap.insert(std::make_pair(bone, newBone)); newSkinInstance->m_ppkBones[i] = newBone; } else newSkinInstance->m_ppkBones[i] = it->second; } else { newSkinInstance->m_ppkBones[i] = nullptr; } } } } NiGeometry * newGeometry = NULL; if (NiTriShape * trishape = geometry->GetAsNiTriShape()) { NiTriShape * newTrishape = NiTriShape::Create(static_cast<NiTriShapeData*>(newGeometryData)); newGeometryData->DecRef(); newTrishape->m_localTransform = geometry->m_localTransform; newTrishape->m_name = geometry->m_name; memcpy(&newTrishape->unk88, &geometry->unk88, 0x1F); newTrishape->m_spEffectState = newTrishapeEffect; newTrishape->m_spPropertyState = newTrishapeProperty; newTrishape->m_spSkinInstance = newSkinInstance; newGeometry = newTrishape; } else if (NiTriStrips * tristrips = geometry->GetAsNiTriStrips()) { NiTriStrips * newTristrips = NiTriStrips::Create(static_cast<NiTriStripsData*>(newGeometryData)); newGeometryData->DecRef(); newTristrips->m_localTransform = geometry->m_localTransform; newTristrips->m_name = geometry->m_name; memcpy(&newTristrips->unk88, &geometry->unk88, 0x1F); newTristrips->m_spEffectState = newTrishapeEffect; newTristrips->m_spPropertyState = newTrishapeProperty; newTristrips->m_spSkinInstance = newSkinInstance; newGeometry = newTristrips; } if (newGeometry) { auto textureData = GetTextureSetForPartByName(actorBase, newGeometry->m_name); if (textureData.first && textureData.second) { BSShaderProperty * shaderProperty = niptr_cast<BSShaderProperty>(newGeometry->m_spEffectState); if (shaderProperty) { if (shaderProperty->GetRTTI() == NiRTTI_BSLightingShaderProperty) { BSLightingShaderProperty * lightingShader = static_cast<BSLightingShaderProperty *>(shaderProperty); BSLightingShaderMaterial * material = static_cast<BSLightingShaderMaterial *>(shaderProperty->material); if (material && material->textureSet) { for (UInt32 i = 0; i < BGSTextureSet::kNumTextures; i++) material->textureSet->SetTexturePath(i, textureData.first->textureSet.GetTexturePath(i)); if (textureData.second->type == BGSHeadPart::kTypeFace) material->textureSet->SetTexturePath(6, m_ddsPath.data); } } } // Save the previous tint mask BSShaderProperty * originalShaderProperty = niptr_cast<BSShaderProperty>(geometry->m_spEffectState); if (originalShaderProperty) { if (originalShaderProperty->GetRTTI() == NiRTTI_BSLightingShaderProperty) { BSLightingShaderProperty * lightingShader = static_cast<BSLightingShaderProperty *>(originalShaderProperty); BSLightingShaderMaterial * material = static_cast<BSLightingShaderMaterial *>(originalShaderProperty->material); if (material) { if (material->GetShaderType() == BSShaderMaterial::kShaderType_FaceGen) { BSMaskedShaderMaterial * maskedMaterial = static_cast<BSMaskedShaderMaterial *>(material); SaveRenderedDDS(niptr_cast<NiRenderedTexture>(maskedMaterial->renderedTexture), m_ddsPath.data); } } } } } skinnedNode->AttachChild(newGeometry, true); } } } for (auto & bones : boneMap) rootNode->AttachChild(bones.second, true); rootNode->AttachChild(skinnedNode, true); UInt8 niStreamMemory[0x5B4]; memset(niStreamMemory, 0, 0x5B4); NiStream * niStream = (NiStream *)niStreamMemory; CALL_MEMBER_FN(niStream, ctor)(); CALL_MEMBER_FN(niStream, AddObject)(rootNode); niStream->SavePath(m_nifPath.data); CALL_MEMBER_FN(niStream, dtor)(); rootNode->DecRef(); if (animationData) { animationData->overrideFlag = 0; CALL_MEMBER_FN(animationData, Reset)(1.0, 1, 1, 0, 0); FaceGen::GetSingleton()->isReset = 1; UpdateModelFace(faceNode); } }