Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class FaceGenVisitor : public TriBasedGeometryVisitor
- {
- public:
- FaceGenVisitor::FaceGenVisitor(BSFixedString faceNode, std::vector<PresetData::Texture> * faceTextures, BSFixedString tintTexture, UInt32 hairColor) : m_faceTextures(faceTextures), m_faceNode(faceNode), m_tintTexture(tintTexture), m_hairColor(hairColor) {};
- virtual bool Accept(NiTriBasedGeom * geometry)
- {
- BSShaderProperty * shaderProperty = niptr_cast<BSShaderProperty>(geometry->m_spEffectState);
- if(shaderProperty) {
- if(shaderProperty->GetRTTI() == NiRTTI_BSLightingShaderProperty) {
- BSLightingShaderProperty * lightingShader = (BSLightingShaderProperty *)shaderProperty;
- BSLightingShaderMaterial * material = (BSLightingShaderMaterial *)shaderProperty->material;
- if(BSFixedString(geometry->m_name) == m_faceNode) {
- for(std::vector<PresetData::Texture>::iterator it = m_faceTextures->begin(); it != m_faceTextures->end(); ++it)
- material->textureSet->SetTexturePath((*it).index, (*it).name.data);
- material->textureSet->SetTexturePath(6, m_tintTexture.data);
- material->ReleaseTextures();
- CALL_MEMBER_FN(lightingShader, InvalidateTextures)(0);
- CALL_MEMBER_FN(lightingShader, InitializeShader)(geometry);
- } else if(material->GetShaderType() == BSLightingShaderMaterial::kShaderType_HairTint) {
- BSTintedShaderMaterial * tintedMaterial = (BSTintedShaderMaterial *)material; // I don't know what this * 2.0 bullshit is.
- tintedMaterial->tintColor.r = (((m_hairColor >> 16) & 0xFF) / 255.0) * 2.0;
- tintedMaterial->tintColor.g = (((m_hairColor >> 8) & 0xFF) / 255.0) * 2.0;
- tintedMaterial->tintColor.b = ((m_hairColor & 0xFF) / 255.0) * 2.0;
- }
- }
- }
- return false;
- }
- BSFixedString m_faceNode;
- std::vector<PresetData::Texture> * m_faceTextures;
- BSFixedString m_tintTexture;
- UInt32 m_hairColor;
- };
- class SKSETaskOverlayCharacter : public TaskDelegate
- {
- virtual void Run()
- {
- if(m_actor && m_presetData)
- {
- TESNPC * npc = DYNAMIC_CAST(m_actor->baseForm, TESForm, TESNPC);
- BSFaceGenNiNode * faceNode = m_actor->GetFaceGenNiNode();
- if(!npc || !faceNode) {
- return;
- }
- for(std::vector<BGSHeadPart*>::iterator it = m_presetData->headParts.begin(); it != m_presetData->headParts.end(); ++it) {
- BGSHeadPart * oldPart = npc->GetCurrentHeadPartByType((*it)->type);
- CALL_MEMBER_FN(npc, ChangeHeadPart)(*it);
- ChangeActorHeadPart(m_actor, oldPart, (*it));
- }
- BGSHeadPart * facePart = npc->GetCurrentHeadPartByType(BGSHeadPart::kTypeFace);
- if(facePart) {
- FaceGenVisitor faceVisitor(facePart->partName, &m_presetData->faceTextures, m_tintPath, m_presetData->hairColor);
- VisitGeometry(faceNode, &faceVisitor);
- }
- }
- }
- virtual void Dispose()
- {
- s_loadCharacterLock.Leave();
- if(m_presetData)
- delete m_presetData;
- delete this;
- }
- public:
- SKSETaskOverlayCharacter::SKSETaskOverlayCharacter(Actor * actor, PresetData * presetData, BSFixedString tintPath) : m_actor(actor), m_presetData(presetData), m_tintPath(tintPath) {};
- Actor * m_actor;
- PresetData * m_presetData;
- BSFixedString m_tintPath;
- };
- bool LoadCharacter(StaticFunctionTag*, Actor * actor, TESRace * race, BSFixedString fileName)
- {
- if(!s_loadCharacterLock.TryEnter()) {
- return false;
- }
- PresetData * presetData = new PresetData;
- std::string path = "Data\\SKSE\\Plugins\\CharGen\\Exported\\";
- std::string slot = path;
- slot.append(fileName.data);
- slot.append(".slot");
- if(g_morphHandler.LoadPreset(slot.c_str(), presetData, true)) {
- s_loadCharacterLock.Leave();
- return false;
- }
- std::string tint = "Data\\Textures\\CharGen\\Exported\\";
- tint.append(fileName.data);
- tint.append(".dds");
- BSFixedString tintPath(tint.c_str());
- TESNPC * npc = DYNAMIC_CAST(actor->baseForm, TESForm, TESNPC);
- BSFaceGenNiNode * faceNode = actor->GetFaceGenNiNode();
- if(!npc || !faceNode) {
- s_loadCharacterLock.Leave();
- return false;
- }
- CALL_MEMBER_FN(actor, SetRace)(race, actor == (*g_thePlayer));
- npc->weight = presetData->weight;
- UInt32 i = 0;
- for(std::vector<SInt32>::iterator it = presetData->presets.begin(); it != presetData->presets.end(); ++it) {
- npc->faceMorph->presets[i] = *it;
- i++;
- }
- i = 0;
- for(std::vector<float>::iterator it = presetData->morphs.begin(); it != presetData->morphs.end(); ++it) {
- npc->faceMorph->option[i] = *it;
- i++;
- }
- // Assign custom morphs here (values only)
- g_morphHandler.Revert(npc);
- for(std::vector<PresetData::Morph>::iterator it = presetData->customMorphs.begin(); it != presetData->customMorphs.end(); ++it) {
- g_morphHandler.SetMorphValue(npc, it->name, it->value);
- }
- // Forcing a part change should invalidate the listing
- for(std::vector<BGSHeadPart*>::iterator it = presetData->headParts.begin(); it != presetData->headParts.end(); ++it)
- CALL_MEMBER_FN(npc, ChangeHeadPart)(*it);
- // Grab the skin tint and convert it from RGBA to RGB on NPC
- if(presetData->tints.size() > 0) {
- PresetData::Tint & tint = presetData->tints.at(0);
- float alpha = (tint.color >> 24) / 255.0;
- TintMask tintMask;
- tintMask.color.red = (tint.color >> 16) & 0xFF;
- tintMask.color.green = (tint.color >> 8) & 0xFF;
- tintMask.color.blue = tint.color & 0xFF;
- tintMask.alpha = alpha;
- tintMask.tintType = TintMask::kMaskType_SkinTone;
- NiColorA colorResult;
- CALL_MEMBER_FN(npc, SetSkinFromTint)(&colorResult, &tintMask, 1, 0);
- }
- // Queue a node update
- CALL_MEMBER_FN(actor, QueueNiNodeUpdate)(true);
- // Queue custom task (should happen after node update) to apply the exported FaceTint file and hair color
- g_task->AddTask(new SKSETaskOverlayCharacter(actor, presetData, tintPath));
- return true;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement