From 58f565e1da9c1d3cae6feb0151380d9c50780182 Mon Sep 17 00:00:00 2001 From: expired6978 Date: Tue, 15 Jan 2019 21:20:18 -0800 Subject: [PATCH] RM 0.3.0 Update --- skee/BodyMorphInterface.cpp | 78 +- skee/BodyMorphInterface.h | 23 +- skee/CDXBrush.cpp | 33 +- skee/CDXBrush.h | 4 - skee/CDXBrushMesh.cpp | 454 ++++ skee/CDXBrushMesh.h | 61 + skee/CDXCamera.cpp | 205 +- skee/CDXCamera.h | 62 +- skee/CDXD3DDevice.h | 21 + skee/CDXEditableMesh.cpp | 101 +- skee/CDXEditableMesh.h | 28 +- skee/CDXEditableScene.cpp | 9 +- skee/CDXEditableScene.h | 10 +- skee/CDXMaterial.cpp | 144 +- skee/CDXMaterial.h | 86 +- skee/CDXMesh.cpp | 302 ++- skee/CDXMesh.h | 67 +- skee/CDXNifBrush.cpp | 4 - skee/CDXNifBrush.h | 4 - skee/CDXNifCommands.cpp | 211 +- skee/CDXNifCommands.h | 20 +- skee/CDXNifMaterial.cpp | 12 + skee/CDXNifMaterial.h | 16 + skee/CDXNifMesh.cpp | 461 ++-- skee/CDXNifMesh.h | 68 +- skee/CDXNifScene.cpp | 349 ++- skee/CDXNifScene.h | 63 +- skee/CDXPicker.h | 3 - skee/CDXResetMask.cpp | 40 +- skee/CDXResetMask.h | 4 - skee/CDXScene.cpp | 255 +-- skee/CDXScene.h | 37 +- skee/CDXShader.cpp | 792 ++++--- skee/CDXShader.h | 83 +- skee/CDXShaderCompile.cpp | 82 + skee/CDXShaderCompile.h | 8 + skee/CDXStroke.cpp | 111 +- skee/CDXStroke.h | 20 +- skee/CDXTypes.h | 25 +- skee/CDXUndo.cpp | 8 +- skee/CDXUndo.h | 6 +- skee/FaceMorphInterface.cpp | 112 +- skee/FaceMorphInterface.h | 30 +- skee/FileUtils.cpp | 28 +- skee/FileUtils.h | 15 +- skee/Hooks_chargen.cpp | 1118 ---------- skee/MorphHandler.cpp | 3206 --------------------------- skee/MorphHandler.h | 450 ---- skee/NifUtils.cpp | 86 +- skee/NifUtils.h | 4 +- skee/OverlayInterface.cpp | 5 +- skee/PartHandler.cpp | 2 +- skee/SKEEHooks.cpp | 111 +- skee/SKEEHooks.h | 5 - skee/ScaleformCharGenFunctions.cpp | 349 +-- skee/ScaleformCharGenFunctions.h | 7 + skee/ScaleformFunctions_chargen.cpp | 1317 ----------- skee/ScaleformFunctions_chargen.h | 263 --- skee/ScaleformLoader.cpp | 10 - skee/ScaleformLoader.h | 46 - skee/StringTable.cpp | 19 +- skee/TintMaskInterface.cpp | 4 +- skee/Utilities.h | 17 + skee/main.cpp | 53 +- skee/main_chargen.cpp | 514 ----- skee/shader.ps | Bin 0 -> 1329 bytes skee/shader.vs | 72 + skee/skee64.vcxproj | 34 +- skee/skee64.vcxproj.filters | 54 +- 69 files changed, 3502 insertions(+), 8799 deletions(-) create mode 100644 skee/CDXBrushMesh.cpp create mode 100644 skee/CDXBrushMesh.h create mode 100644 skee/CDXD3DDevice.h create mode 100644 skee/CDXNifMaterial.cpp create mode 100644 skee/CDXNifMaterial.h create mode 100644 skee/CDXShaderCompile.cpp create mode 100644 skee/CDXShaderCompile.h delete mode 100644 skee/Hooks_chargen.cpp delete mode 100644 skee/MorphHandler.cpp delete mode 100644 skee/MorphHandler.h delete mode 100644 skee/ScaleformFunctions_chargen.cpp delete mode 100644 skee/ScaleformFunctions_chargen.h delete mode 100644 skee/ScaleformLoader.cpp delete mode 100644 skee/ScaleformLoader.h create mode 100644 skee/Utilities.h delete mode 100644 skee/main_chargen.cpp create mode 100644 skee/shader.ps create mode 100644 skee/shader.vs diff --git a/skee/BodyMorphInterface.cpp b/skee/BodyMorphInterface.cpp index cf42250..e2d54d1 100644 --- a/skee/BodyMorphInterface.cpp +++ b/skee/BodyMorphInterface.cpp @@ -304,16 +304,16 @@ void TriShapeFullVertexData::ApplyMorphRaw(UInt16 vertCount, void * data, float } } -void TriShapeFullVertexData::ApplyMorph(UInt16 vertexCount, NiSkinPartition::TriShape * vertexData, float factor) +void TriShapeFullVertexData::ApplyMorph(UInt16 vertexCount, Layout * vertexData, float factor) { - UInt32 offset = NiSkinPartition::GetVertexAttributeOffset(vertexData->m_VertexDesc, VertexAttribute::VA_POSITION); - UInt32 vertexSize = NiSkinPartition::GetVertexSize(vertexData->m_VertexDesc); + UInt32 offset = NiSkinPartition::GetVertexAttributeOffset(vertexData->vertexDesc, VertexAttribute::VA_POSITION); + UInt32 vertexSize = NiSkinPartition::GetVertexSize(vertexData->vertexDesc); if (m_maxIndex < vertexCount) { for (const auto & vert : m_vertexDeltas) { - DirectX::XMFLOAT4 * position = reinterpret_cast(&vertexData->m_RawVertexData[vertexSize * vert.index + offset]); + DirectX::XMFLOAT4 * position = reinterpret_cast(&vertexData->vertexData[vertexSize * vert.index + offset]); DirectX::XMStoreFloat4(position, DirectX::XMVectorAdd(DirectX::XMLoadFloat4(position), DirectX::XMVectorScale(vert.delta, factor))); } } @@ -345,16 +345,16 @@ void TriShapePackedVertexData::ApplyMorphRaw(UInt16 vertCount, void * data, floa } } -void TriShapePackedVertexData::ApplyMorph(UInt16 vertexCount, NiSkinPartition::TriShape * vertexData, float factor) +void TriShapePackedVertexData::ApplyMorph(UInt16 vertexCount, Layout * vertexData, float factor) { - UInt32 vertexSize = NiSkinPartition::GetVertexSize(vertexData->m_VertexDesc); - UInt32 offset = NiSkinPartition::GetVertexAttributeOffset(vertexData->m_VertexDesc, VertexAttribute::VA_POSITION); + UInt32 vertexSize = NiSkinPartition::GetVertexSize(vertexData->vertexDesc); + UInt32 offset = NiSkinPartition::GetVertexAttributeOffset(vertexData->vertexDesc, VertexAttribute::VA_POSITION); if (m_maxIndex < vertexCount) { for (const auto & vert : m_vertexDeltas) { - DirectX::XMFLOAT4 * position = reinterpret_cast(&vertexData->m_RawVertexData[vertexSize * vert.index + offset]); + DirectX::XMFLOAT4 * position = reinterpret_cast(&vertexData->vertexData[vertexSize * vert.index + offset]); DirectX::XMStoreFloat4(position, DirectX::XMVectorAdd(DirectX::XMLoadFloat4(position), DirectX::XMVectorScale(vert.delta, factor))); } } @@ -385,18 +385,18 @@ void TriShapePackedUVData::ApplyMorphRaw(UInt16 vertCount, void * data, float fa } } -void TriShapePackedUVData::ApplyMorph(UInt16 vertexCount, NiSkinPartition::TriShape * vertexData, float factor) +void TriShapePackedUVData::ApplyMorph(UInt16 vertexCount, Layout * vertexData, float factor) { - VertexFlags flags = NiSkinPartition::GetVertexFlags(vertexData->m_VertexDesc); + VertexFlags flags = NiSkinPartition::GetVertexFlags(vertexData->vertexDesc); if ((flags & VF_UV)) { - UInt32 vertexSize = NiSkinPartition::GetVertexSize(vertexData->m_VertexDesc); - UInt32 offset = NiSkinPartition::GetVertexAttributeOffset(vertexData->m_VertexDesc, VertexAttribute::VA_TEXCOORD0); + UInt32 vertexSize = NiSkinPartition::GetVertexSize(vertexData->vertexDesc); + UInt32 offset = NiSkinPartition::GetVertexAttributeOffset(vertexData->vertexDesc, VertexAttribute::VA_TEXCOORD0); if (m_maxIndex < vertexCount) { for (const auto & delta : m_uvDeltas) { - UVCoord * texCoord = reinterpret_cast(&vertexData->m_RawVertexData[vertexSize * delta.index + offset]); + UVCoord * texCoord = reinterpret_cast(&vertexData->vertexData[vertexSize * delta.index + offset]); texCoord->u += (float)delta.u * m_multiplier * factor; texCoord->v += (float)delta.v * m_multiplier * factor; } @@ -599,12 +599,15 @@ void MorphFileCache::ApplyMorph(TESObjectREFR * refr, NiAVObject * rootNode, boo auto & partition = newSkinPartition->m_pkPartitions[0]; UInt32 vertexSize = newSkinPartition->GetVertexSize(partition.vertexDesc); UInt32 vertexCount = newSkinPartition->vertexCount; + TriShapeVertexData::Layout layout; + layout.vertexDesc = partition.shapeData->m_VertexDesc; + layout.vertexData = partition.shapeData->m_RawVertexData; std::function vertexMorpher = [&](const TriShapeVertexDataPtr morphData, float morphFactor) { if (morphFactor != 0.0f) { - morphData->ApplyMorph(vertexCount, partition.shapeData, morphFactor); + morphData->ApplyMorph(vertexCount, &layout, morphFactor); } }; @@ -612,7 +615,7 @@ void MorphFileCache::ApplyMorph(TESObjectREFR * refr, NiAVObject * rootNode, boo { if (morphFactor != 0.0f) { - morphData->ApplyMorph(vertexCount, partition.shapeData, morphFactor); + morphData->ApplyMorph(vertexCount, &layout, morphFactor); } }; @@ -626,12 +629,11 @@ void MorphFileCache::ApplyMorph(TESObjectREFR * refr, NiAVObject * rootNode, boo memcpy(pPartition.shapeData->m_RawVertexData, partition.shapeData->m_RawVertexData, newSkinPartition->vertexCount * vertexSize); } - skinInstance->m_spSkinPartition = newSkinPartition; - newSkinPartition->DecRef(); // DeepCopy started refcount at 1 - if (mutex) mutex->lock(); - auto updateTask = new NIOVTaskUpdateSkinPartition(newSkinPartition); + auto updateTask = new NIOVTaskUpdateSkinPartition(skinInstance, newSkinPartition); + newSkinPartition->DecRef(); // DeepCopy started refcount at 1, passed ownership to the task + if (deferred) { g_task->AddTask(updateTask); @@ -1180,8 +1182,9 @@ void NIOVTaskUpdateModelWeight::Run() } } -NIOVTaskUpdateSkinPartition::NIOVTaskUpdateSkinPartition(NiSkinPartition * partition) +NIOVTaskUpdateSkinPartition::NIOVTaskUpdateSkinPartition(NiSkinInstance * skinInstance, NiSkinPartition * partition) { + m_skinInstance = skinInstance; m_partition = partition; } @@ -1192,8 +1195,10 @@ void NIOVTaskUpdateSkinPartition::Dispose(void) void NIOVTaskUpdateSkinPartition::Run() { - if (m_partition) + if (m_skinInstance && m_partition) { + EnterCriticalSection(&g_renderManager->lock); + EnterCriticalSection(&m_skinInstance->lock); auto & partition = m_partition->m_pkPartitions[0]; UInt32 vertexSize = m_partition->GetVertexSize(partition.vertexDesc); UInt32 vertexCount = m_partition->vertexCount; @@ -1206,6 +1211,10 @@ void NIOVTaskUpdateSkinPartition::Run() auto & pPartition = m_partition->m_pkPartitions[p]; deviceContext->UpdateSubresource(pPartition.shapeData->m_VertexBuffer, 0, nullptr, pPartition.shapeData->m_RawVertexData, vertexCount * vertexSize, 0); } + + m_skinInstance->m_spSkinPartition = m_partition; + LeaveCriticalSection(&m_skinInstance->lock); + LeaveCriticalSection(&g_renderManager->lock); } } @@ -1395,18 +1404,17 @@ bool BodyMorphInterface::ReadBodyMorphTemplates(SKEEFixedString filePath) return true; } -void BodyMorphInterface::GetFilteredNPCList(std::vector activeNPCs[], UInt8 modIndex, UInt16 lightIndex, UInt32 gender, TESRace * raceFilter) +void BodyMorphInterface::GetFilteredNPCList(std::vector activeNPCs[], const ModInfo * modInfo, UInt32 gender, TESRace * raceFilter) { for (UInt32 i = 0; i < (*g_dataHandler)->npcs.count; i++) { TESNPC * npc = nullptr; if ((*g_dataHandler)->npcs.GetNthItem(i, npc)) { - bool matchMod = modIndex == 0xFF || (npc->formID >> 24) == modIndex; - bool matchLightMod = lightIndex == 0xFFFF || (((npc->formID & 0xFF000000) == 0xFE000000) && (lightIndex == ((npc->formID >> 12) & 0xFFF))); + bool matchMod = modInfo ? modInfo->IsFormInMod(npc->formID) : false; bool matchRace = (raceFilter == nullptr || npc->race.race == raceFilter); - if (npc && npc->nextTemplate == nullptr && matchMod && matchLightMod && matchRace) + if (npc && npc->nextTemplate == nullptr && matchMod && matchRace) { if (gender == 0xFF) { @@ -1497,14 +1505,12 @@ bool BodyMorphInterface::ReadBodyMorphs(SKEEFixedString filePath) paramIndex++; } - GetFilteredNPCList(activeNPCs, 0xFF, 0xFFFF, gender, foundRace); + GetFilteredNPCList(activeNPCs, nullptr, gender, foundRace); } else { - UInt8 modIndex = (*g_dataHandler)->GetLoadedModIndex(modNameText.c_str()); - UInt16 lightIndex = (*g_dataHandler)->GetLoadedLightModIndex(modNameText.c_str()); - - if (modIndex == 0xFF && lightIndex == 0xFFFF) { + const ModInfo * modInfo = (*g_dataHandler)->LookupModByName(modNameText.c_str()); + if (!modInfo || !modInfo->IsActive()) { _WARNING("%s - Warning - Mod '%s' not a loaded mod.\tLine (%d) [%s]", __FUNCTION__, modNameText.c_str(), lineCount, filePath.c_str()); continue; } @@ -1543,7 +1549,7 @@ bool BodyMorphInterface::ReadBodyMorphs(SKEEFixedString filePath) paramIndex++; } - GetFilteredNPCList(activeNPCs, modIndex, lightIndex, gender, foundRace); + GetFilteredNPCList(activeNPCs, modInfo, gender, foundRace); } else // Fallout4.esm|XXXX[|Gender] { @@ -1553,12 +1559,7 @@ bool BodyMorphInterface::ReadBodyMorphs(SKEEFixedString filePath) continue; } - UInt32 formId = 0; - if (lightIndex != 0xFFFF) - formId = 0xFE000000 | (UInt32(lightIndex) << 12) | (formLower & 0xFFFFFF); - else - formId = UInt32(modIndex) << 24 | formLower & 0xFFFFFF; - + UInt32 formId = modInfo->GetFormID(formLower); foundForm = LookupFormByID(formId); if (!foundForm) { _ERROR("%s - Error - Invalid form %08X.\tLine (%d) [%s]", __FUNCTION__, formId, lineCount, filePath.c_str()); @@ -1566,7 +1567,6 @@ bool BodyMorphInterface::ReadBodyMorphs(SKEEFixedString filePath) } } - if (foundForm) { TESLevCharacter * levCharacter = DYNAMIC_CAST(foundForm, TESForm, TESLevCharacter); @@ -1813,7 +1813,7 @@ bool BodyMorph::Load(SKSESerializationInterface * intfc, UInt32 kVersion, const { m_name = StringTable::ReadString(intfc, stringTable); } - else if (kVersion >= BodyMorphInterface::kSerializationVersion2) + else if (kVersion >= BodyMorphInterface::kSerializationVersion1) { char * stringName = NULL; UInt8 stringLength; diff --git a/skee/BodyMorphInterface.h b/skee/BodyMorphInterface.h index da3f7c4..e92e5e0 100644 --- a/skee/BodyMorphInterface.h +++ b/skee/BodyMorphInterface.h @@ -40,6 +40,7 @@ class NiExtraData; class TESNPC; class TESRace; class NiSkinPartition; +struct ModInfo; #define MORPH_MOD_DIRECTORY "actors\\character\\BodyGenData\\" @@ -108,7 +109,14 @@ class TriShapeVertexData { public: virtual void ApplyMorphRaw(UInt16 vertCount, void * vertices, float factor) = 0; - virtual void ApplyMorph(UInt16 vertexCount, NiSkinPartition::TriShape * vertexData, float factor) = 0; + + struct Layout + { + UInt64 vertexDesc; + UInt8 * vertexData; + }; + + virtual void ApplyMorph(UInt16 vertexCount, Layout * vertexData, float factor) = 0; }; typedef std::shared_ptr TriShapeVertexDataPtr; @@ -118,7 +126,7 @@ class TriShapeFullVertexData : public TriShapeVertexData TriShapeFullVertexData() : m_maxIndex(0) { } virtual void ApplyMorphRaw(UInt16 vertCount, void * vertices, float factor); - virtual void ApplyMorph(UInt16 vertexCount, NiSkinPartition::TriShape * vertexData, float factor); + virtual void ApplyMorph(UInt16 vertexCount, Layout * vertexData, float factor); UInt32 m_maxIndex; std::vector m_vertexDeltas; @@ -131,7 +139,7 @@ class TriShapePackedVertexData : public TriShapeVertexData TriShapePackedVertexData() : m_maxIndex(0) { } virtual void ApplyMorphRaw(UInt16 vertCount, void * vertices, float factor); - virtual void ApplyMorph(UInt16 vertexCount, NiSkinPartition::TriShape * vertexData, float factor); + virtual void ApplyMorph(UInt16 vertexCount, Layout * vertexData, float factor); float m_multiplier; UInt32 m_maxIndex; @@ -151,7 +159,7 @@ class TriShapePackedUVData : public TriShapeVertexData }; virtual void ApplyMorphRaw(UInt16 vertCount, void * vertices, float factor); - virtual void ApplyMorph(UInt16 vertexCount, NiSkinPartition::TriShape * vertexData, float factor); + virtual void ApplyMorph(UInt16 vertexCount, Layout * vertexData, float factor); float m_multiplier; UInt32 m_maxIndex; @@ -243,10 +251,11 @@ class NIOVTaskUpdateSkinPartition : public TaskDelegate virtual void Run(); virtual void Dispose(); - NIOVTaskUpdateSkinPartition(NiSkinPartition * partition); + NIOVTaskUpdateSkinPartition(NiSkinInstance * skinInstance, NiSkinPartition * partition); private: - NiPointer m_partition; + NiPointer m_partition; + NiPointer m_skinInstance; }; class BodyGenMorphData @@ -346,7 +355,7 @@ class BodyMorphInterface : public IPluginInterface virtual void VisitActors(std::function functor); protected: - void GetFilteredNPCList(std::vector activeNPCs[], UInt8 modIndex, UInt16 lightIndex, UInt32 gender, TESRace * raceFilter); + void GetFilteredNPCList(std::vector activeNPCs[], const ModInfo * modInfo, UInt32 gender, TESRace * raceFilter); private: ActorMorphs actorMorphs; diff --git a/skee/CDXBrush.cpp b/skee/CDXBrush.cpp index 4b48dc3..fac3c0c 100644 --- a/skee/CDXBrush.cpp +++ b/skee/CDXBrush.cpp @@ -1,11 +1,11 @@ -#ifdef FIXME - #include "CDXBrush.h" #include "CDXMesh.h" #include "CDXUndo.h" #include "CDXShader.h" #include "CDXMaterial.h" +using namespace DirectX; + double g_brushProperties[CDXBrush::kBrushTypes][CDXBrush::kBrushProperties][CDXBrush::kBrushPropertyValues]; void CDXBrush::InitGlobals() @@ -143,7 +143,7 @@ float CDXBrush::CalculateFalloff(float & dist) double y = -(1.0 - (1.0 - falloff)) * ((dist / radius) - 1.0) + (1.0 - falloff); y = y*y*(3 - 2 * y); - return y; + return (float)y; /*double p = 1.0f; @@ -175,25 +175,26 @@ float CDXBrush::CalculateFalloff(float & dist) CDXHitIndexMap CDXBasicHitBrush::GetHitIndices(CDXPickInfo & pickInfo, CDXEditableMesh * mesh) { - CDXMeshVert * pVertices = mesh->LockVertices(); + CDXMeshVert * pVertices = mesh->LockVertices(CDXMesh::LockMode::READ); CDXHitIndexMap hitVertex; - for (UInt32 i = 0; i < mesh->GetVertexCount(); i++) { + for (UInt16 i = 0; i < mesh->GetVertexCount(); i++) { if (FilterVertex(mesh, pVertices, i)) continue; - CDXVec3 vTest = pVertices[i].Position; - CDXVec3 vDiff = pickInfo.origin - vTest; - float testRadius = D3DXVec3Length(&vDiff); // Spherical radius + + CDXVec vTest = XMLoadFloat3(&pVertices[i].Position); + CDXVec vDiff = XMVectorSubtract(pickInfo.origin, vTest); + float testRadius = XMVectorGetX(XMVector3Length(vDiff)); // Spherical radius if (testRadius <= m_property[kBrushProperty_Radius][kBrushPropertyValue_Value]) { hitVertex.emplace(i, CalculateFalloff(testRadius)); } } - mesh->UnlockVertices(); + mesh->UnlockVertices(CDXMesh::LockMode::READ); return hitVertex; } bool CDXBasicHitBrush::FilterVertex(CDXEditableMesh * mesh, CDXMeshVert * pVertices, CDXMeshIndex i) { - if (pVertices[i].Color != COLOR_UNSELECTED) + if (XMVector3NotEqual(XMLoadFloat3(&pVertices[i].Color), COLOR_UNSELECTED)) return true; return false; @@ -303,11 +304,11 @@ bool CDXInflateBrush::UpdateStroke(CDXPickInfo & pickInfo, CDXEditableMesh * mes auto hitVertex = GetHitIndices(pickInfo, stroke->GetMesh()); - CDXVec3 normal(0, 0, 0); + CDXVec normal = XMVectorZero(); for (auto i : hitVertex) { - normal += mesh->CalculateVertexNormal(i.first); + normal = XMVectorAdd(normal, mesh->CalculateVertexNormal(i.first)); } - XMVector3Normalize(&normal, &normal); + normal = XMVector3Normalize(normal); for (auto i : hitVertex) { CDXInflateStroke::InflateInfo strokeInfo; @@ -472,9 +473,9 @@ bool CDXMoveBrush::UpdateStroke(CDXPickInfo & pickInfo, CDXEditableMesh * mesh, DebugOut("%d - %f", strokeInfo.index, strokeInfo.falloff); #endif*/ CDXRayInfo rayStart = moveStroke->GetRayInfo(); - CDXVec3 d = pickInfo.ray.point - rayStart.point; + CDXVec d = pickInfo.ray.point - rayStart.point; if (isMirror) - d.x = -d.x; + d = XMVectorSetX(d, -XMVectorGetX(d)); strokeInfo.offset = d; stroke->Update(&strokeInfo); } @@ -482,5 +483,3 @@ bool CDXMoveBrush::UpdateStroke(CDXPickInfo & pickInfo, CDXEditableMesh * mesh, return true; } - -#endif \ No newline at end of file diff --git a/skee/CDXBrush.h b/skee/CDXBrush.h index 2652532..3d10db2 100644 --- a/skee/CDXBrush.h +++ b/skee/CDXBrush.h @@ -1,5 +1,3 @@ -#ifdef FIXME - #ifndef __CDXBRUSH__ #define __CDXBRUSH__ @@ -175,5 +173,3 @@ class CDXMoveBrush : public CDXBasicHitBrush }; #endif - -#endif \ No newline at end of file diff --git a/skee/CDXBrushMesh.cpp b/skee/CDXBrushMesh.cpp new file mode 100644 index 0000000..b6867f7 --- /dev/null +++ b/skee/CDXBrushMesh.cpp @@ -0,0 +1,454 @@ +#include "CDXBrushMesh.h" +#include "CDXD3DDevice.h" +#include "CDXShader.h" +#include "CDXShaderCompile.h" +#include "CDXBrush.h" + +using namespace DirectX; + +CDXBrushMesh::CDXBrushMesh() : CDXMesh() +{ + m_vertexShader = nullptr; + m_pixelShader = nullptr; + m_solidState = nullptr; + m_layout = nullptr; +} + +bool CDXBrushMesh::Create(CDXD3DDevice * device, bool dashed, XMVECTOR ringColor, XMVECTOR dotColor, const ShaderFileData & vertexShaderData, const ShaderFileData & pixelShaderData) +{ + static unsigned int NUM_VERTS = 360 / 5; + static const float RADIUS = 1.0f; + static const float RADIUS_STEP = 5.0f * (XM_PI / 180.0f); + + ID3DBlob* vertexShaderBuffer; + ID3DBlob* pixelShaderBuffer; + D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc; + D3D11_SUBRESOURCE_DATA vertexData, indexData; + HRESULT result; + + m_pDevice = device; + m_vertCount = NUM_VERTS; + m_indexCount = NUM_VERTS; + + m_dashed = dashed; + + auto pDevice = device->GetDevice(); + auto pDeviceContext = device->GetDeviceContext(); + + // Create the vertex array. + m_primitive = new ColoredPrimitive[m_vertCount]; + if (!m_primitive) + { + return false; + } + + // Create the index array. + m_indices = new CDXMeshIndex[m_indexCount]; + if (!m_indices) + { + return false; + } + + ComputeSphere(m_sphere.m_vertices, m_sphere.m_indices, 1.0f, 10, 10, dotColor); + + + float i = 0; + for (unsigned int j = 0; j < m_vertCount; j++) + { + m_primitive[j].Position = XMVectorSet(sin(i) * RADIUS, cos(i) * RADIUS, 0, 0); + m_primitive[j].Color = ringColor; + + i += RADIUS_STEP; + } + + for (unsigned int j = 0; j < m_vertCount; j++) + { + m_indices[j] = j; + } + + // Set up the description of the static vertex buffer. + vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + vertexBufferDesc.ByteWidth = sizeof(ColoredPrimitive) * m_vertCount; + vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + vertexBufferDesc.MiscFlags = 0; + vertexBufferDesc.StructureByteStride = 0; + + // Give the subresource structure a pointer to the vertex data. + vertexData.pSysMem = m_primitive; + vertexData.SysMemPitch = 0; + vertexData.SysMemSlicePitch = 0; + + // Now create the vertex buffer. + result = pDevice->CreateBuffer(&vertexBufferDesc, &vertexData, &m_vertexBuffer); + if (FAILED(result)) + { + _ERROR("%s - Failed to create vertex buffer 1", __FUNCTION__); + return false; + } + + vertexData.pSysMem = &m_sphere.m_vertices.at(0); + vertexBufferDesc.ByteWidth = sizeof(ColoredPrimitive) * m_sphere.m_vertices.size(); + + // Now create the vertex buffer. + result = pDevice->CreateBuffer(&vertexBufferDesc, &vertexData, &m_sphere.m_vertexBuffer); + if (FAILED(result)) + { + _ERROR("%s - Failed to create vertex buffer 2", __FUNCTION__); + return false; + } + + // Set up the description of the static index buffer. + indexBufferDesc.Usage = D3D11_USAGE_DEFAULT; + indexBufferDesc.ByteWidth = sizeof(CDXMeshIndex) * m_indexCount; + indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + indexBufferDesc.CPUAccessFlags = 0; + indexBufferDesc.MiscFlags = 0; + indexBufferDesc.StructureByteStride = 0; + + // Give the subresource structure a pointer to the index data. + indexData.pSysMem = m_indices; + indexData.SysMemPitch = 0; + indexData.SysMemSlicePitch = 0; + + // Create the index buffer. + result = pDevice->CreateBuffer(&indexBufferDesc, &indexData, &m_indexBuffer); + if (FAILED(result)) + { + _ERROR("%s - Failed to create index buffer 1", __FUNCTION__); + return false; + } + + indexData.pSysMem = &m_sphere.m_indices.at(0); + indexBufferDesc.ByteWidth = sizeof(CDXMeshIndex) * m_sphere.m_indices.size(); + + // Create the index buffer. + result = pDevice->CreateBuffer(&indexBufferDesc, &indexData, &m_sphere.m_indexBuffer); + if (FAILED(result)) + { + _ERROR("%s - Failed to create index buffer 2", __FUNCTION__); + return false; + } + + // Compile the vertex shader code. + result = CompileShaderFromData(vertexShaderData.pSrcData, vertexShaderData.SrcDataSize, vertexShaderData.pSourceName, "BrushVShader", "vs_5_0", &vertexShaderBuffer, nullptr); + if (FAILED(result)) + { + _ERROR("%s - Failed to compile vertex shader", __FUNCTION__); + return false; + } + + // Create the vertex shader from the buffer. + result = pDevice->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &m_vertexShader); + if (FAILED(result)) + { + _ERROR("%s - Failed to create vertex shader", __FUNCTION__); + return false; + } + + + // Compile the pixel shader code. + result = CompileShaderFromData(pixelShaderData.pSrcData, pixelShaderData.SrcDataSize, pixelShaderData.pSourceName, "BrushPShader", "ps_5_0", &pixelShaderBuffer, nullptr); + if (FAILED(result)) + { + _ERROR("%s - Failed to compile pixel shader", __FUNCTION__); + return false; + } + + result = pDevice->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &m_pixelShader); + if (FAILED(result)) + { + _ERROR("%s - Failed to create pixel shader", __FUNCTION__); + return false; + } + + D3D11_INPUT_ELEMENT_DESC polygonLayout[2]; + polygonLayout[0].SemanticName = "POSITION"; + polygonLayout[0].SemanticIndex = 0; + polygonLayout[0].Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + polygonLayout[0].InputSlot = 0; + polygonLayout[0].AlignedByteOffset = 0; + polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[0].InstanceDataStepRate = 0; + + polygonLayout[1].SemanticName = "COLOR"; + polygonLayout[1].SemanticIndex = 0; + polygonLayout[1].Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + polygonLayout[1].InputSlot = 0; + polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[1].InstanceDataStepRate = 0; + + // Get a count of the elements in the layout. + unsigned int numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]); + + // Create the vertex input layout. + result = pDevice->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), + vertexShaderBuffer->GetBufferSize(), &m_layout); + if (FAILED(result)) + { + _ERROR("%s - Failed to create input layout", __FUNCTION__); + return false; + } + + vertexShaderBuffer->Release(); + vertexShaderBuffer = 0; + + pixelShaderBuffer->Release(); + pixelShaderBuffer = 0; + + // Setup the raster description which will determine how and what polygons will be drawn. + D3D11_RASTERIZER_DESC rasterDesc; + rasterDesc.AntialiasedLineEnable = true; + rasterDesc.CullMode = D3D11_CULL_BACK; + rasterDesc.DepthBias = -2000; + rasterDesc.DepthBiasClamp = 0.0f; + rasterDesc.DepthClipEnable = true; + rasterDesc.FillMode = D3D11_FILL_SOLID; + rasterDesc.FrontCounterClockwise = false; + rasterDesc.MultisampleEnable = true; + rasterDesc.ScissorEnable = false; + rasterDesc.SlopeScaledDepthBias = 0.0f; + + // Create the rasterizer state from the description we just filled out. + result = pDevice->CreateRasterizerState(&rasterDesc, &m_solidState); + if (FAILED(result)) + { + _ERROR("%s - Failed to create rasterizer state", __FUNCTION__); + return false; + } + + return true; +} + +void CDXBrushMesh::ComputeSphere(std::vector& vertices, std::vector & indices, float radius, int sliceCount, int stackCount, DirectX::XMVECTOR color) +{ + CDXMesh::ColoredPrimitive vertex; + vertex.Position = XMVectorSet(0, radius, 0, 0); + vertex.Color = color; + vertices.push_back(vertex); + + float phiStep = XM_PI / stackCount; + float thetaStep = XM_2PI / sliceCount; + + for (int i = 1; i <= stackCount - 1; i++) { + float phi = i * phiStep; + for (int j = 0; j <= sliceCount; j++) { + float theta = j * thetaStep; + XMVECTOR p = XMVectorSet( + (radius*sin(phi)*cos(theta)), + (radius*cos(phi)), + (radius*sin(phi)*sin(theta)), + 0 + ); + + //p = XMVector3Rotate(p, XMQuaternionRotationRollPitchYaw(0, 0, XM_PI)); + + vertex.Position = p; + vertices.push_back(vertex); + } + } + + vertex.Position = XMVectorSet(0, -radius, 0, 0); + vertices.push_back(vertex); + + for (int i = 1; i <= sliceCount; i++) { + indices.push_back(0); + indices.push_back(i + 1); + indices.push_back(i); + } + int baseIndex = 1; + int ringVertexCount = sliceCount + 1; + for (int i = 0; i < stackCount - 2; i++) { + for (int j = 0; j < sliceCount; j++) { + indices.push_back(baseIndex + i * ringVertexCount + j); + indices.push_back(baseIndex + i * ringVertexCount + j + 1); + indices.push_back(baseIndex + (i + 1)*ringVertexCount + j); + + indices.push_back(baseIndex + (i + 1)*ringVertexCount + j); + indices.push_back(baseIndex + i * ringVertexCount + j + 1); + indices.push_back(baseIndex + (i + 1)*ringVertexCount + j + 1); + } + } + int southPoleIndex = vertices.size() - 1; + baseIndex = southPoleIndex - ringVertexCount; + for (int i = 0; i < sliceCount; i++) { + indices.push_back(southPoleIndex); + indices.push_back(baseIndex + i); + indices.push_back(baseIndex + i + 1); + } + + /* + vertices.clear(); + indices.clear(); + + int tessellation = sliceCount; + float diameter = radius * 2.0f; + + if (tessellation < 3) + throw std::out_of_range("tesselation parameter out of range"); + + size_t verticalSegments = tessellation; + size_t horizontalSegments = tessellation * 2; + + // Create rings of vertices at progressively higher latitudes. + for (size_t i = 0; i <= verticalSegments; i++) + { + //float v = 1 - float(i) / verticalSegments; + + float latitude = (i * XM_PI / verticalSegments) - XM_PIDIV2; + float dy, dxz; + + XMScalarSinCos(&dy, &dxz, latitude); + + // Create a single ring of vertices at this latitude. + for (size_t j = 0; j <= horizontalSegments; j++) + { + //float u = float(j) / horizontalSegments; + + float longitude = j * XM_2PI / horizontalSegments; + float dx, dz; + + XMScalarSinCos(&dx, &dz, longitude); + + dx *= dxz; + dz *= dxz; + + XMVECTOR normal = XMVectorSet(dx, dy, dz, 0); + //XMVECTOR textureCoordinate = XMVectorSet(u, v, 0, 0); + + CDXMesh::ColoredPrimitive prim; + prim.Position = XMVectorScale(normal, radius); + prim.Color = color; + vertices.push_back(prim); + } + } + + // Fill the index buffer with triangles joining each pair of latitude rings. + size_t stride = horizontalSegments + 1; + + for (size_t i = 0; i < verticalSegments; i++) + { + for (size_t j = 0; j <= horizontalSegments; j++) + { + size_t nextI = i + 1; + size_t nextJ = (j + 1) % stride; + + indices.push_back(i * stride + j); + indices.push_back(nextI * stride + j); + indices.push_back(i * stride + nextJ); + + indices.push_back(i * stride + nextJ); + indices.push_back(nextI * stride + j); + indices.push_back(nextI * stride + nextJ); + } + }*/ +} + +void CDXBrushMesh::Render(CDXD3DDevice * pDevice, CDXShader * shader) +{ + unsigned int stride = sizeof(ColoredPrimitive); + unsigned int offset = 0; + + auto pDeviceContext = pDevice->GetDeviceContext(); + + // Set the vertex buffer to active in the input assembler so it can be rendered. + pDeviceContext->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &offset); + + // Set the index buffer to active in the input assembler so it can be rendered. + pDeviceContext->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R16_UINT, 0); + + // Set the type of primitive that should be rendered from this vertex buffer, in this case triangles. + pDeviceContext->IASetPrimitiveTopology(m_dashed ? D3D11_PRIMITIVE_TOPOLOGY_LINELIST : D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP); + + pDeviceContext->IASetInputLayout(m_layout); + pDeviceContext->RSSetState(m_solidState); + pDeviceContext->VSSetShader(m_vertexShader, NULL, 0); + pDeviceContext->PSSetShader(m_pixelShader, NULL, 0); + + pDeviceContext->DrawIndexed(m_indexCount, 0, 0); + + CDXShader::TransformBuffer xform; + xform.transform = GetSphereTransform(); + shader->VSSetTransformBuffer(pDevice, xform); + + pDeviceContext->IASetVertexBuffers(0, 1, &m_sphere.m_vertexBuffer, &stride, &offset); + pDeviceContext->IASetIndexBuffer(m_sphere.m_indexBuffer, DXGI_FORMAT_R16_UINT, 0); + pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + pDeviceContext->DrawIndexed(m_sphere.m_indices.size(), 0, 0); +} + +void CDXBrushMesh::Release() +{ + __super::Release(); + + if (m_pixelShader) + { + m_pixelShader->Release(); + m_pixelShader = nullptr; + } + + // Release the vertex shader. + if (m_vertexShader) + { + m_vertexShader->Release(); + m_vertexShader = nullptr; + } + + if (m_solidState) + { + m_solidState->Release(); + m_solidState = nullptr; + } + + if (m_layout) + { + m_layout->Release(); + m_layout = nullptr; + } +} + +bool CDXBrushMesh::Pick(CDXRayInfo & rayInfo, CDXPickInfo & pickInfo) +{ + return false; +} + +bool CDXBrushTranslator::Pick(CDXPickInfo & pickInfo, CDXMesh * mesh, bool isMirror) +{ + auto brush = isMirror ? m_brushMeshMirror : m_brushMesh; + + if (isMirror && !m_brush->IsMirror()) { + brush->SetVisible(false); + return false; + } + + if (mesh->IsEditable()) + { + if (pickInfo.isHit) + { + double scale = m_brush->GetProperty(CDXBrush::BrushProperty::kBrushProperty_Radius, CDXBrush::BrushPropertyValue::kBrushPropertyValue_Value); + + auto n2 = pickInfo.normal; + auto n1 = XMVectorSet(0, 0, 1, 0); + auto rotation = XMQuaternionRotationMatrix(XMMatrixRotationAxis(XMVector3Cross(n1, n2), acos(XMVectorGetX(XMVector3Dot(n1, n2))))); + auto offset = XMVectorMultiplyAdd(XMVectorReplicate(0.05), n2, pickInfo.origin); + + CDXMatrix transform1 = XMMatrixAffineTransformation(XMVectorReplicate(scale), XMVectorZero(), rotation, offset); + CDXMatrix transform2 = XMMatrixAffineTransformation(XMVectorReplicate(1.0f/16.0f), XMVectorZero(), rotation, offset); + + brush->SetTransform(XMMatrixTranspose(transform1)); + brush->SetSphereTransform(XMMatrixTranspose(transform2)); + brush->SetVisible(true); + return true; + } + } + + brush->SetVisible(false); + return false; +} + +bool CDXBrushTranslator::Mirror() const +{ + return true; +} \ No newline at end of file diff --git a/skee/CDXBrushMesh.h b/skee/CDXBrushMesh.h new file mode 100644 index 0000000..09160b3 --- /dev/null +++ b/skee/CDXBrushMesh.h @@ -0,0 +1,61 @@ +#pragma once + +#include "CDXMesh.h" +#include "CDXPicker.h" + +class CDXBrush; +struct ShaderFileData; + +class CDXBrushMesh : public CDXMesh +{ +public: + CDXBrushMesh(); + + bool Create(CDXD3DDevice * pDevice, bool dashed, DirectX::XMVECTOR ringColor, DirectX::XMVECTOR dotColor, const ShaderFileData & vertexShaderData, const ShaderFileData & pixelShaderData); + + virtual void Render(CDXD3DDevice * pDevice, CDXShader * shader) override; + virtual void Release() override; + virtual bool Pick(CDXRayInfo & rayInfo, CDXPickInfo & pickInfo) override; + + const CDXMatrix & GetSphereTransform() { return m_sphere.m_transform; }; + void SetSphereTransform(const CDXMatrix & mat) { m_sphere.m_transform = mat; } + +protected: + struct Sphere + { + std::vector m_vertices; + ID3D11Buffer* m_vertexBuffer; + std::vector m_indices; + ID3D11Buffer* m_indexBuffer; + CDXMatrix m_transform; + }; + + void ComputeSphere(std::vector& vertices, std::vector & indices, float radius, int sliceCount, int stackCount, DirectX::XMVECTOR color); + +private: + ID3D11VertexShader * m_vertexShader; + ID3D11PixelShader* m_pixelShader; + ID3D11RasterizerState* m_solidState; + ID3D11Buffer* m_matrixBuffer; + ID3D11InputLayout* m_layout; + Sphere m_sphere; + bool m_dashed; +}; + +class CDXBrushTranslator : public CDXPicker +{ +public: + CDXBrushTranslator(CDXBrush * brush, CDXBrushMesh * brushMesh, CDXBrushMesh * brushMeshMirror) + : m_brush(brush) + , m_brushMesh(brushMesh) + , m_brushMeshMirror(brushMeshMirror) + { } + + virtual bool Pick(CDXPickInfo & pickInfo, CDXMesh * mesh, bool isMirror) override; + virtual bool Mirror() const override; + +private: + CDXBrush * m_brush; + CDXBrushMesh * m_brushMesh; + CDXBrushMesh * m_brushMeshMirror; +}; \ No newline at end of file diff --git a/skee/CDXCamera.cpp b/skee/CDXCamera.cpp index 2475758..556cd81 100644 --- a/skee/CDXCamera.cpp +++ b/skee/CDXCamera.cpp @@ -1,24 +1,24 @@ #include "CDXCamera.h" -#ifdef FIXME +using namespace DirectX; CDXArcBall::CDXArcBall() { Reset(); - m_vDownPt = DirectX::XMVectorZero(); - m_vCurrentPt = DirectX::XMVectorZero(); + m_vDownPt = XMVectorZero(); + m_vCurrentPt = XMVectorZero(); m_Offset.x = m_Offset.y = 0; } //-------------------------------------------------------------------------------------- void CDXArcBall::Reset() { - m_qDown = DirectX::XMQuaternionIdentity(); - m_qNow = DirectX::XMQuaternionIdentity(); + m_qDown = XMQuaternionIdentity(); + m_qNow = XMQuaternionIdentity(); - m_mRotation = DirectX::XMMatrixIdentity(); - m_mTranslation = DirectX::XMMatrixIdentity(); - m_mTranslationDelta = DirectX::XMMatrixIdentity(); + m_mRotation = XMMatrixIdentity(); + m_mTranslation = XMMatrixIdentity(); + m_mTranslationDelta = XMMatrixIdentity(); m_bDrag = FALSE; m_fRadiusTranslation = 1.0f; @@ -45,15 +45,15 @@ CDXVec CDXArcBall::ScreenToVector( float fScreenPtX, float fScreenPtY ) z = sqrtf( 1.0f - mag ); // Return vector - return DirectX::XMVectorSet(x, y, z, 1); + return XMVectorSet(x, y, z, 1); } //-------------------------------------------------------------------------------------- CDXVec CDXArcBall::QuatFromBallPoints( const CDXVec& vFrom, const CDXVec& vTo ) { - float fDot = DirectX::XMVectorGetX(DirectX::XMVector3Dot(vFrom, vTo)); - CDXVec vPart = DirectX::XMVector3Cross(vFrom, vTo); - return DirectX::XMVectorSet(DirectX::XMVectorGetX(vPart), DirectX::XMVectorGetY(vPart), DirectX::XMVectorGetZ(vPart), fDot ); + float fDot = XMVectorGetX(XMVector3Dot(vFrom, vTo)); + CDXVec vPart = XMVector3Cross(vFrom, vTo); + return XMVectorSet(XMVectorGetX(vPart), XMVectorGetY(vPart), XMVectorGetZ(vPart), fDot ); } //-------------------------------------------------------------------------------------- @@ -78,7 +78,7 @@ void CDXArcBall::OnRotate( int nX, int nY ) if( m_bDrag ) { m_vCurrentPt = ScreenToVector( ( float )nX, ( float )nY ); - m_qNow = DirectX::XMVectorMultiply(m_qDown, QuatFromBallPoints( m_vDownPt, m_vCurrentPt )); + m_qNow = XMQuaternionMultiply(m_qDown, QuatFromBallPoints( m_vDownPt, m_vCurrentPt )); } } @@ -101,40 +101,7 @@ VOID CDXModelViewerCamera::SetProjParams( FLOAT fFOV, FLOAT fAspect, FLOAT fNear m_fNearPlane = fNearPlane; m_fFarPlane = fFarPlane; - m_mProj = DirectX::XMMatrixPerspectiveFovLH(fFOV, fAspect, fNearPlane, fFarPlane ); -} -/* -void CDXModelViewerCamera::UpdateMouseDelta(int currentX, int currentY) -{ - POINT ptCurMouseDelta; - POINT ptCurMousePos; - ptCurMousePos.x = currentX; - ptCurMousePos.y = currentY; - - // Calc how far it's moved since last frame - ptCurMouseDelta.x = ptCurMousePos.x - m_ptLastMousePosition.x; - ptCurMouseDelta.y = ptCurMousePos.y - m_ptLastMousePosition.y; - - // Record current position for next time - m_ptLastMousePosition = ptCurMousePos; - - // Smooth the relative mouse data over a few frames so it isn't - // jerky when moving slowly at low frame rates. - float fPercentOfNew = 1.0f / m_fFramesToSmoothMouseData; - float fPercentOfOld = 1.0f - fPercentOfNew; - m_vMouseDelta.x = m_vMouseDelta.x * fPercentOfOld + ptCurMouseDelta.x * fPercentOfNew; - m_vMouseDelta.y = m_vMouseDelta.y * fPercentOfOld + ptCurMouseDelta.y * fPercentOfNew; - - m_vRotVelocity = m_vMouseDelta * m_fRotationScaler; -} -*/ -//-------------------------------------------------------------------------------------- -// Clamps pV to lie inside m_vMinBoundary & m_vMaxBoundary -//-------------------------------------------------------------------------------------- -void CDXModelViewerCamera::ConstrainToBoundary( CDXVec* pV ) -{ - // Constrain vector to a bounding box - *pV = DirectX::XMVectorClamp(*pV, m_vMinBoundary, m_vMaxBoundary); + m_mProj = XMMatrixPerspectiveFovLH(fFOV, fAspect, fNearPlane, fFarPlane ); } //-------------------------------------------------------------------------------------- @@ -142,44 +109,23 @@ void CDXModelViewerCamera::ConstrainToBoundary( CDXVec* pV ) //-------------------------------------------------------------------------------------- CDXModelViewerCamera::CDXModelViewerCamera() { - CDXVec vEyePt = DirectX::XMVectorZero(); - CDXVec vLookatPt = DirectX::XMVectorSet(0, 0, 1.0f, 0); + CDXVec vEyePt = XMVectorZero(); + CDXVec vLookatPt = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f); // Setup the view matrix SetViewParams( &vEyePt, &vLookatPt ); // Setup the projection matrix - SetProjParams( DirectX::XM_PI / 4, 1.0f, 1.0f, 1000.0f ); - - //m_ptLastMousePosition.x = 0; - //m_ptLastMousePosition.y = 0; - - m_fCameraYawAngle = 0.0f; - m_fCameraPitchAngle = 0.0f; - - //SetRect( &m_rcDrag, LONG_MIN, LONG_MIN, LONG_MAX, LONG_MAX ); - m_vVelocity = DirectX::XMVectorZero(); - //m_bMovementDrag = false; - //m_vVelocityDrag = CDXVec( 0, 0, 0 ); - //m_fDragTimer = 0.0f; - //m_fTotalDragTimeToZero = 0.25; - //m_vRotVelocity = D3DXVECTOR2( 0, 0 ); - - //m_fRotationScaler = 0.01f; - //m_fMoveScaler = 5.0f; + SetProjParams(60 * (XM_PI / 180.0f), 1.0f, 1.0f, 1000.0f); - //m_vMouseDelta = D3DXVECTOR2( 0, 0 ); - //m_fFramesToSmoothMouseData = 2.0f; + m_vMinBoundary = XMVectorSet(-1, -1, -1, 1); + m_vMaxBoundary = XMVectorSet(1, 1, 1, 1); - m_bClipToBoundary = false; - m_vMinBoundary = DirectX::XMVectorSet(-1, -1, -1, 0); - m_vMaxBoundary = DirectX::XMVectorSet(1, 1, 1, 0); + m_mWorld = XMMatrixIdentity(); + m_mModelRot = XMMatrixIdentity(); + m_mModelLastRot = XMMatrixIdentity(); - m_mWorld = DirectX::XMMatrixIdentity(); - m_mModelRot = DirectX::XMMatrixIdentity(); - m_mModelLastRot = DirectX::XMMatrixIdentity(); - m_mCameraRotLast = DirectX::XMMatrixIdentity(); - m_vModelCenter = DirectX::XMVectorZero(); + m_vModelCenter = XMVectorSet(0, 0, 0, 1); m_fRadius = 5.0f; m_fDefaultRadius = 5.0f; m_fMinRadius = 1.0f; @@ -190,7 +136,6 @@ CDXModelViewerCamera::CDXModelViewerCamera() void CDXModelViewerCamera::OnRotate(int currentX, int currentY) { - //UpdateMouseDelta(currentX, currentY); m_WorldArcBall.OnRotate(currentX, currentY); m_bDragSinceLastUpdate = true; Update(); @@ -199,21 +144,22 @@ void CDXModelViewerCamera::OnRotate(int currentX, int currentY) void CDXModelViewerCamera::OnMoveBegin(int currentX, int currentY) { m_vDragLook = m_vLookAt; - m_vDragStart = DirectX::XMVectorSet(currentX, currentY, 0, 0); + m_vDragStart = XMVectorSet((float)currentX, 0, (float)currentY, 0); m_vDragPos = m_vDragStart; } void CDXModelViewerCamera::OnMove(int x, int y) { - m_vDragPos = DirectX::XMVectorSet(x, y, 0, 0); + m_vDragPos = XMVectorSet((float)x, 0, (float)y, 0); m_vLookAt = m_vDragLook; - auto multiplier = DirectX::XMVectorMultiply(DirectX::XMVectorReplicate(m_fPanMultiplier), DirectX::XMVectorSet(-1, 1, 1, 1)); + auto multiplier = XMVectorSetW(XMVectorReplicate(m_fPanMultiplier), 0.0f); + multiplier = XMVectorSetZ(multiplier, -XMVectorGetZ(multiplier)); - auto panDelta = DirectX::XMVectorMultiply(DirectX::XMVectorSubtract(m_vDragPos, m_vDragStart), multiplier); + auto panDelta = XMVectorMultiply(XMVectorSubtract(m_vDragPos, m_vDragStart), multiplier); - m_vLookAt = DirectX::XMVectorAdd(m_vLookAt, panDelta); + m_vLookAt = XMVectorAdd(m_vLookAt, panDelta); m_bDragSinceLastUpdate = true; Update(); @@ -222,8 +168,8 @@ void CDXModelViewerCamera::OnMove(int x, int y) void CDXModelViewerCamera::OnMoveEnd() { m_vDragLook = m_vLookAt; - m_vDragStart = DirectX::XMVectorZero(); - m_vDragPos = DirectX::XMVectorZero(); + m_vDragStart = XMVectorSet(0, 0, 0, 1); + m_vDragPos = XMVectorSet(0, 0, 0, 1); } void CDXModelViewerCamera::Update() @@ -234,76 +180,47 @@ void CDXModelViewerCamera::Update() return; m_bDragSinceLastUpdate = false; - // Simple euler method to calculate position delta - //CDXVec vPosDelta = m_vVelocity; - // Change the radius from the camera to the model based on wheel scrolling m_fRadius = __min( m_fMaxRadius, m_fRadius ); m_fRadius = __max( m_fMinRadius, m_fRadius ); - // Get the inverse of the arcball's rotation matrix - - auto det = DirectX::XMMatrixDeterminant(m_ViewArcBall.GetRotationMatrix()); - auto mCameraRot = DirectX::XMMatrixInverse(&det, m_ViewArcBall.GetRotationMatrix()); - - //D3DXMATRIX mCameraRot; - //D3DXMatrixRotationYawPitchRoll(&mCameraRot, m_fCameraYawAngle, m_fCameraPitchAngle, 0); + auto mCameraRot = XMMatrixInverse(nullptr, m_ViewArcBall.GetRotationMatrix()); // Transform vectors based on camera's rotation matrix CDXVec vWorldUp, vWorldAhead; - CDXVec vLocalUp = DirectX::XMVectorSet( 0, 1, 0, 0 ); - CDXVec vLocalAhead = DirectX::XMVectorSet(0, 0, 1, 0 ); + CDXVec vLocalUp = XMVectorSet( 0, 1, 0, 1 ); + CDXVec vLocalAhead = XMVectorSet(0, 0, 1, 1 ); vWorldUp = XMVector3TransformCoord(vLocalUp, mCameraRot ); vWorldAhead = XMVector3TransformCoord(vLocalAhead, mCameraRot ); - // Transform the position delta by the camera's rotation - /*CDXVec vPosDeltaWorld; - D3DXVec3TransformCoord( &vPosDeltaWorld, &vPosDelta, &mCameraRot ); - - // Move the lookAt position - m_vLookAt += vPosDeltaWorld; - if( m_bClipToBoundary ) - ConstrainToBoundary( &m_vLookAt );*/ - - /*m_vEye += vPosDeltaWorld; - if (m_bClipToBoundary) - ConstrainToBoundary(&m_vEye);*/ - // Update the eye point based on a radius away from the lookAt position - m_vEye = DirectX::XMVectorScale(DirectX::XMVectorSubtract(m_vLookAt, vWorldAhead), m_fRadius); - //m_vLookAt = m_vEye + vWorldAhead * m_fRadius; + m_vEye = XMVectorSubtract(m_vLookAt, XMVectorScale(vWorldAhead, m_fRadius)); // Update the view matrix - m_mView = DirectX::XMMatrixLookAtLH( m_vEye, m_vLookAt, vWorldUp ); - - auto mInvViewDet = DirectX::XMMatrixDeterminant(m_mView); - auto mInvView = DirectX::XMMatrixInverse(&mInvViewDet, m_mView); + m_mView = XMMatrixLookAtLH( m_vEye, m_vLookAt, vWorldUp ); - mInvView.r[3] = DirectX::XMVectorZero(); + auto mInvView = XMMatrixInverse(nullptr, m_mView); - auto mModelLastRotInvDet = DirectX::XMMatrixDeterminant(m_mModelLastRot); - auto mModelLastRotInv = DirectX::XMMatrixInverse(&mModelLastRotInvDet, m_mModelLastRot); + mInvView.r[3] = XMVectorZero(); - // Accumulate the delta of the arcball's rotation in view space. - // Note that per-frame delta rotations could be problematic over long periods of time. + auto mModelLastRotInv = XMMatrixInverse(nullptr, m_mModelLastRot); + auto mModelRot = m_WorldArcBall.GetRotationMatrix(); + m_mModelRot *= m_mView * mModelLastRotInv * mModelRot * mInvView; - m_mCameraRotLast = mCameraRot; m_mModelLastRot = mModelRot; // Since we're accumulating delta rotations, we need to orthonormalize // the matrix to prevent eventual matrix skew - m_mModelRot.r[0] = DirectX::XMVector3Normalize(m_mModelRot.r[0]); - m_mModelRot.r[1] = DirectX::XMVector3Cross(m_mModelRot.r[2], m_mModelRot.r[0]); - m_mModelRot.r[1] = DirectX::XMVector3Normalize(m_mModelRot.r[1]); - m_mModelRot.r[2] = DirectX::XMVector3Cross(m_mModelRot.r[0], m_mModelRot.r[1]); + m_mModelRot.r[0] = XMVector3Normalize(m_mModelRot.r[0]); + m_mModelRot.r[1] = XMVector3Cross(m_mModelRot.r[2], m_mModelRot.r[0]); + m_mModelRot.r[1] = XMVector3Normalize(m_mModelRot.r[1]); + m_mModelRot.r[2] = XMVector3Cross(m_mModelRot.r[0], m_mModelRot.r[1]); m_mModelRot.r[3] = m_vModelCenter; - // Translate world matrix so its at the center of the model - //D3DXMatrixTranslation( &mTrans, -m_vModelCenter.x, -m_vModelCenter.y, -m_vModelCenter.z ); - m_mWorld = DirectX::XMMatrixScaling(-1.0, 1.0, 1.0) * m_mModelRot; + m_mWorld = m_mModelRot; } //-------------------------------------------------------------------------------------- @@ -313,10 +230,9 @@ VOID CDXModelViewerCamera::Reset() { SetViewParams( &m_vDefaultEye, &m_vDefaultLookAt ); - m_mWorld = DirectX::XMMatrixIdentity(); - m_mModelRot = DirectX::XMMatrixIdentity(); - m_mModelLastRot = DirectX::XMMatrixIdentity(); - m_mCameraRotLast = DirectX::XMMatrixIdentity(); + m_mWorld = XMMatrixIdentity(); + m_mModelRot = XMMatrixIdentity(); + m_mModelLastRot = XMMatrixIdentity(); m_fRadius = m_fDefaultRadius; m_WorldArcBall.Reset(); @@ -336,33 +252,26 @@ void CDXModelViewerCamera::SetViewParams( CDXVec* pvEyePt, CDXVec* pvLookatPt ) m_vDefaultLookAt = m_vLookAt = *pvLookatPt; // Calc the view matrix - CDXVec vUp = DirectX::XMVectorSet( 0,1,0,1 ); - m_mView = DirectX::XMMatrixLookAtLH( *pvEyePt, *pvLookatPt, vUp ); + CDXVec vUp = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f ); + m_mView = XMMatrixLookAtLH( *pvEyePt, *pvLookatPt, vUp ); - auto m_mViewDet = DirectX::XMMatrixDeterminant(m_mView); - auto mInvView = DirectX::XMMatrixInverse(&m_mViewDet, m_mView); + auto mInvView = XMMatrixInverse(nullptr, m_mView); // The axis basis vectors and camera position are stored inside the // position matrix in the 4 rows of the camera's world matrix. // To figure out the yaw/pitch of the camera, we just need the Z basis vector - CDXVec* pZBasis = ( CDXVec* )&mInvView.r[3]; - - m_fCameraYawAngle = atan2f(DirectX::XMVectorGetX(*pZBasis), DirectX::XMVectorGetZ(*pZBasis)); - float fLen = sqrtf(DirectX::XMVectorGetZ(*pZBasis) * DirectX::XMVectorGetZ(*pZBasis) + DirectX::XMVectorGetX(*pZBasis) * DirectX::XMVectorGetX(*pZBasis)); - m_fCameraPitchAngle = -atan2f(DirectX::XMVectorGetY(*pZBasis), fLen ); // Propogate changes to the member arcball - auto mRotation = DirectX::XMMatrixLookAtLH(*pvEyePt, *pvLookatPt, vUp); - mRotation = DirectX::XMMatrixRotationRollPitchYaw(-DirectX::XM_PI / 2, 0, 0); + auto mRotation = XMMatrixLookAtLH(*pvEyePt, *pvLookatPt, vUp); + mRotation = XMMatrixRotationRollPitchYaw(-XM_PI / 2.0f, 0, 0); - auto quat = DirectX::XMQuaternionRotationMatrix(mRotation); + auto quat = XMQuaternionRotationMatrix(mRotation); m_ViewArcBall.SetQuatNow( quat ); // Set the radius according to the distance - CDXVec vEyeToPoint = DirectX::XMVectorSubtract(*pvLookatPt, *pvEyePt); - SetRadius( DirectX::XMVectorGetX(DirectX::XMVector3Length(vEyeToPoint))); + CDXVec vEyeToPoint = XMVectorSubtract(*pvLookatPt, *pvEyePt); + SetRadius( XMVectorGetX(XMVector3Length(vEyeToPoint))); // View information changed. FrameMove should be called. m_bDragSinceLastUpdate = true; } -#endif \ No newline at end of file diff --git a/skee/CDXCamera.h b/skee/CDXCamera.h index 4dd4df5..a5de7a0 100644 --- a/skee/CDXCamera.h +++ b/skee/CDXCamera.h @@ -2,10 +2,23 @@ #define _CDXCAMERA_H_ #pragma once -#ifdef FIXME - #include "CDXTypes.h" +class CDXCamera +{ +public: + virtual const CDXMatrix* GetWorldMatrix() const = 0; + virtual const CDXMatrix& GetViewMatrix() const = 0; + virtual const CDXMatrix& GetProjMatrix() const = 0; + virtual const CDXVec& GetEyePt() const = 0; + virtual const CDXVec& GetLookAtPt() const = 0; + + virtual int GetWidth() const = 0; + virtual int GetHeight() const = 0; + + virtual void Update() = 0; +}; + class CDXArcBall { public: @@ -59,17 +72,18 @@ class CDXArcBall CDXVec ScreenToVector( float fScreenPtX, float fScreenPtY ); }; -class CDXModelViewerCamera +class CDXModelViewerCamera : public CDXCamera { public: CDXModelViewerCamera(); - const CDXMatrix& GetViewMatrix() const { return m_mView; } - const CDXMatrix& GetProjMatrix() const { return m_mProj; } - const CDXVec& GetEyePt() const { return m_vEye; } - const CDXVec& GetLookAtPt() const { return m_vLookAt; } + virtual const CDXMatrix* GetWorldMatrix() const override { return &m_mWorld; } + virtual const CDXMatrix& GetViewMatrix() const override { return m_mView; } + virtual const CDXMatrix& GetProjMatrix() const override { return m_mProj; } + virtual const CDXVec& GetEyePt() const override { return m_vEye; } + virtual const CDXVec& GetLookAtPt() const override { return m_vLookAt; } + virtual void Update() override; - void Update(); void Reset(); void SetViewParams( CDXVec* pvEyePt, CDXVec* pvLookatPt ); void SetWindow( int nWidth, int nHeight, float fArcballRadius=0.9f ) { m_WorldArcBall.SetWindow( nWidth, nHeight, fArcballRadius ); m_ViewArcBall.SetWindow( nWidth, nHeight, fArcballRadius ); } @@ -78,12 +92,10 @@ class CDXModelViewerCamera void SetViewQuat( CDXVec q ) { m_ViewArcBall.SetQuatNow( q ); m_bDragSinceLastUpdate = true; } void SetWorldQuat( CDXVec q ) { m_WorldArcBall.SetQuatNow( q ); m_bDragSinceLastUpdate = true; } void SetProjParams( FLOAT fFOV, FLOAT fAspect, FLOAT fNearPlane, FLOAT fFarPlane ); - //void UpdateMouseDelta(int currentX, int currentY); - void ConstrainToBoundary( CDXVec* pV ); float GetRadius() const { return m_fRadius; } - int GetWidth() const { return m_WorldArcBall.GetWidth(); } - int GetHeight() const { return m_WorldArcBall.GetHeight(); } + virtual int GetWidth() const override { return m_WorldArcBall.GetWidth(); } + virtual int GetHeight() const override { return m_WorldArcBall.GetHeight(); } void OnRotateBegin(int x, int y) { m_WorldArcBall.OnRotateBegin(x, y); } void OnRotate(int x, int y); @@ -94,49 +106,27 @@ class CDXModelViewerCamera void OnMoveEnd(); void SetPanSpeed(float speed) { m_fPanMultiplier = speed; }; - - // Functions to get state - const CDXMatrix* GetWorldMatrix() const { return &m_mWorld; } void SetWorldMatrix( CDXMatrix &mWorld ) { m_mWorld = mWorld; m_bDragSinceLastUpdate = true; } protected: CDXMatrix m_mView; // View matrix CDXMatrix m_mProj; // Projection matrix - //CDXVec3 m_vKeyboardDirection; // Direction vector of keyboard input - //POINT m_ptLastMousePosition; // Last absolute position of mouse cursor - //CDXVec2 m_vMouseDelta; // Mouse relative delta smoothed over a few frames - //float m_fFramesToSmoothMouseData; // Number of frames to smooth mouse data over - CDXVec m_vDefaultEye; // Default camera eye position CDXVec m_vDefaultLookAt; // Default LookAt position CDXVec m_vEye; // Camera eye position CDXVec m_vLookAt; // LookAt position - float m_fCameraYawAngle; // Yaw angle of camera - float m_fCameraPitchAngle; // Pitch angle of camera float m_fPanMultiplier; CDXVec m_vDragLook; CDXVec m_vDragStart; CDXVec m_vDragPos; - //RECT m_rcDrag; // Rectangle within which a drag can be initiated. - CDXVec m_vVelocity; // Velocity of camera - //bool m_bMovementDrag; // If true, then camera movement will slow to a stop otherwise movement is instant - //CDXVec3 m_vVelocityDrag; // Velocity drag force - //float m_fDragTimer; // Countdown timer to apply drag - //float m_fTotalDragTimeToZero; // Time it takes for velocity to go from full to 0 - //CDXVec2 m_vRotVelocity; // Velocity of camera - float m_fFOV; // Field of view float m_fAspect; // Aspect ratio float m_fNearPlane; // Near plane float m_fFarPlane; // Far plane - //float m_fRotationScaler; // Scaler for rotation - //float m_fMoveScaler; // Scaler for movement - - bool m_bClipToBoundary; // If true, then the camera will be clipped to the boundary CDXVec m_vMinBoundary; // Min point in clip boundary CDXVec m_vMaxBoundary; // Max point in clip boundary @@ -152,9 +142,5 @@ class CDXModelViewerCamera float m_fMinRadius; // Min radius float m_fMaxRadius; // Max radius bool m_bDragSinceLastUpdate; // True if mouse drag has happened since last time FrameMove is called. - - CDXMatrix m_mCameraRotLast; - }; #endif -#endif \ No newline at end of file diff --git a/skee/CDXD3DDevice.h b/skee/CDXD3DDevice.h new file mode 100644 index 0000000..fb4d91f --- /dev/null +++ b/skee/CDXD3DDevice.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +class CDXD3DDevice +{ +public: + CDXD3DDevice() : m_pDevice(nullptr), m_pDeviceContext(nullptr) { } + CDXD3DDevice(const Microsoft::WRL::ComPtr & pDevice, const Microsoft::WRL::ComPtr & pDeviceContext) : m_pDevice(pDevice), m_pDeviceContext(pDeviceContext){} + + void SetDevice(const Microsoft::WRL::ComPtr & d) { m_pDevice = d; } + void setDeviceContext(const Microsoft::WRL::ComPtr & d) { m_pDeviceContext = d; } + + Microsoft::WRL::ComPtr GetDevice() { return m_pDevice; } + Microsoft::WRL::ComPtr GetDeviceContext() { return m_pDeviceContext; } + +protected: + Microsoft::WRL::ComPtr m_pDevice; + Microsoft::WRL::ComPtr m_pDeviceContext; +}; \ No newline at end of file diff --git a/skee/CDXEditableMesh.cpp b/skee/CDXEditableMesh.cpp index 40d2a6d..0c50661 100644 --- a/skee/CDXEditableMesh.cpp +++ b/skee/CDXEditableMesh.cpp @@ -2,7 +2,7 @@ #include "CDXMaterial.h" #include "CDXShader.h" -#ifdef FIXME +using namespace DirectX; CDXEditableMesh::CDXEditableMesh() : CDXMesh() { @@ -16,12 +16,12 @@ CDXEditableMesh::~CDXEditableMesh() m_vertexEdges.clear(); } -bool CDXEditableMesh::IsEditable() +bool CDXEditableMesh::IsEditable() const { return true; } -bool CDXEditableMesh::IsLocked() +bool CDXEditableMesh::IsLocked() const { #ifdef CDX_MUTEX std::lock_guard guard(m_mutex); @@ -29,7 +29,7 @@ bool CDXEditableMesh::IsLocked() return m_locked; } -bool CDXEditableMesh::ShowWireframe() +bool CDXEditableMesh::ShowWireframe() const { #ifdef CDX_MUTEX std::lock_guard guard(m_mutex); @@ -51,6 +51,66 @@ void CDXEditableMesh::SetLocked(bool l) m_locked = l; } +void CDXEditableMesh::BuildAdjacency() +{ + CDXMeshIndex* pIndices = LockIndices(); + + if (!pIndices) + return; + + for (UInt16 i = 0; i < GetVertexCount(); i++) { + for (UInt32 f = 0; f < GetFaceCount(); f++) { + CDXMeshFace * face = (CDXMeshFace *)&pIndices[f * 3]; + if (i == face->v1 || i == face->v2 || i == face->v3) + m_adjacency[i].push_back(*face); + } + } + + UnlockIndices(); +} + +void CDXEditableMesh::BuildFacemap() +{ + CDXMeshIndex* pIndices = LockIndices(); + if (!pIndices) + return; + + CDXEdgeMap edges; + for (UInt32 f = 0; f < GetFaceCount(); f++) + { + CDXMeshFace * face = (CDXMeshFace *)&pIndices[f * 3]; + auto it = edges.emplace(CDXMeshEdge(min(face->v1, face->v2), max(face->v1, face->v2)), 1); + if (it.second == false) + it.first->second++; + it = edges.emplace(CDXMeshEdge(min(face->v2, face->v3), max(face->v2, face->v3)), 1); + if (it.second == false) + it.first->second++; + it = edges.emplace(CDXMeshEdge(min(face->v3, face->v1), max(face->v3, face->v1)), 1); + if (it.second == false) + it.first->second++; + } + + for (auto e : edges) { + if (e.second == 1) { + m_vertexEdges.insert(e.first.p1); + m_vertexEdges.insert(e.first.p2); + } + } + UnlockIndices(); +} + +void CDXEditableMesh::BuildNormals() +{ + CDXMeshVert* pVertices = LockVertices(LockMode::WRITE); + if (!pVertices) + return; + + for (UInt16 i = 0; i < GetVertexCount(); i++) { + XMStoreFloat3(&pVertices[i].Normal, CalculateVertexNormal(i)); + } + UnlockVertices(LockMode::WRITE); +} + void CDXEditableMesh::VisitAdjacencies(CDXMeshIndex i, std::function functor) { #ifdef CDX_MUTEX @@ -65,32 +125,26 @@ void CDXEditableMesh::VisitAdjacencies(CDXMeshIndex i, std::functionSetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - CDXMesh::Render(pDevice, shader); // Render again but in wireframe if (m_wireframe) { - //pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); - - /*if (m_material) { + // Now set the rasterizer state. + if (m_material) { m_material->SetWireframe(true); CDXMesh::Render(pDevice, shader); m_material->SetWireframe(false); - }*/ + } } } CDXVec CDXEditableMesh::CalculateVertexNormal(CDXMeshIndex i) { - CDXMeshVert* pVertices = NULL; - CDXMeshIndex* pIndices = NULL; + CDXMeshVert* pVertices = LockVertices(LockMode::READ); - CDXVec vNormal = DirectX::XMVectorZero(); - ID3D11Buffer * pVB = GetVertexBuffer(); - //pVB->Lock(0, 0, (void**)&pVertices, 0); + CDXVec vNormal = XMVectorZero(); if (!pVertices) return vNormal; @@ -101,17 +155,17 @@ CDXVec CDXEditableMesh::CalculateVertexNormal(CDXMeshIndex i) CDXMeshVert * v2 = &pVertices[tri.v2]; CDXMeshVert * v3 = &pVertices[tri.v3]; - auto e1 = DirectX::XMVectorSubtract(DirectX::XMLoadFloat3(&v2->Position), DirectX::XMLoadFloat3(&v1->Position)); - auto e2 = DirectX::XMVectorSubtract(DirectX::XMLoadFloat3(&v3->Position), DirectX::XMLoadFloat3(&v2->Position)); + auto e1 = XMVectorSubtract(XMLoadFloat3(&v2->Position), XMLoadFloat3(&v1->Position)); + auto e2 = XMVectorSubtract(XMLoadFloat3(&v3->Position), XMLoadFloat3(&v2->Position)); - auto faceNormal = DirectX::XMVector3Cross(e1, e2); - faceNormal = DirectX::XMVector3Normalize(faceNormal); - DirectX::XMVectorAdd(vNormal, faceNormal); + auto faceNormal = XMVector3Cross(e1, e2); + faceNormal = XMVector3Normalize(faceNormal); + vNormal = XMVectorAdd(vNormal, faceNormal); } - DirectX::XMVector3Normalize(vNormal); + vNormal = XMVector3Normalize(vNormal); } - //pVB->Unlock(); + UnlockVertices(LockMode::READ); return vNormal; } @@ -123,4 +177,3 @@ bool CDXEditableMesh::IsEdgeVertex(CDXMeshIndex i) const return false; } -#endif \ No newline at end of file diff --git a/skee/CDXEditableMesh.h b/skee/CDXEditableMesh.h index ae7d15d..0e0c2cc 100644 --- a/skee/CDXEditableMesh.h +++ b/skee/CDXEditableMesh.h @@ -3,8 +3,6 @@ #pragma once -#ifdef FIXME - #include "CDXMesh.h" #include @@ -17,8 +15,8 @@ typedef std::unordered_map CDXMaskMap; typedef std::pair CDXMaskPair; -typedef std::unordered_map CDXVectorMap; -typedef std::pair CDXVectorPair; +typedef std::unordered_map CDXVectorMap; +typedef std::pair CDXVectorPair; typedef std::vector CDXAdjacentList; typedef std::map CDXAdjacencyMap; @@ -26,29 +24,36 @@ typedef std::map CDXAdjacencyMap; typedef std::unordered_map CDXEdgeMap; typedef std::unordered_set CDXVertexEdgeList; -#define COLOR_UNSELECTED CDXColor(255, 255, 255, 255) -#define COLOR_SELECTED CDXColor(0, 0, 255, 255) +#define COLOR_UNSELECTED XMVectorSet(1.0, 1.0, 1.0, 1.0) +#define COLOR_SELECTED XMVectorSet(0, 0, 1.0, 1.0) class CDXEditableMesh : public CDXMesh { public: CDXEditableMesh(); - ~CDXEditableMesh(); + virtual ~CDXEditableMesh(); - virtual void Render(ID3D11Device * pDevice, CDXShader * shader); - virtual bool IsEditable(); - virtual bool IsLocked(); + virtual void Render(CDXD3DDevice * pDevice, CDXShader * shader); + virtual bool IsEditable() const override; + virtual bool IsLocked() const override; + virtual bool ShowWireframe() const override; - bool ShowWireframe(); void SetShowWireframe(bool wf); void SetLocked(bool l); + void BuildAdjacency(); + void BuildFacemap(); + void BuildNormals(); + void VisitAdjacencies(CDXMeshIndex i, std::function functor); bool IsEdgeVertex(CDXMeshIndex i) const; CDXVec CalculateVertexNormal(CDXMeshIndex i); protected: +#ifdef CDX_MUTEX + mutable std::mutex m_mutex; +#endif CDXAdjacencyMap m_adjacency; CDXVertexEdgeList m_vertexEdges; bool m_wireframe; @@ -56,4 +61,3 @@ class CDXEditableMesh : public CDXMesh }; #endif -#endif diff --git a/skee/CDXEditableScene.cpp b/skee/CDXEditableScene.cpp index 93933d1..4804b85 100644 --- a/skee/CDXEditableScene.cpp +++ b/skee/CDXEditableScene.cpp @@ -1,9 +1,6 @@ #include "CDXEditableScene.h" #include "CDXShader.h" -#ifdef FIXME - -extern CDXModelViewerCamera g_Camera; extern CDXUndoStack g_undoStack; CDXEditableScene::CDXEditableScene() : CDXScene() @@ -29,10 +26,10 @@ void CDXEditableScene::ReleaseBrushes() m_brushes.clear(); } -void CDXEditableScene::Setup(ID3D11Device * pDevice) +bool CDXEditableScene::Setup(const CDXInitParams & initParams) { CreateBrushes(); - CDXScene::Setup(pDevice); + return CDXScene::Setup(initParams); } void CDXEditableScene::Release() @@ -61,5 +58,3 @@ void CDXEditableScene::SetCurrentBrush(CDXBrush::BrushType brushType) { m_currentBrush = brushType; } - -#endif \ No newline at end of file diff --git a/skee/CDXEditableScene.h b/skee/CDXEditableScene.h index e70831e..86207ed 100644 --- a/skee/CDXEditableScene.h +++ b/skee/CDXEditableScene.h @@ -1,11 +1,11 @@ -#ifdef FIXME - #ifndef __CDXEDITABLESCENE__ #define __CDXEDITABLESCENE__ #pragma once #include "CDXScene.h" +#include "CDXBrush.h" +#include "CDXTypes.h" typedef std::vector CDXBrushList; @@ -14,8 +14,8 @@ class CDXEditableScene : public CDXScene public: CDXEditableScene(); - virtual void Setup(ID3D11Device * pDevice); - virtual void Release(); + virtual bool Setup(const CDXInitParams & initParams) override; + virtual void Release() override; virtual void CreateBrushes(); virtual void ReleaseBrushes(); @@ -31,5 +31,3 @@ class CDXEditableScene : public CDXScene }; #endif - -#endif \ No newline at end of file diff --git a/skee/CDXMaterial.cpp b/skee/CDXMaterial.cpp index f8813db..9632e07 100644 --- a/skee/CDXMaterial.cpp +++ b/skee/CDXMaterial.cpp @@ -1,13 +1,18 @@ +#include "CDXD3DDevice.h" #include "CDXMaterial.h" +#include "CDXShader.h" -#ifdef FIXME +using namespace DirectX; CDXMaterial::CDXMaterial() { - m_diffuseTexture = NULL; - m_specularColor = DirectX::XMFLOAT3(1.0f, 1.0f, 1.0f); - m_diffuseColor = DirectX::XMFLOAT3(1.0f, 1.0f, 1.0f); - m_ambientColor = DirectX::XMFLOAT3(1.0f, 1.0f, 1.0f); + m_pTextures[0] = nullptr; + m_pTextures[1] = nullptr; + m_pTextures[2] = nullptr; + m_pTextures[3] = nullptr; + m_pTextures[4] = nullptr; + m_wireframeColor = XMFLOAT4(1.0f, 1.0f, 1.0f, 0.0f); + m_tintColor = XMFLOAT4(0.0f, 0.0f, 0.0f, 0.0f); m_alphaThreshold = 0; m_shaderFlags1 = 0; m_shaderFlags2 = 0; @@ -16,52 +21,78 @@ CDXMaterial::CDXMaterial() SetDestBlendMode(ALPHA_INVSRCALPHA); SetTestMode(TEST_ALWAYS); m_wireframe = false; + m_blendingDirty = true; + m_blendingState = nullptr; } CDXMaterial::~CDXMaterial() { - + if (m_blendingState) + { + m_blendingState->Release(); + m_blendingState = nullptr; + } } void CDXMaterial::Release() { - SetDiffuseTexture(NULL); + SetTexture(0, nullptr); + SetTexture(1, nullptr); + SetTexture(2, nullptr); + SetTexture(3, nullptr); + SetTexture(4, nullptr); } -void CDXMaterial::SetDiffuseTexture(LPDIRECT3DBASETEXTURE9 texture) +void CDXMaterial::SetTexture(int index, ID3D11ShaderResourceView* texture) { #ifdef CDX_MUTEX std::lock_guard guard(m_mutex); #endif - if(m_diffuseTexture) - m_diffuseTexture->Release(); - m_diffuseTexture = texture; - if(m_diffuseTexture) - m_diffuseTexture->AddRef(); + if(m_pTextures[index]) + m_pTextures[index]->Release(); + m_pTextures[index] = texture; + if(m_pTextures[index]) + m_pTextures[index]->AddRef(); } -void CDXMaterial::SetDiffuseColor(DirectX::XMFLOAT3 color) +ID3D11BlendState1* CDXMaterial::GetBlendingState(CDXD3DDevice * device) { -#ifdef CDX_MUTEX - std::lock_guard guard(m_mutex); -#endif - m_diffuseColor = color; -} -void CDXMaterial::SetSpecularColor(DirectX::XMFLOAT3 color) -{ -#ifdef CDX_MUTEX - std::lock_guard guard(m_mutex); -#endif - m_specularColor = color; -} -void CDXMaterial::SetAmbientColor(DirectX::XMFLOAT3 color) -{ -#ifdef CDX_MUTEX - std::lock_guard guard(m_mutex); -#endif - m_ambientColor = color; + if (m_blendingDirty) + { + if (m_blendingState) + { + m_blendingState->Release(); + m_blendingState = nullptr; + } + + D3D11_BLEND_DESC1 blendStateDescription; + // Clear the blend state description. + ZeroMemory(&blendStateDescription, sizeof(D3D11_BLEND_DESC1)); + + // Create an alpha enabled blend state description. + blendStateDescription.RenderTarget[0].BlendEnable = GetAlphaBlending(); + blendStateDescription.RenderTarget[0].SrcBlend = GetD3DBlendMode(GetSrcBlendMode()); + blendStateDescription.RenderTarget[0].DestBlend = GetD3DBlendMode(GetDestBlendMode());; + blendStateDescription.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + blendStateDescription.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA; + blendStateDescription.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_DEST_ALPHA; + blendStateDescription.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + blendStateDescription.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; + + // Create the blend state using the description. + HRESULT result = device->GetDevice()->CreateBlendState1(&blendStateDescription, &m_blendingState); + if (FAILED(result)) + { + return nullptr; + } + + m_blendingDirty = false; + } + + return m_blendingState; } -void CDXMaterial::SetWireframeColor(DirectX::XMFLOAT3 color) + +void CDXMaterial::SetWireframeColor(DirectX::XMFLOAT4 color) { #ifdef CDX_MUTEX std::lock_guard guard(m_mutex); @@ -69,33 +100,28 @@ void CDXMaterial::SetWireframeColor(DirectX::XMFLOAT3 color) m_wireframeColor = color; } -DirectX::XMFLOAT3 & CDXMaterial::GetDiffuseColor() -{ -#ifdef CDX_MUTEX - std::lock_guard guard(m_mutex); -#endif - return m_diffuseColor; -} -DirectX::XMFLOAT3 & CDXMaterial::GetSpecularColor() +void CDXMaterial::SetTintColor(DirectX::XMFLOAT4 color) { #ifdef CDX_MUTEX std::lock_guard guard(m_mutex); #endif - return m_specularColor; + m_tintColor = color; } -DirectX::XMFLOAT3 & CDXMaterial::GetAmbientColor() + +DirectX::XMFLOAT4 & CDXMaterial::GetWireframeColor() { #ifdef CDX_MUTEX std::lock_guard guard(m_mutex); #endif - return m_ambientColor; + return m_wireframeColor; } -DirectX::XMFLOAT3 & CDXMaterial::GetWireframeColor() + +DirectX::XMFLOAT4 & CDXMaterial::GetTintColor() { #ifdef CDX_MUTEX std::lock_guard guard(m_mutex); #endif - return m_wireframeColor; + return m_tintColor; } void CDXMaterial::SetShaderFlags1(UInt32 flags) @@ -124,6 +150,7 @@ void CDXMaterial::SetFlags(UInt16 flags) void CDXMaterial::SetAlphaBlending(bool bAlpha) { SetBit(bAlpha, ALPHA_BLEND_MASK); + m_blendingDirty = true; } bool CDXMaterial::GetAlphaBlending() const @@ -134,6 +161,7 @@ bool CDXMaterial::GetAlphaBlending() const void CDXMaterial::SetSrcBlendMode(AlphaFunction eSrcBlend) { SetField((UInt16)(eSrcBlend), SRC_BLEND_MASK, SRC_BLEND_POS); + m_blendingDirty = true; } CDXMaterial::AlphaFunction CDXMaterial::GetSrcBlendMode() const @@ -144,6 +172,7 @@ CDXMaterial::AlphaFunction CDXMaterial::GetSrcBlendMode() const void CDXMaterial::SetDestBlendMode(AlphaFunction eDestBlend) { SetField((UInt16)(eDestBlend), DEST_BLEND_MASK, DEST_BLEND_POS); + m_blendingDirty = true; } CDXMaterial::AlphaFunction CDXMaterial::GetDestBlendMode() const @@ -171,4 +200,25 @@ CDXMaterial::TestFunction CDXMaterial::GetTestMode() const return (CDXMaterial::TestFunction) GetField(TEST_FUNC_MASK, TEST_FUNC_POS); } -#endif \ No newline at end of file +D3D11_BLEND CDXMaterial::GetD3DBlendMode(AlphaFunction alphaFunc) +{ + static std::unordered_map testMode = { + { ALPHA_ONE, D3D11_BLEND_ONE }, + { ALPHA_ZERO, D3D11_BLEND_ZERO }, + { ALPHA_SRCCOLOR, D3D11_BLEND_SRC_COLOR }, + { ALPHA_INVSRCCOLOR, D3D11_BLEND_INV_SRC_COLOR }, + { ALPHA_DESTCOLOR, D3D11_BLEND_DEST_COLOR }, + { ALPHA_INVDESTCOLOR, D3D11_BLEND_INV_DEST_COLOR }, + { ALPHA_SRCALPHA, D3D11_BLEND_SRC_ALPHA }, + { ALPHA_INVSRCALPHA, D3D11_BLEND_INV_SRC_ALPHA }, + { ALPHA_DESTALPHA, D3D11_BLEND_DEST_ALPHA }, + { ALPHA_INVDESTALPHA, D3D11_BLEND_INV_DEST_ALPHA }, + { ALPHA_SRCALPHASAT, D3D11_BLEND_SRC_ALPHA_SAT } + }; + auto it = testMode.find(alphaFunc); + if (it != testMode.end()) + { + return it->second; + } + return D3D11_BLEND_ZERO; +} \ No newline at end of file diff --git a/skee/CDXMaterial.h b/skee/CDXMaterial.h index 215920f..73c5602 100644 --- a/skee/CDXMaterial.h +++ b/skee/CDXMaterial.h @@ -1,11 +1,13 @@ -#ifdef FIXME - #ifndef __CDXMATERIAL__ #define __CDXMATERIAL__ #pragma once +#include "CDXTypes.h" + #include +#include +#include #define DeclareFlags(type) \ private: \ @@ -35,30 +37,33 @@ } static UInt32 mappedAlphaFunctions[] = { - D3DBLEND_ONE, - D3DBLEND_ZERO, - D3DBLEND_SRCCOLOR, - D3DBLEND_INVSRCCOLOR, - D3DBLEND_DESTCOLOR, - D3DBLEND_INVDESTCOLOR, - D3DBLEND_SRCALPHA, - D3DBLEND_INVSRCALPHA, - D3DBLEND_DESTALPHA, - D3DBLEND_INVDESTALPHA, - D3DBLEND_SRCALPHASAT + D3D11_BLEND_ONE, + D3D11_BLEND_ZERO, + D3D11_BLEND_SRC_COLOR, + D3D11_BLEND_INV_SRC_COLOR, + D3D11_BLEND_DEST_COLOR, + D3D11_BLEND_INV_DEST_COLOR, + D3D11_BLEND_SRC_ALPHA, + D3D11_BLEND_INV_SRC_ALPHA, + D3D11_BLEND_DEST_ALPHA, + D3D11_BLEND_INV_DEST_ALPHA, + D3D11_BLEND_SRC_ALPHA_SAT }; static UInt32 mappedTestFunctions[] = { - D3DCMP_ALWAYS, - D3DCMP_LESS, - D3DCMP_EQUAL, - D3DCMP_LESSEQUAL, - D3DCMP_GREATER, - D3DCMP_NOTEQUAL, - D3DCMP_GREATEREQUAL, - D3DCMP_NEVER, + D3D11_COMPARISON_ALWAYS, + D3D11_COMPARISON_LESS, + D3D11_COMPARISON_EQUAL, + D3D11_COMPARISON_LESS_EQUAL, + D3D11_COMPARISON_GREATER, + D3D11_COMPARISON_NOT_EQUAL, + D3D11_COMPARISON_GREATER_EQUAL, + D3D11_COMPARISON_NEVER, }; +class CDXD3DDevice; +class CDXShader; + class CDXMaterial { public: @@ -67,18 +72,16 @@ class CDXMaterial void Release(); - void SetDiffuseTexture(LPDIRECT3DBASETEXTURE9 texture); - LPDIRECT3DBASETEXTURE9 GetDiffuseTexture() const { return m_diffuseTexture; } + void SetTexture(int index, ID3D11ShaderResourceView* texture); + ID3D11ShaderResourceView** GetTextures() { return m_pTextures; } + + ID3D11BlendState1* GetBlendingState(CDXD3DDevice * device); - void SetDiffuseColor(DirectX::XMFLOAT3 color); - void SetSpecularColor(DirectX::XMFLOAT3 color); - void SetAmbientColor(DirectX::XMFLOAT3 color); - void SetWireframeColor(DirectX::XMFLOAT3 color); + void SetWireframeColor(DirectX::XMFLOAT4 color); + DirectX::XMFLOAT4 & GetWireframeColor(); - DirectX::XMFLOAT3 & GetDiffuseColor(); - DirectX::XMFLOAT3 & GetSpecularColor(); - DirectX::XMFLOAT3 & GetAmbientColor(); - DirectX::XMFLOAT3 & GetWireframeColor(); + void SetTintColor(DirectX::XMFLOAT4 color); + DirectX::XMFLOAT4 & GetTintColor(); UInt32 GetShaderFlags1() const { return m_shaderFlags1; } UInt32 GetShaderFlags2() const { return m_shaderFlags2; } @@ -104,6 +107,8 @@ class CDXMaterial ALPHA_MAX_MODES }; + D3D11_BLEND GetD3DBlendMode(AlphaFunction alphaFunc); + enum { ALPHA_BLEND_MASK = 0x0001, @@ -151,23 +156,28 @@ class CDXMaterial bool IsWireframe() const { return m_wireframe; } void SetWireframe(bool w) { m_wireframe = w; } + bool HasDiffuse() const { return m_pTextures[0] != nullptr; } + bool HasNormal() const { return m_pTextures[1] != nullptr; } + bool HasSpecular() const { return m_pTextures[2] != nullptr; } + bool HasDetail() const { return m_pTextures[3] != nullptr; } + bool HasTintMask() const { return m_pTextures[4] != nullptr; } + protected: - LPDIRECT3DBASETEXTURE9 m_diffuseTexture; + ID3D11ShaderResourceView * m_pTextures[5]; + ID3D11BlendState1* m_blendingState; + bool m_blendingDirty; - DirectX::XMFLOAT3 m_specularColor; - DirectX::XMFLOAT3 m_diffuseColor; - DirectX::XMFLOAT3 m_ambientColor; - DirectX::XMFLOAT3 m_wireframeColor; + DirectX::XMFLOAT4 m_wireframeColor; + DirectX::XMFLOAT4 m_tintColor; DeclareFlags(UInt16); UInt32 m_shaderFlags1; UInt32 m_shaderFlags2; UInt8 m_alphaThreshold; bool m_wireframe; + #ifdef CDX_MUTEX std::mutex m_mutex; #endif }; #endif - -#endif \ No newline at end of file diff --git a/skee/CDXMesh.cpp b/skee/CDXMesh.cpp index 3df3c18..777071f 100644 --- a/skee/CDXMesh.cpp +++ b/skee/CDXMesh.cpp @@ -1,22 +1,22 @@ +#include "CDXD3DDevice.h" #include "CDXMesh.h" #include "CDXShader.h" #include "CDXCamera.h" #include "CDXMaterial.h" #include "CDXPicker.h" -#ifdef FIXME +using namespace DirectX; CDXMesh::CDXMesh() { - m_vertexBuffer = NULL; + m_vertexBuffer = nullptr; m_vertCount = 0; - m_indexBuffer = NULL; - m_primitiveCount = 0; + m_indexBuffer = nullptr; + m_indexCount = 0; m_visible = true; - //m_material = NULL; - //m_primitiveType = D3DPT_TRIANGLELIST; - - m_transform = DirectX::XMMatrixIdentity(); + m_material = nullptr; + m_transform = XMMatrixIdentity(); + m_topology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; } CDXMesh::~CDXMesh() @@ -27,21 +27,28 @@ CDXMesh::~CDXMesh() void CDXMesh::Release() { m_vertCount = 0; - m_primitiveCount = 0; + m_indexCount = 0; m_visible = false; if(m_vertexBuffer) { m_vertexBuffer->Release(); - m_vertexBuffer = NULL; + m_vertexBuffer = nullptr; } if(m_indexBuffer) { m_indexBuffer->Release(); - m_indexBuffer = NULL; + m_indexBuffer = nullptr; } - /*if(m_material) { + if(m_material) { m_material->Release(); delete m_material; - m_material = NULL; - }*/ + m_material = nullptr; + } + + // Release the arrays now that the vertex and index buffers have been created and loaded. + delete[] m_vertices; + m_vertices = 0; + + delete[] m_indices; + m_indices = 0; } void CDXMesh::SetMaterial(CDXMaterial * material) @@ -49,7 +56,7 @@ void CDXMesh::SetMaterial(CDXMaterial * material) #ifdef CDX_MUTEX std::lock_guard guard(m_mutex); #endif - //m_material = material; + m_material = material; } CDXMaterial * CDXMesh::GetMaterial() @@ -57,7 +64,7 @@ CDXMaterial * CDXMesh::GetMaterial() #ifdef CDX_MUTEX std::lock_guard guard(m_mutex); #endif - return nullptr;//m_material; + return m_material; } void CDXMesh::SetVisible(bool visible) @@ -90,27 +97,33 @@ ID3D11Buffer * CDXMesh::GetIndexBuffer() return m_indexBuffer; } -UInt32 CDXMesh::GetPrimitiveCount() +UInt32 CDXMesh::GetIndexCount() { - return m_primitiveCount; + return m_indexCount; } + +UInt32 CDXMesh::GetFaceCount() +{ + return m_indexCount / 3; +} + UInt32 CDXMesh::GetVertexCount() { return m_vertCount; } -DirectX::XMVECTOR CalculateFaceNormal(UInt32 f, CDXMeshIndex * faces, CDXMeshVert * vertices) +XMVECTOR CalculateFaceNormal(UInt32 f, CDXMeshIndex * faces, CDXMeshVert * vertices) { - DirectX::XMVECTOR vNormal; + XMVECTOR vNormal; CDXMeshVert * v1 = &vertices[faces[f]]; CDXMeshVert * v2 = &vertices[faces[f + 1]]; CDXMeshVert * v3 = &vertices[faces[f + 2]]; - auto e1 = DirectX::XMVectorSubtract(DirectX::XMLoadFloat3(&v2->Position), DirectX::XMLoadFloat3(&v1->Position)); - auto e2 = DirectX::XMVectorSubtract(DirectX::XMLoadFloat3(&v3->Position), DirectX::XMLoadFloat3(&v2->Position)); + auto e1 = XMVectorSubtract(XMLoadFloat3(&v2->Position), XMLoadFloat3(&v1->Position)); + auto e2 = XMVectorSubtract(XMLoadFloat3(&v3->Position), XMLoadFloat3(&v2->Position)); - vNormal = DirectX::XMVector3Cross(e1, e2); - vNormal = DirectX::XMVector3Normalize(vNormal); + vNormal = XMVector3Cross(e1, e2); + vNormal = XMVector3Normalize(vNormal); return vNormal; } @@ -118,10 +131,10 @@ bool IntersectSphere(float radius, float & dist, CDXVec & center, CDXVec & rayOr { //FLOAT t0 = -1, t1 = -1; // solutions for t if the ray intersects - CDXVec L = DirectX::XMVectorSubtract(center, rayOrigin); - float tca = DirectX::XMVector3Dot(L, rayDir).m128_f32[0]; + CDXVec L = XMVectorSubtract(center, rayOrigin); + float tca = XMVectorGetX(XMVector3Dot(L, rayDir)); if (tca < 0) return false; - float d2 = DirectX::XMVector3Dot(L, L).m128_f32[0] - tca * tca; + float d2 = XMVector3Dot(L, L).m128_f32[0] - tca * tca; if (d2 > radius) return false; float thc = sqrt(radius - d2); //t0 = tca - thc; @@ -133,20 +146,20 @@ bool IntersectSphere(float radius, float & dist, CDXVec & center, CDXVec & rayOr bool IntersectTriangle( const CDXVec& orig, const CDXVec& dir, CDXVec& v0, CDXVec& v1, CDXVec& v2, float* t, float* u, float* v ) { // Find vectors for two edges sharing vert0 - CDXVec edge1 = DirectX::XMVectorSubtract(v1, v0); - CDXVec edge2 = DirectX::XMVectorSubtract(v2, v0); + CDXVec edge1 = XMVectorSubtract(v1, v0); + CDXVec edge2 = XMVectorSubtract(v2, v0); // Begin calculating determinant - also used to calculate U parameter - CDXVec pvec = DirectX::XMVector3Cross(dir, edge2); + CDXVec pvec = XMVector3Cross(dir, edge2); // If determinant is near zero, ray lies in plane of triangle - float det = DirectX::XMVector3Dot(edge1, pvec).m128_f32[0]; + float det = XMVectorGetX(XMVector3Dot(edge1, pvec)); CDXVec tvec; if(det > 0) { - tvec = DirectX::XMVectorSubtract(orig, v0); + tvec = XMVectorSubtract(orig, v0); } else { - tvec = DirectX::XMVectorSubtract(v0, orig); + tvec = XMVectorSubtract(v0, orig); det = -det; } @@ -154,20 +167,20 @@ bool IntersectTriangle( const CDXVec& orig, const CDXVec& dir, CDXVec& v0, CDXVe return false; // Calculate U parameter and test bounds - *u = DirectX::XMVector3Dot(tvec, pvec).m128_f32[0]; + *u = XMVectorGetX(XMVector3Dot(tvec, pvec)); if(*u < 0.0f || *u > det) return false; // Prepare to test V parameter - CDXVec qvec = DirectX::XMVector3Cross(tvec, edge1); + CDXVec qvec = XMVector3Cross(tvec, edge1); // Calculate V parameter and test bounds - *v = DirectX::XMVector3Dot(dir, qvec).m128_f32[0]; + *v = XMVectorGetX(XMVector3Dot(dir, qvec)); if(*v < 0.0f || *u + *v > det) return false; // Calculate t, scale parameters, ray intersects triangle - *t = DirectX::XMVector3Dot(edge2, qvec).m128_f32[0]; + *t = XMVectorGetX(XMVector3Dot(edge2, qvec)); float fInvDet = 1.0f / det; *t *= fInvDet; *u *= fInvDet; @@ -176,39 +189,74 @@ bool IntersectTriangle( const CDXVec& orig, const CDXVec& dir, CDXVec& v0, CDXVe return true; } +CDXMeshVert * CDXMesh::LockVertices(const LockMode type) +{ + if (type == LockMode::WRITE) + { + D3D11_MAPPED_SUBRESOURCE vertResource; + CDXMeshVert* pVertices = nullptr; + HRESULT res = m_pDevice->GetDeviceContext()->Map(m_vertexBuffer, 0, (D3D11_MAP)type, 0, &vertResource); + if (res == S_OK) + { + return static_cast(vertResource.pData); + } + } + + return m_vertices; +} + +CDXMeshIndex * CDXMesh::LockIndices() +{ + return m_indices; +} + +void CDXMesh::UnlockVertices(const LockMode type) +{ + if (type == LockMode::WRITE) + { + m_pDevice->GetDeviceContext()->Unmap(m_vertexBuffer, 0); + } +} + +void CDXMesh::UnlockIndices(bool write) +{ + if(write) + m_pDevice->GetDeviceContext()->UpdateSubresource(m_indexBuffer, 0, nullptr, m_indices, 0, 0); +} + bool CDXMesh::Pick(CDXRayInfo & rayInfo, CDXPickInfo & pickInfo) { #ifdef CDX_MUTEX std::lock_guard guard(m_mutex); #endif - CDXMeshVert* pVertices = LockVertices(); + CDXMeshVert* pVertices = LockVertices(LockMode::READ); CDXMeshIndex* pIndices = LockIndices(); if (!pVertices || !pIndices) return false; float hitDist = FLT_MAX; - CDXVec hitNormal = DirectX::XMVectorZero(); + CDXVec hitNormal = XMVectorZero(); // Edges = Face * 3 - for(UInt32 e = 0; e < m_primitiveCount * 3; e += 3) + for(UInt32 e = 0; e < m_indexCount; e += 3) { - CDXVec v0 = DirectX::XMLoadFloat3(&pVertices[pIndices[e + 0]].Position); - CDXVec v1 = DirectX::XMLoadFloat3(&pVertices[pIndices[e + 1]].Position); - CDXVec v2 = DirectX::XMLoadFloat3(&pVertices[pIndices[e + 2]].Position); + CDXVec v0 = XMLoadFloat3(&pVertices[pIndices[e + 0]].Position); + CDXVec v1 = XMLoadFloat3(&pVertices[pIndices[e + 1]].Position); + CDXVec v2 = XMLoadFloat3(&pVertices[pIndices[e + 2]].Position); // Calculate the norm of the face - CDXVec fNormal = DirectX::XMVectorZero(); - CDXVec f1 = DirectX::XMVectorSubtract(v1, v0); - CDXVec f2 = DirectX::XMVectorSubtract(v2, v1); - fNormal = DirectX::XMVector3Cross(f1, f2); - fNormal = DirectX::XMVector3Normalize(fNormal); + CDXVec fNormal = XMVectorZero(); + CDXVec f1 = XMVectorSubtract(v1, v0); + CDXVec f2 = XMVectorSubtract(v2, v1); + fNormal = XMVector3Cross(f1, f2); + fNormal = XMVector3Normalize(fNormal); // Normalize the direction, just in case - CDXVec vDir = DirectX::XMVector3Normalize(rayInfo.direction); + CDXVec vDir = XMVector3Normalize(rayInfo.direction); // Skip faces that are in the same direction as the ray - if(DirectX::XMVector3Dot(vDir, fNormal).m128_f32[0] >= 0) + if(XMVectorGetX(XMVector3Dot(vDir, fNormal)) >= 0) continue; // Skip face that doesn't intersect with the ray @@ -224,100 +272,126 @@ bool CDXMesh::Pick(CDXRayInfo & rayInfo, CDXPickInfo & pickInfo) } } + UnlockVertices(LockMode::READ); + UnlockIndices(); + pickInfo.ray = rayInfo; pickInfo.dist = hitDist; if (hitDist != FLT_MAX) { - CDXVec hitVec = DirectX::XMVectorReplicate(hitDist); - CDXVec vHit = DirectX::XMVectorMultiplyAdd(rayInfo.direction, hitVec, rayInfo.origin); - pickInfo.origin = vHit; + CDXVec hitVec = XMVectorReplicate(hitDist); + CDXVec vHit = XMVectorMultiplyAdd(rayInfo.direction, hitVec, rayInfo.origin); + pickInfo.origin = XMVectorSetW(vHit, 0.0f); pickInfo.normal = hitNormal; pickInfo.isHit = true; } else { - pickInfo.origin = DirectX::XMVectorZero(); - pickInfo.normal = DirectX::XMVectorZero(); + pickInfo.origin = XMVectorZero(); + pickInfo.normal = XMVectorZero(); pickInfo.isHit = false; } - UnlockVertices(); - UnlockIndices(); return pickInfo.isHit; } -CDXMeshVert* CDXMesh::LockVertices() +bool CDXMesh::InitializeBuffers(CDXD3DDevice * device, UInt32 vertexCount, UInt32 indexCount, std::function fillFunction) { - CDXMeshVert* pVertices = NULL; - if (!m_vertexBuffer) - return NULL; + D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc; + D3D11_SUBRESOURCE_DATA vertexData, indexData; + HRESULT result; - /*if (FAILED(m_vertexBuffer->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD))) - return NULL;*/ + m_pDevice = device; + m_vertCount = vertexCount; + m_indexCount = indexCount; - return pVertices; -} + auto pDevice = device->GetDevice(); + auto pDeviceContext = device->GetDeviceContext(); -CDXMeshIndex* CDXMesh::LockIndices() -{ - CDXMeshIndex* pIndices = NULL; - if (!m_indexBuffer) - return NULL; + // Create the vertex array. + m_vertices = new CDXMeshVert[m_vertCount]; + if (!m_vertices) + { + return false; + } - /*if (FAILED(m_indexBuffer->Lock(0, 0, (void**)&pIndices, D3DLOCK_DISCARD))) - return NULL;*/ + // Create the index array. + m_indices = new CDXMeshIndex[m_indexCount]; + if (!m_indices) + { + return false; + } - return pIndices; -} + // Load the vertex array and index array with data. + fillFunction(m_vertices, m_indices); + + // Set up the description of the static vertex buffer. + vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + vertexBufferDesc.ByteWidth = sizeof(CDXMeshVert) * m_vertCount; + vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + vertexBufferDesc.MiscFlags = 0; + vertexBufferDesc.StructureByteStride = 0; + + // Give the subresource structure a pointer to the vertex data. + vertexData.pSysMem = m_vertices; + vertexData.SysMemPitch = 0; + vertexData.SysMemSlicePitch = 0; + + // Now create the vertex buffer. + result = pDevice->CreateBuffer(&vertexBufferDesc, &vertexData, &m_vertexBuffer); + if (FAILED(result)) + { + return false; + } -void CDXMesh::UnlockVertices() -{ - //m_vertexBuffer->Unlock(); -} -void CDXMesh::UnlockIndices() -{ - //m_indexBuffer->Unlock(); + // Set up the description of the static index buffer. + indexBufferDesc.Usage = D3D11_USAGE_DEFAULT; + indexBufferDesc.ByteWidth = sizeof(CDXMeshIndex) * m_indexCount; + indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + indexBufferDesc.CPUAccessFlags = 0; + indexBufferDesc.MiscFlags = 0; + indexBufferDesc.StructureByteStride = 0; + + // Give the subresource structure a pointer to the index data. + indexData.pSysMem = m_indices; + indexData.SysMemPitch = 0; + indexData.SysMemSlicePitch = 0; + + // Create the index buffer. + result = pDevice->CreateBuffer(&indexBufferDesc, &indexData, &m_indexBuffer); + if (FAILED(result)) + { + return false; + } + + return true; } -void CDXMesh::Render(ID3D11Device * pDevice, CDXShader * shader) +void CDXMesh::Render(CDXD3DDevice * device, CDXShader * shader) { #ifdef CDX_MUTEX std::lock_guard guard(m_mutex); #endif - /*ID3DXEffect * effect = shader->GetEffect(); - effect->SetMatrix(shader->m_hTransform, &m_transform); - - if (m_material && m_material->IsWireframe()) { - effect->SetTechnique(effect->GetTechniqueByName("Wireframe")); - effect->SetTexture(shader->m_hTexture, NULL); - } else if (m_material && m_material->GetDiffuseTexture()) { - effect->SetTechnique(effect->GetTechniqueByName("TexturedSpecular")); - effect->SetTexture(shader->m_hTexture, m_material->GetDiffuseTexture()); - } else { - effect->SetTechnique(effect->GetTechniqueByName("Specular")); - effect->SetTexture(shader->m_hTexture, NULL); - } + unsigned int stride; + unsigned int offset; - effect->CommitChanges(); + // Set vertex buffer stride and offset. + stride = sizeof(CDXMeshVert); + offset = 0; - UINT iPass, cPasses; - effect->Begin(&cPasses, 0); - for (iPass = 0; iPass < cPasses; iPass++) - { - effect->BeginPass(iPass); - Pass(pDevice, iPass, shader); - effect->EndPass(); - } + auto pDeviceContext = device->GetDeviceContext(); - effect->End();*/ -} + // Set the vertex buffer to active in the input assembler so it can be rendered. + pDeviceContext->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &offset); -void CDXMesh::Pass(ID3D11Device * pDevice, UInt32 iPass, CDXShader * shader) -{ - if (!m_vertexBuffer || !m_indexBuffer) - return; + // Set the index buffer to active in the input assembler so it can be rendered. + pDeviceContext->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R16_UINT, 0); + + // Set the type of primitive that should be rendered from this vertex buffer, in this case triangles. + pDeviceContext->IASetPrimitiveTopology(m_topology); + + shader->RenderShader(device, m_material); - //pDevice->SetStreamSource(0, m_vertexBuffer, 0, sizeof(CDXMeshVert)); - //pDevice->SetIndices(m_indexBuffer); - //pDevice->DrawIndexedPrimitive((D3DPRIMITIVETYPE)m_primitiveType, 0, 0, m_vertCount, 0, m_primitiveCount); + // Render the triangle. + pDeviceContext->DrawIndexed(m_indexCount, 0, 0); } -#endif \ No newline at end of file diff --git a/skee/CDXMesh.h b/skee/CDXMesh.h index bdd3c5c..7a7e90e 100644 --- a/skee/CDXMesh.h +++ b/skee/CDXMesh.h @@ -4,17 +4,11 @@ #include #endif -#include "CDXTypes.h" +#include -/*const static D3DVERTEXELEMENT9 VertexDecl[6] = -{ - { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, - { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, - { 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, - { 0, 32, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 }, - D3DDECL_END() -};*/ +#include "CDXTypes.h" +class CDXD3DDevice; class CDXMaterial; class CDXPicker; class CDXShader; @@ -26,14 +20,18 @@ class CDXMesh { public: CDXMesh(); - ~CDXMesh(); + virtual ~CDXMesh(); + + bool InitializeBuffers(CDXD3DDevice * pDevice, UInt32 vertexCount, UInt32 indexCount, std::function fillFunction); - virtual void Render(ID3D11Device * pDevice, CDXShader * shader); - virtual void Pass(ID3D11Device * pDevice, UInt32 iPass, CDXShader * shader); + virtual const char* GetName() const { return ""; } + virtual void Render(CDXD3DDevice * pDevice, CDXShader * shader); virtual void Release(); virtual bool Pick(CDXRayInfo & rayInfo, CDXPickInfo & pickInfo); - virtual bool IsEditable() { return false; } - virtual bool IsLocked() { return true; } + virtual bool IsEditable() const { return false; } + virtual bool IsLocked() const { return true; } + virtual bool IsMorphable() const { return false; } + virtual bool ShowWireframe() const { return false; } void SetVisible(bool visible); bool IsVisible(); @@ -41,27 +39,52 @@ class CDXMesh void SetMaterial(CDXMaterial * material); CDXMaterial * GetMaterial(); - CDXMeshVert* LockVertices(); - CDXMeshIndex* LockIndices(); + enum LockMode + { + READ = D3D11_MAP_READ, + WRITE = D3D11_MAP_WRITE_NO_OVERWRITE + }; - void UnlockVertices(); - void UnlockIndices(); + void SetTopology(D3D_PRIMITIVE_TOPOLOGY topo) { m_topology = topo; } + + virtual CDXMeshVert * LockVertices(const LockMode type = READ); + virtual CDXMeshIndex * LockIndices(); + + virtual void UnlockVertices(const LockMode type); + virtual void UnlockIndices(bool write = false); ID3D11Buffer * GetVertexBuffer(); ID3D11Buffer * GetIndexBuffer(); - UInt32 GetPrimitiveCount(); + const CDXMatrix & GetTransform() { return m_transform; }; + void SetTransform(const CDXMatrix & mat) { m_transform = mat; } + + UInt32 GetIndexCount(); + UInt32 GetFaceCount(); UInt32 GetVertexCount(); protected: bool m_visible; ID3D11Buffer * m_vertexBuffer; UInt32 m_vertCount; + + struct ColoredPrimitive + { + CDXVec Position; + CDXVec Color; + }; + union + { + CDXMeshVert * m_vertices; + ColoredPrimitive * m_primitive; + }; ID3D11Buffer * m_indexBuffer; - UInt32 m_primitiveCount; - //UInt8 m_primitiveType; - //CDXMaterial * m_material; + UInt32 m_indexCount; + CDXMeshIndex * m_indices; + D3D_PRIMITIVE_TOPOLOGY m_topology; + CDXMaterial * m_material; CDXMatrix m_transform; + CDXD3DDevice * m_pDevice; #ifdef CDX_MUTEX std::mutex m_mutex; diff --git a/skee/CDXNifBrush.cpp b/skee/CDXNifBrush.cpp index 1218ae7..63672fe 100644 --- a/skee/CDXNifBrush.cpp +++ b/skee/CDXNifBrush.cpp @@ -1,8 +1,6 @@ #include "CDXNifBrush.h" #include "CDXNifCommands.h" -#ifdef FIXME - CDXStrokePtr CDXNifMaskAddBrush::CreateStroke(CDXBrush * brush, CDXEditableMesh * mesh) { return std::make_shared(brush, mesh); @@ -32,5 +30,3 @@ CDXStrokePtr CDXNifMoveBrush::CreateStroke(CDXBrush * brush, CDXEditableMesh * m { return std::make_shared(brush, mesh); } - -#endif \ No newline at end of file diff --git a/skee/CDXNifBrush.h b/skee/CDXNifBrush.h index 4061448..615a882 100644 --- a/skee/CDXNifBrush.h +++ b/skee/CDXNifBrush.h @@ -1,5 +1,3 @@ -#ifdef FIXME - #ifndef __CDXNIFBRUSH__ #define __CDXNIFBRUSH__ @@ -50,5 +48,3 @@ class CDXNifMoveBrush : public CDXMoveBrush }; #endif - -#endif \ No newline at end of file diff --git a/skee/CDXNifCommands.cpp b/skee/CDXNifCommands.cpp index 9fddad9..9b572c1 100644 --- a/skee/CDXNifCommands.cpp +++ b/skee/CDXNifCommands.cpp @@ -1,5 +1,3 @@ -#ifdef FIXME - #include "CDXNifCommands.h" #include "CDXNifMesh.h" #include "CDXNifScene.h" @@ -12,25 +10,28 @@ #include "skse64/NiGeometry.h" #include "skse64/NiExtraData.h" -#include "MorphHandler.h" +#include "FaceMorphInterface.h" #include "FileUtils.h" #include "NifUtils.h" +#include "SKEEHooks.h" #include "skse64/ScaleformCallbacks.h" #include "skse64/PluginAPI.h" -extern MorphHandler g_morphHandler; +extern FaceMorphInterface g_morphInterface; extern SKSETaskInterface * g_task; extern CDXNifScene g_World; -void ApplyMorphData(NiGeometry * geometry, CDXVectorMap & vectorMap, float multiplier) +using namespace DirectX; + +void ApplyMorphData(BSTriShape * geometry, CDXVectorMap & vectorMap, float multiplier) { Actor * actor = g_World.GetWorkingActor(); TESNPC * npc = DYNAMIC_CAST(actor->baseForm, TESForm, TESNPC); // Create mapped extra vertex data for NPC - auto sculptTarget = g_morphHandler.GetSculptTarget(npc, true); + auto sculptTarget = g_morphInterface.GetSculptTarget(npc, true); if (sculptTarget) { std::string headPartName = geometry->m_name; BGSHeadPart * headPart = GetHeadPartByName(headPartName); @@ -59,7 +60,7 @@ void ApplyMorphData(NiGeometry * geometry, CDXVectorMap & vectorMap, float multi } } -void AddStrokeCommand(CDXStroke * stroke, NiGeometry * geometry, SInt32 id) +void AddStrokeCommand(CDXStroke * stroke, BSTriShape * geometry, SInt32 id) { if (g_task) g_task->AddUITask(new CRGNUITaskAddStroke(stroke, geometry, id)); @@ -69,7 +70,7 @@ void CDXNifInflateStroke::Undo() { CDXInflateStroke::Undo(); CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { ApplyMorphData(geometry, m_current, -1.0); } @@ -78,8 +79,8 @@ void CDXNifInflateStroke::Undo() void CDXNifInflateStroke::Redo() { CDXInflateStroke::Redo(); - CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + CDXLegacyNifMesh * nifMesh = static_cast(m_mesh); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { ApplyMorphData(geometry, m_current, 1.0); } @@ -89,7 +90,7 @@ void CDXNifDeflateStroke::Undo() { CDXDeflateStroke::Undo(); CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { ApplyMorphData(geometry, m_current, -1.0); } @@ -99,7 +100,7 @@ void CDXNifDeflateStroke::Redo() { CDXDeflateStroke::Redo(); CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { ApplyMorphData(geometry, m_current, 1.0); } @@ -109,7 +110,7 @@ void CDXNifSmoothStroke::Undo() { CDXSmoothStroke::Undo(); CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { ApplyMorphData(geometry, m_current, -1.0); } @@ -118,7 +119,7 @@ void CDXNifSmoothStroke::Redo() { CDXSmoothStroke::Redo(); CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { ApplyMorphData(geometry, m_current, 1.0); } @@ -128,7 +129,7 @@ void CDXNifMoveStroke::Undo() { CDXMoveStroke::Undo(); CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { ApplyMorphData(geometry, m_current, -1.0); } @@ -138,7 +139,7 @@ void CDXNifMoveStroke::Redo() { CDXMoveStroke::Redo(); CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { ApplyMorphData(geometry, m_current, 1.0); } @@ -147,7 +148,7 @@ void CDXNifMoveStroke::Redo() void CDXNifInflateStroke::Apply(SInt32 i) { CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { ApplyMorphData(geometry, m_current, 1.0); AddStrokeCommand(this, geometry, i); @@ -157,7 +158,7 @@ void CDXNifInflateStroke::Apply(SInt32 i) void CDXNifDeflateStroke::Apply(SInt32 i) { CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { ApplyMorphData(geometry, m_current, 1.0); AddStrokeCommand(this, geometry, i); @@ -167,7 +168,7 @@ void CDXNifDeflateStroke::Apply(SInt32 i) void CDXNifSmoothStroke::Apply(SInt32 i) { CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { ApplyMorphData(geometry, m_current, 1.0); AddStrokeCommand(this, geometry, i); @@ -177,7 +178,7 @@ void CDXNifSmoothStroke::Apply(SInt32 i) void CDXNifMoveStroke::Apply(SInt32 i) { CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { ApplyMorphData(geometry, m_current, 1.0); AddStrokeCommand(this, geometry, i); @@ -187,7 +188,7 @@ void CDXNifMoveStroke::Apply(SInt32 i) void CDXNifMaskAddStroke::Apply(SInt32 i) { CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { AddStrokeCommand(this, geometry, i); } @@ -196,7 +197,7 @@ void CDXNifMaskAddStroke::Apply(SInt32 i) void CDXNifMaskSubtractStroke::Apply(SInt32 i) { CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { AddStrokeCommand(this, geometry, i); } @@ -206,14 +207,14 @@ void CDXNifMaskSubtractStroke::Apply(SInt32 i) void CDXNifResetMask::Apply(SInt32 i) { CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { if (g_task) g_task->AddUITask(new CRGNUITaskStandardCommand(this, geometry, i)); } } -CRGNTaskUpdateModel::CRGNTaskUpdateModel(NiGeometry * geometry) +CRGNTaskUpdateModel::CRGNTaskUpdateModel(BSTriShape * geometry) { m_geometry = geometry; if (m_geometry) @@ -233,7 +234,7 @@ void CRGNTaskUpdateModel::Dispose() delete this; } -CRGNUITaskAddStroke::CRGNUITaskAddStroke(CDXStroke * stroke, NiGeometry * geometry, SInt32 id) +CRGNUITaskAddStroke::CRGNUITaskAddStroke(CDXStroke * stroke, BSTriShape * geometry, SInt32 id) { m_id = id; m_stroke = stroke; @@ -253,8 +254,9 @@ void CRGNUITaskAddStroke::Run() { IMenu * menu = MenuManager::GetSingleton()->GetMenu(&UIStringHolder::GetSingleton()->raceSexMenu); if (menu && menu->view) { - GFxValue obj; - menu->view->CreateObject(&obj); + FxResponseArgs<1> args; + menu->view->CreateObject(&args.args[1]); + GFxValue & obj = args.args[1]; GFxValue commandId; commandId.SetNumber(m_id); obj.SetMember("id", &commandId); @@ -273,14 +275,11 @@ void CRGNUITaskAddStroke::Run() GFxValue partName; partName.SetString(m_geometry->m_name); obj.SetMember("part", &partName); - - FxResponseArgsList args; - args.Add(&obj); InvokeFunction(menu->view, "AddAction", &args); } } -CRGNUITaskStandardCommand::CRGNUITaskStandardCommand(CDXUndoCommand * cmd, NiGeometry * geometry, SInt32 id) +CRGNUITaskStandardCommand::CRGNUITaskStandardCommand(CDXUndoCommand * cmd, BSTriShape * geometry, SInt32 id) { m_id = id; m_cmd = cmd; @@ -300,8 +299,9 @@ void CRGNUITaskStandardCommand::Run() { IMenu * menu = MenuManager::GetSingleton()->GetMenu(&UIStringHolder::GetSingleton()->raceSexMenu); if (menu && menu->view) { - GFxValue obj; - menu->view->CreateObject(&obj); + FxResponseArgs<1> args; + menu->view->CreateObject(&args.args[1]); + GFxValue & obj = args.args[1]; GFxValue commandId; commandId.SetNumber(m_id); obj.SetMember("id", &commandId); @@ -311,9 +311,6 @@ void CRGNUITaskStandardCommand::Run() GFxValue partName; partName.SetString(m_geometry->m_name); obj.SetMember("part", &partName); - - FxResponseArgsList args; - args.Add(&obj); InvokeFunction(menu->view, "AddAction", &args); } } @@ -324,29 +321,31 @@ CDXNifResetSculpt::CDXNifResetSculpt(CDXNifMesh * mesh) : CDXUndoCommand() Actor * actor = g_World.GetWorkingActor(); TESNPC * npc = DYNAMIC_CAST(actor->baseForm, TESForm, TESNPC); - NiGeometry * geometry = m_mesh->GetNifGeometry(); - + BSTriShape * geometry = m_mesh->GetGeometry(); if (geometry) { // Create mapped extra vertex data for NPC - auto sculptTarget = g_morphHandler.GetSculptTarget(npc, false); + auto sculptTarget = g_morphInterface.GetSculptTarget(npc, false); if (sculptTarget) { std::string headPartName = geometry->m_name; BGSHeadPart * headPart = GetHeadPartByName(headPartName); if (headPart) { auto sculptHost = sculptTarget->GetSculptHost(SculptData::GetHostByPart(headPart), false); if (sculptHost) { - CDXMeshVert* pVertices = m_mesh->LockVertices(); + CDXMeshVert* pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); for (auto it : *sculptHost) { // Skip masked vertices - if (pVertices[it.first].Color != COLOR_UNSELECTED) + CDXColor color; + XMStoreFloat3(&color, COLOR_SELECTED); + + if (XMVector3Equal(XMLoadFloat3(&pVertices[it.first].Color), XMLoadFloat3(&color))) continue; // Store it in the NPC mapped data - CDXVec3 temp = *(CDXVec3*)&it.second; - pVertices[it.first].Position -= temp; - m_current.emplace(it.first, -temp); + auto delta = XMLoadFloat3((XMFLOAT3*)&it.second); + XMStoreFloat3(&pVertices[it.first].Position, XMVectorSubtract(XMLoadFloat3(&pVertices[it.first].Position), delta)); + m_current.emplace(it.first, XMVectorNegate(delta)); } - m_mesh->UnlockVertices(); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); } } } @@ -365,18 +364,18 @@ CDXUndoCommand::UndoType CDXNifResetSculpt::GetUndoType() void CDXNifResetSculpt::Redo() { - CDXMeshVert* pVertices = m_mesh->LockVertices(); + CDXMeshVert* pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); if (!pVertices) return; // Do what we have now for (auto it : m_current) - pVertices[it.first].Position += it.second; + XMStoreFloat3(&pVertices[it.first].Position, XMVectorAdd(XMLoadFloat3(&pVertices[it.first].Position), it.second)); - m_mesh->UnlockVertices(); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { ApplyMorphData(geometry, m_current, 1.0); } @@ -384,18 +383,18 @@ void CDXNifResetSculpt::Redo() void CDXNifResetSculpt::Undo() { - CDXMeshVert* pVertices = m_mesh->LockVertices(); + CDXMeshVert* pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); if (!pVertices) return; // Undo what we did for (auto it : m_current) - pVertices[it.first].Position -= it.second; + XMStoreFloat3(&pVertices[it.first].Position, XMVectorSubtract(XMLoadFloat3(&pVertices[it.first].Position), it.second)); - m_mesh->UnlockVertices(); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { ApplyMorphData(geometry, m_current, -1.0); } @@ -404,7 +403,7 @@ void CDXNifResetSculpt::Undo() void CDXNifResetSculpt::Apply(SInt32 i) { CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { ApplyMorphData(geometry, m_current, 1.0); if (g_task) @@ -412,49 +411,91 @@ void CDXNifResetSculpt::Apply(SInt32 i) } } -CDXNifImportGeometry::CDXNifImportGeometry(CDXNifMesh * mesh, NiGeometry * source) : CDXUndoCommand() +CDXNifImportGeometry::CDXNifImportGeometry(CDXNifMesh * mesh, NiAVObject * source) : CDXUndoCommand() { m_mesh = mesh; Actor * actor = g_World.GetWorkingActor(); TESNPC * npc = DYNAMIC_CAST(actor->baseForm, TESForm, TESNPC); - NiGeometry * geometry = m_mesh->GetNifGeometry(); - - if (geometry) { + BSTriShape * target = m_mesh->GetGeometry(); + if (target) { // Create mapped extra vertex data for NPC - auto sculptTarget = g_morphHandler.GetSculptTarget(npc, true); + auto sculptTarget = g_morphInterface.GetSculptTarget(npc, true); if (sculptTarget) { - std::string headPartName = geometry->m_name; + std::string headPartName = target->m_name; BGSHeadPart * headPart = GetHeadPartByName(headPartName); if (headPart) { auto sculptHost = sculptTarget->GetSculptHost(SculptData::GetHostByPart(headPart), true); if (sculptHost) { - // Create differences from source and destination geometry - NiGeometryData * dstData = niptr_cast(geometry->m_spModelData); - NiGeometryData * srcData = niptr_cast(source->m_spModelData); + UInt32 srcNumVertices = 0; + UInt32 dstNumVertices = target->numVertices; - NiTransform dstTransform = GetGeometryTransform(geometry); - NiTransform srcTransform = GetGeometryTransform(source); + NiPoint3 * srcGeometry = nullptr; + NiPoint3 * dstGeometry = nullptr; - if (dstData && srcData && dstData->m_usVertices == srcData->m_usVertices) { + UInt32 srcStride = 0; + UInt32 dstStride = 0; - CDXMeshVert* pVertices = m_mesh->LockVertices(); + NiTransform srcTransform; + NiTransform dstTransform; - for (UInt32 i = 0; i < srcData->m_usVertices; i++) { + BSDynamicTriShape * dstDynamicShape = ni_cast(target, BSDynamicTriShape); + if (dstDynamicShape) { + dstGeometry = reinterpret_cast(dstDynamicShape->diffBlock); + dstStride = sizeof(XMFLOAT4); + dstTransform = GetGeometryTransform(dstDynamicShape); + } + + NiGeometry * legacyGeometry = source->GetAsNiGeometry(); + if (legacyGeometry) { + NiTriShapeData * srcData = niptr_cast(legacyGeometry->m_spModelData); + srcNumVertices = srcData->m_usVertices; + srcGeometry = reinterpret_cast(srcData->m_pkVertex); + srcStride = sizeof(NiPoint3); + srcTransform = GetLegacyGeometryTransform(legacyGeometry); + } + BSTriShape * sourceGeometry = source->GetAsBSTriShape(); + if (sourceGeometry) { + srcTransform = GetGeometryTransform(sourceGeometry); + srcNumVertices = sourceGeometry->numVertices; + + BSDynamicTriShape * srcDynamicShape = ni_cast(sourceGeometry, BSDynamicTriShape); + if (srcDynamicShape) { + srcGeometry = reinterpret_cast(srcDynamicShape->diffBlock); + srcStride = sizeof(XMFLOAT4); + } + else { + const NiSkinInstance * skinInstance = sourceGeometry->m_spSkinInstance.m_pObject; + const NiSkinPartition * skinPartition = skinInstance ? skinInstance->m_spSkinPartition.m_pObject : nullptr; + srcGeometry = skinPartition ? reinterpret_cast(&skinPartition->m_pkPartitions[0].shapeData->m_RawVertexData) : nullptr; + srcStride = NiSkinPartition::GetVertexSize(sourceGeometry->vertexDesc); + } + } + + if (srcNumVertices == dstNumVertices && srcGeometry && dstGeometry) { + CDXMeshVert* pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); + + for (UInt32 i = 0; i < srcNumVertices; i++) { - if (pVertices[i].Color != COLOR_UNSELECTED) + CDXColor color; + XMStoreFloat3(&color, COLOR_SELECTED); + + // Skip masked vertices + if (XMVector3Equal(XMLoadFloat3(&pVertices[i].Color), XMLoadFloat3(&color))) continue; - NiPoint3 diff = (srcTransform * srcData->m_pkVertex[i]) - (dstTransform * dstData->m_pkVertex[i]); - CDXVec3 temp = *(CDXVec3*)&diff; + NiPoint3 * srcVertex = reinterpret_cast(reinterpret_cast(srcGeometry) + (srcStride * i)); + NiPoint3 * dstVertex = reinterpret_cast(reinterpret_cast(dstGeometry) + (dstStride * i)); - pVertices[i].Position += temp; + NiPoint3 diff = (srcTransform * (*srcVertex)) - (dstTransform * (*dstVertex)); + XMVECTOR diffVector = XMLoadFloat3(reinterpret_cast(&diff)); - // Store it in the action - m_current.emplace(i, temp); + XMStoreFloat3(&pVertices[i].Position, XMVectorAdd(XMLoadFloat3(&pVertices[i].Position), diffVector)); + + m_current.emplace(i, diffVector); } - m_mesh->UnlockVertices(); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); } } } @@ -474,18 +515,18 @@ CDXUndoCommand::UndoType CDXNifImportGeometry::GetUndoType() void CDXNifImportGeometry::Redo() { - CDXMeshVert* pVertices = m_mesh->LockVertices(); + CDXMeshVert* pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); if (!pVertices) return; // Do what we have now for (auto it : m_current) - pVertices[it.first].Position += it.second; + XMStoreFloat3(&pVertices[it.first].Position, XMVectorAdd(XMLoadFloat3(&pVertices[it.first].Position), it.second)); - m_mesh->UnlockVertices(); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { ApplyMorphData(geometry, m_current, 1.0); } @@ -493,18 +534,18 @@ void CDXNifImportGeometry::Redo() void CDXNifImportGeometry::Undo() { - CDXMeshVert* pVertices = m_mesh->LockVertices(); + CDXMeshVert* pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); if (!pVertices) return; // Undo what we did for (auto it : m_current) - pVertices[it.first].Position -= it.second; + XMStoreFloat3(&pVertices[it.first].Position, XMVectorSubtract(XMLoadFloat3(&pVertices[it.first].Position), it.second)); - m_mesh->UnlockVertices(); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { ApplyMorphData(geometry, m_current, -1.0); } @@ -513,12 +554,10 @@ void CDXNifImportGeometry::Undo() void CDXNifImportGeometry::Apply(SInt32 i) { CDXNifMesh * nifMesh = static_cast(m_mesh); - NiGeometry * geometry = nifMesh->GetNifGeometry(); + BSTriShape * geometry = nifMesh->GetGeometry(); if (geometry) { ApplyMorphData(geometry, m_current, 1.0); if (g_task) g_task->AddUITask(new CRGNUITaskStandardCommand(this, geometry, i)); } } - -#endif \ No newline at end of file diff --git a/skee/CDXNifCommands.h b/skee/CDXNifCommands.h index 415606a..77f64c0 100644 --- a/skee/CDXNifCommands.h +++ b/skee/CDXNifCommands.h @@ -1,5 +1,3 @@ -#ifdef FIXME - #ifndef __CDXNIFCOMMANDS__ #define __CDXNIFCOMMANDS__ @@ -14,7 +12,7 @@ class CDXNifMesh; -class NiGeometry; +class BSTriShape; class UIDelegate; class CDXNifMaskAddStroke : public CDXMaskAddStroke @@ -103,7 +101,7 @@ class CDXNifResetSculpt : public CDXUndoCommand class CDXNifImportGeometry : public CDXUndoCommand { public: - CDXNifImportGeometry(CDXNifMesh * mesh, NiGeometry * source); + CDXNifImportGeometry(CDXNifMesh * mesh, NiAVObject * source); ~CDXNifImportGeometry(); virtual UndoType GetUndoType(); @@ -121,19 +119,19 @@ class CDXNifImportGeometry : public CDXUndoCommand class CRGNTaskUpdateModel : public TaskDelegate { public: - CRGNTaskUpdateModel(NiGeometry * geometry); + CRGNTaskUpdateModel(BSTriShape * geometry); virtual void Run(); virtual void Dispose(); private: - NiGeometry * m_geometry; + BSTriShape * m_geometry; }; class CRGNUITaskAddStroke : public UIDelegate_v1 { public: - CRGNUITaskAddStroke(CDXStroke * stroke, NiGeometry * geometry, SInt32 i); + CRGNUITaskAddStroke(CDXStroke * stroke, BSTriShape * geometry, SInt32 i); virtual void Run(); virtual void Dispose(); @@ -141,13 +139,13 @@ class CRGNUITaskAddStroke : public UIDelegate_v1 private: CDXStroke * m_stroke; SInt32 m_id; - NiGeometry * m_geometry; + BSTriShape * m_geometry; }; class CRGNUITaskStandardCommand : public UIDelegate_v1 { public: - CRGNUITaskStandardCommand(CDXUndoCommand * cmd, NiGeometry * geometry, SInt32 i); + CRGNUITaskStandardCommand(CDXUndoCommand * cmd, BSTriShape * geometry, SInt32 i); virtual void Run(); virtual void Dispose(); @@ -155,9 +153,7 @@ class CRGNUITaskStandardCommand : public UIDelegate_v1 private: CDXUndoCommand * m_cmd; SInt32 m_id; - NiGeometry * m_geometry; + BSTriShape * m_geometry; }; -#endif - #endif \ No newline at end of file diff --git a/skee/CDXNifMaterial.cpp b/skee/CDXNifMaterial.cpp new file mode 100644 index 0000000..9cabe27 --- /dev/null +++ b/skee/CDXNifMaterial.cpp @@ -0,0 +1,12 @@ +#include "CDXNifMaterial.h" +#include + +void CDXNifMaterial::SetNiTexture(int index, NiTexture* texture) +{ + m_pTextures[index] = texture; + + auto rendererData = m_pTextures[index]->rendererData; + if (rendererData) { + SetTexture(index, rendererData->resourceView); + } +} \ No newline at end of file diff --git a/skee/CDXNifMaterial.h b/skee/CDXNifMaterial.h new file mode 100644 index 0000000..d05a3d1 --- /dev/null +++ b/skee/CDXNifMaterial.h @@ -0,0 +1,16 @@ +#pragma once + +#include "CDXMaterial.h" + +#include "skse64/NiTypes.h" +#include "skse64/NiTextures.h" + +class CDXNifMaterial : public CDXMaterial +{ +public: + // Holds a reference to the NiTexture to keep it from being destroyed + void SetNiTexture(int index, NiTexture* texture); + +private: + NiPointer m_pTextures[5]; +}; \ No newline at end of file diff --git a/skee/CDXNifMesh.cpp b/skee/CDXNifMesh.cpp index 1358557..cddb48f 100644 --- a/skee/CDXNifMesh.cpp +++ b/skee/CDXNifMesh.cpp @@ -1,70 +1,256 @@ -#ifdef FIXME - #include "CDXNifMesh.h" +#include "CDXNifMaterial.h" #include "CDXScene.h" #include "CDXShader.h" #include "skse64/NiGeometry.h" #include "skse64/NiRTTI.h" #include "skse64/NiExtraData.h" +#include "skse64/NiRenderer.h" #include "NifUtils.h" #include #include -#include #include -#include + +#ifdef min +#undef min +#endif +#ifdef max +#undef max +#endif +#include "half.hpp" + +#include + +using namespace DirectX; CDXNifMesh::CDXNifMesh() : CDXEditableMesh() { - m_material = NULL; - m_geometry = NULL; + m_material = nullptr; m_morphable = false; } CDXNifMesh::~CDXNifMesh() { - if (m_geometry) { - m_geometry->DecRef(); - } + } -NiGeometry * CDXNifMesh::GetNifGeometry() +CDXMeshVert * CDXNifMesh::LockVertices(const LockMode type) { -#ifdef CDX_MUTEX - std::lock_guard guard(m_mutex); -#endif - return m_geometry; + EnterCriticalSection(&g_renderManager->lock); + return CDXMesh::LockVertices(type); } -bool CDXNifMesh::IsMorphable() +CDXMeshIndex * CDXNifMesh::LockIndices() { -#ifdef CDX_MUTEX - std::lock_guard guard(m_mutex); -#endif - return m_morphable; + EnterCriticalSection(&g_renderManager->lock); + return CDXMesh::LockIndices(); } -CDXNifMesh * CDXNifMesh::Create(ID3D11Device * pDevice, NiGeometry * geometry) +void CDXNifMesh::UnlockVertices(const LockMode type) +{ + CDXMesh::UnlockVertices(type); + LeaveCriticalSection(&g_renderManager->lock); +} +void CDXNifMesh::UnlockIndices(bool write) +{ + CDXMesh::UnlockIndices(write); + LeaveCriticalSection(&g_renderManager->lock); +} + +CDXBSTriShapeMesh::CDXBSTriShapeMesh() +{ + m_geometry = nullptr; +} + +CDXBSTriShapeMesh::~CDXBSTriShapeMesh() +{ + +} + +CDXBSTriShapeMesh * CDXBSTriShapeMesh::Create(CDXD3DDevice * pDevice, BSTriShape * geometry) { UInt32 vertCount = 0; UInt32 triangleCount = 0; - ID3D11Buffer * vertexBuffer = NULL; - ID3D11Buffer * indexBuffer = NULL; - LPDIRECT3DBASETEXTURE9 diffuseTexture = NULL; + UInt16 alphaFlags = 0; UInt8 alphaThreshold = 0; UInt32 shaderFlags1 = 0; UInt32 shaderFlags2 = 0; - CDXNifMesh * nifMesh = new CDXNifMesh; + CDXBSTriShapeMesh * nifMesh = new CDXBSTriShapeMesh; + nifMesh->m_geometry = geometry; + BSShaderMaterial * material = nullptr; + + if (geometry) + { + // Pre-transform + NiTransform localTransform = GetGeometryTransform(geometry); + const BSLightingShaderProperty * shaderProperty = ni_cast(geometry->m_spEffectState, BSLightingShaderProperty); + if (shaderProperty) { + material = shaderProperty->material; + shaderFlags1 = shaderProperty->shaderFlags1; + shaderFlags2 = shaderProperty->shaderFlags2; + } + + const NiAlphaProperty * alphaProperty = ni_cast(geometry->m_spPropertyState, NiAlphaProperty); + if (alphaProperty) { + alphaFlags = alphaProperty->alphaFlags; + alphaThreshold = alphaProperty->alphaThreshold; + } + + const NiSkinInstance * skinInstance = geometry->m_spSkinInstance.m_pObject; + if (!skinInstance) { + delete nifMesh; + return nullptr; + } + + const NiSkinPartition * skinPartition = skinInstance->m_spSkinPartition.m_pObject; + if (!skinPartition) { + delete nifMesh; + return nullptr; + } + + std::vector indices; + for (UInt32 p = 0; p < skinPartition->m_uiPartitions; ++p) + { + for (UInt32 t = 0; t < skinPartition->m_pkPartitions[p].m_usTriangles * 3; ++t) + { + indices.push_back(skinPartition->m_pkPartitions[p].m_pusTriList[t]); + } + } + + vertCount = geometry->numVertices; + triangleCount = indices.size(); - if (geometry) { - geometry->IncRef(); - nifMesh->m_geometry = geometry; + nifMesh->m_vertCount = vertCount; + nifMesh->m_indexCount = triangleCount; + + BSFaceGenBaseMorphExtraData * morphData = (BSFaceGenBaseMorphExtraData *)geometry->GetExtraData("FOD"); + if (morphData) { + nifMesh->m_morphable = true; + } + + nifMesh->InitializeBuffers(pDevice, nifMesh->m_vertCount, nifMesh->m_indexCount, [&](CDXMeshVert* pVertices, CDXMeshIndex* pIndices) + { + nifMesh->m_topology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + memcpy(pIndices, &indices.at(0), indices.size() * sizeof(CDXMeshIndex)); + + BSDynamicTriShape * dynamicTriShape = ni_cast(geometry, BSDynamicTriShape); + UInt32 vertexSize = NiSkinPartition::GetVertexSize(geometry->vertexDesc); + UInt32 uvOffset = NiSkinPartition::GetVertexAttributeOffset(geometry->vertexDesc, VertexAttribute::VA_TEXCOORD0); + + for (UInt32 i = 0; i < vertCount; i++) { + NiPoint3 * vertex = dynamicTriShape ? reinterpret_cast(&reinterpret_cast(dynamicTriShape->diffBlock)[i]) : reinterpret_cast(&skinPartition->m_pkPartitions[0].shapeData->m_RawVertexData[i * vertexSize]); + NiPoint3 xformed = localTransform * (*vertex); + struct UVCoord + { + half_float::half u; + half_float::half v; + }; + UVCoord * texCoord = reinterpret_cast(&skinPartition->m_pkPartitions[0].shapeData->m_RawVertexData[i * vertexSize + uvOffset]); + DirectX::XMFLOAT2 uv{ texCoord->u, texCoord->v }; + pVertices[i].Position = *(DirectX::XMFLOAT3*)&xformed; + pVertices[i].Normal = DirectX::XMFLOAT3(0,0,0); + pVertices[i].Tex = uv; + XMStoreFloat3(&pVertices[i].Color, COLOR_UNSELECTED); + } + }); + + nifMesh->BuildAdjacency(); + if (nifMesh->IsMorphable()) { + nifMesh->BuildFacemap(); + nifMesh->BuildNormals(); + } + + CDXNifMaterial * meshMaterial = new CDXNifMaterial; + meshMaterial->SetWireframeColor(XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f)); + meshMaterial->SetShaderFlags1(shaderFlags1); + meshMaterial->SetShaderFlags2(shaderFlags2); + if (alphaFlags != 0) { + meshMaterial->SetFlags(alphaFlags); + meshMaterial->SetAlphaThreshold(alphaThreshold); + } + + const BSLightingShaderProperty * lightingShaderProperty = ni_cast(geometry->m_spEffectState, BSLightingShaderProperty); + if (lightingShaderProperty) { + BSLightingShaderMaterial * lightingMaterial = static_cast(material); + NiTexture * textures[] = { lightingMaterial->texture1, lightingMaterial->texture2, lightingMaterial->texture3 }; + for (UInt32 i = 0; i < sizeof(textures) / sizeof(NiTexture*); ++i) + { + if (textures[i]) { + meshMaterial->SetNiTexture(i, textures[i]); + } + } + } + + if (material) { + switch(material->GetShaderType()) + { + case BSShaderMaterial::kShaderType_FaceGen: + { + const BSLightingShaderMaterialFacegen * tintMaterial = static_cast(material); + if (tintMaterial->renderedTexture) { + meshMaterial->SetNiTexture(4, tintMaterial->renderedTexture); + } + break; + } + case BSShaderMaterial::kShaderType_FaceGenRGBTint: + { + const BSLightingShaderMaterialFacegenTint * tintMaterial = static_cast(material); + meshMaterial->SetTintColor(DirectX::XMFLOAT4(tintMaterial->tintColor.r, tintMaterial->tintColor.g, tintMaterial->tintColor.b, 1.0f)); + break; + } + case BSShaderMaterial::kShaderType_HairTint: + { + const BSLightingShaderMaterialHairTint * tintMaterial = static_cast(material); + meshMaterial->SetTintColor(DirectX::XMFLOAT4(tintMaterial->tintColor.r, tintMaterial->tintColor.g, tintMaterial->tintColor.b, 1.0f)); + break; + } + } + } + + nifMesh->SetMaterial(meshMaterial); } + if (!nifMesh->IsMorphable()) + nifMesh->SetLocked(true); + + return nifMesh; +} + +const char * CDXBSTriShapeMesh::GetName() const +{ + return m_geometry ? m_geometry->m_name : ""; +} + +CDXLegacyNifMesh::CDXLegacyNifMesh() +{ + m_geometry = nullptr; +} + +CDXLegacyNifMesh::~CDXLegacyNifMesh() +{ + +} + +CDXLegacyNifMesh * CDXLegacyNifMesh::Create(CDXD3DDevice * pDevice, NiGeometry * geometry) +{ + UInt32 vertCount = 0; + UInt32 triangleCount = 0; + + ID3D11ShaderResourceView * diffuseTexture = nullptr; + + UInt16 alphaFlags = 0; + UInt8 alphaThreshold = 0; + UInt32 shaderFlags1 = 0; + UInt32 shaderFlags2 = 0; + + CDXLegacyNifMesh * nifMesh = new CDXLegacyNifMesh; + nifMesh->m_geometry = geometry; + if (geometry) { NiTriBasedGeomData * geometryData = niptr_cast(geometry->m_spModelData); @@ -75,17 +261,16 @@ CDXNifMesh * CDXNifMesh::Create(ID3D11Device * pDevice, NiGeometry * geometry) if (triShapeData || triStripsData) { // Pre-transform - NiTransform localTransform = GetGeometryTransform(geometry); - BSLightingShaderProperty * shaderProperty = niptr_cast(geometry->m_spEffectState); + NiTransform localTransform = GetLegacyGeometryTransform(geometry); + BSLightingShaderProperty * shaderProperty = ni_cast(geometry->m_spEffectState, BSLightingShaderProperty); if (shaderProperty) { BSLightingShaderMaterial * material = shaderProperty->material; if (material) { - NiTexture * diffuse = niptr_cast(material->diffuse); + NiTexture * diffuse = material->texture1; if (diffuse) { NiTexture::RendererData * rendererData = diffuse->rendererData; if (rendererData) { - NiTexture::NiDX9TextureData * dx9RendererData = (NiTexture::NiDX9TextureData *)rendererData; - diffuseTexture = dx9RendererData->texture; + diffuseTexture = rendererData->resourceView; } } } @@ -94,7 +279,7 @@ CDXNifMesh * CDXNifMesh::Create(ID3D11Device * pDevice, NiGeometry * geometry) shaderFlags2 = shaderProperty->shaderFlags2; } - NiAlphaProperty * alphaProperty = niptr_cast(geometry->m_spPropertyState); + NiAlphaProperty * alphaProperty = ni_cast(geometry->m_spPropertyState, NiAlphaProperty); if (alphaProperty) { alphaFlags = alphaProperty->alphaFlags; alphaThreshold = alphaProperty->alphaThreshold; @@ -104,129 +289,109 @@ CDXNifMesh * CDXNifMesh::Create(ID3D11Device * pDevice, NiGeometry * geometry) triangleCount = geometryData->m_usTriangles; nifMesh->m_vertCount = vertCount; - nifMesh->m_primitiveCount = triangleCount; + nifMesh->m_indexCount = triangleCount; BSFaceGenBaseMorphExtraData * morphData = (BSFaceGenBaseMorphExtraData *)geometry->GetExtraData("FOD"); if (morphData) { nifMesh->m_morphable = true; } - pDevice->CreateVertexBuffer(geometryData->m_usVertices*sizeof(CDXMeshVert), 0, 0, D3DPOOL_MANAGED, &vertexBuffer, NULL); - - CDXMeshVert* pVertices = NULL; - CDXMeshIndex* pIndices = NULL; + nifMesh->InitializeBuffers(pDevice, nifMesh->m_vertCount, nifMesh->m_indexCount, [&](CDXMeshVert* pVertices, CDXMeshIndex* pIndices) + { + if (triShapeData) + { + nifMesh->m_topology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + memcpy(pIndices, triShapeData->m_pusTriList, triShapeData->m_uiTriListLength * sizeof(CDXMeshIndex)); + } + else if (triStripsData) + { + nifMesh->m_topology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; + memcpy(pIndices, triStripsData->m_pusStripLists, GetStripLengthSum(triStripsData) * sizeof(CDXMeshIndex)); + } - if (triShapeData) - pDevice->CreateIndexBuffer(triangleCount*sizeof(CDXMeshFace), 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &indexBuffer, NULL); - else if (triStripsData) - pDevice->CreateIndexBuffer(GetStripLengthSum(triStripsData)*sizeof(CDXMeshIndex), 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &indexBuffer, NULL); + for (UInt32 i = 0; i < vertCount; i++) { + NiPoint3 xformed = localTransform * geometryData->m_pkVertex[i]; + NiPoint2 uv = geometryData->m_pkTexture[i]; + pVertices[i].Position = *(DirectX::XMFLOAT3*)&xformed; + DirectX::XMFLOAT3 vNormal(0, 0, 0); + pVertices[i].Normal = vNormal; + pVertices[i].Tex = *(DirectX::XMFLOAT2*)&uv; + XMStoreFloat3(&pVertices[i].Color, COLOR_UNSELECTED); + + // Build adjacency table + if (nifMesh->m_morphable) { + for (UInt32 f = 0; f < triangleCount; f++) { + if (triShapeData) { + CDXMeshFace * face = (CDXMeshFace *)&pIndices[f * 3]; + if (i == face->v1 || i == face->v2 || i == face->v3) + nifMesh->m_adjacency[i].push_back(*face); + } + else if (triStripsData) { + UInt16 v1 = 0, v2 = 0, v3 = 0; + GetTriangleIndices(triStripsData, f, v1, v2, v3); + if (i == v1 || i == v2 || i == v3) + nifMesh->m_adjacency[i].push_back(CDXMeshFace(v1, v2, v3)); + } + } + } + } - // lock i_buffer and load the indices into it - indexBuffer->Lock(0, 0, (void**)&pIndices, 0); - if (triShapeData) { - memcpy(pIndices, triShapeData->m_pusTriList, triShapeData->m_uiTriListLength*sizeof(CDXMeshIndex)); - nifMesh->m_primitiveType = D3DPT_TRIANGLELIST; - } - else if (triStripsData) { - memcpy(pIndices, triStripsData->m_pusStripLists, GetStripLengthSum(triStripsData)*sizeof(CDXMeshIndex)); - nifMesh->m_primitiveCount = GetStripLengthSum(triStripsData); - nifMesh->m_primitiveType = D3DPT_TRIANGLESTRIP; - } - nifMesh->m_indexBuffer = indexBuffer; - indexBuffer->Unlock(); - - vertexBuffer->Lock(0, 0, (void**)&pVertices, 0); - for (UInt32 i = 0; i < vertCount; i++) { - NiPoint3 xformed = localTransform * geometryData->m_pkVertex[i]; - NiPoint2 uv = geometryData->m_pkTexture[i]; - pVertices[i].Position = *(DirectX::XMFLOAT3*)&xformed; - DirectX::XMFLOAT3 vNormal(0, 0, 0); - pVertices[i].Normal = vNormal; - pVertices[i].Tex = *(DirectX::XMFLOAT2*)&uv; - pVertices[i].Color = COLOR_UNSELECTED; - - // Build adjacency table + // Don't need edge table if not editable if (nifMesh->m_morphable) { + CDXEdgeMap edges; for (UInt32 f = 0; f < triangleCount; f++) { + if (triShapeData) { CDXMeshFace * face = (CDXMeshFace *)&pIndices[f * 3]; - if (i == face->v1 || i == face->v2 || i == face->v3) - nifMesh->m_adjacency[i].push_back(*face); + auto it = edges.emplace(CDXMeshEdge(std::min(face->v1, face->v2), std::max(face->v1, face->v2)), 1); + if (it.second == false) + it.first->second++; + it = edges.emplace(CDXMeshEdge(std::min(face->v2, face->v3), std::max(face->v2, face->v3)), 1); + if (it.second == false) + it.first->second++; + it = edges.emplace(CDXMeshEdge(std::min(face->v3, face->v1), std::max(face->v3, face->v1)), 1); + if (it.second == false) + it.first->second++; } else if (triStripsData) { UInt16 v1 = 0, v2 = 0, v3 = 0; GetTriangleIndices(triStripsData, f, v1, v2, v3); - if (i == v1 || i == v2 || i == v3) - nifMesh->m_adjacency[i].push_back(CDXMeshFace(v1, v2, v3)); + auto it = edges.emplace(CDXMeshEdge(std::min(v1, v2), std::max(v1, v2)), 1); + if (it.second == false) + it.first->second++; + it = edges.emplace(CDXMeshEdge(std::min(v2, v3), std::max(v2, v3)), 1); + if (it.second == false) + it.first->second++; + it = edges.emplace(CDXMeshEdge(std::min(v3, v1), std::max(v3, v1)), 1); + if (it.second == false) + it.first->second++; } } - } - } - nifMesh->m_vertexBuffer = vertexBuffer; - - // Don't need edge table if not editable - if (nifMesh->m_morphable) { - CDXEdgeMap edges; - for (UInt32 f = 0; f < triangleCount; f++) { - - if (triShapeData) { - CDXMeshFace * face = (CDXMeshFace *)&pIndices[f * 3]; - auto it = edges.emplace(CDXMeshEdge(min(face->v1, face->v2), max(face->v1, face->v2)), 1); - if (it.second == false) - it.first->second++; - it = edges.emplace(CDXMeshEdge(min(face->v2, face->v3), max(face->v2, face->v3)), 1); - if (it.second == false) - it.first->second++; - it = edges.emplace(CDXMeshEdge(min(face->v3, face->v1), max(face->v3, face->v1)), 1); - if (it.second == false) - it.first->second++; - } - else if (triStripsData) { - UInt16 v1 = 0, v2 = 0, v3 = 0; - GetTriangleIndices(triStripsData, f, v1, v2, v3); - auto it = edges.emplace(CDXMeshEdge(min(v1, v2), max(v1, v2)), 1); - if (it.second == false) - it.first->second++; - it = edges.emplace(CDXMeshEdge(min(v2, v3), max(v2, v3)), 1); - if (it.second == false) - it.first->second++; - it = edges.emplace(CDXMeshEdge(min(v3, v1), max(v3, v1)), 1); - if (it.second == false) - it.first->second++; + for (auto e : edges) { + if (e.second == 1) { + nifMesh->m_vertexEdges.insert(e.first.p1); + nifMesh->m_vertexEdges.insert(e.first.p2); + } } } - for (auto e : edges) { - if (e.second == 1) { - nifMesh->m_vertexEdges.insert(e.first.p1); - nifMesh->m_vertexEdges.insert(e.first.p2); + // Only need vertex normals when it's editable + if (nifMesh->m_morphable) { + for (UInt32 i = 0; i < vertCount; i++) { + // Setup normals + CDXVec vNormal = XMVectorSet(0, 0, 0, 0); + if (!geometryData->m_pkNormal) + XMStoreFloat3(&pVertices[i].Normal, nifMesh->CalculateVertexNormal(i)); + else + XMStoreFloat3(&pVertices[i].Normal, XMLoadFloat3((XMFLOAT3*)&geometryData->m_pkNormal[i])); } } - } - - // Only need vertex normals when it's editable - if (nifMesh->m_morphable) { - for (UInt32 i = 0; i < vertCount; i++) { - // Setup normals - DirectX::XMFLOAT3 vNormal(0, 0, 0); - if (!geometryData->m_pkNormal) - vNormal = nifMesh->CalculateVertexNormal(i); - else - vNormal = *(DirectX::XMFLOAT3*)&geometryData->m_pkNormal[i]; - - pVertices[i].Normal = vNormal; - } - } - - vertexBuffer->Unlock(); - + }); + CDXMaterial * material = new CDXMaterial; - material->SetDiffuseTexture(diffuseTexture); - material->SetSpecularColor(DirectX::XMFLOAT3(1.0f, 1.0f, 1.0f)); - material->SetAmbientColor(DirectX::XMFLOAT3(0.2f, 0.2f, 0.2f)); - material->SetDiffuseColor(DirectX::XMFLOAT3(1.0f, 1.0f, 1.0f)); - material->SetWireframeColor(DirectX::XMFLOAT3(1.0f, 1.0f, 1.0f)); + material->SetTexture(0, diffuseTexture); + material->SetWireframeColor(XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f)); material->SetShaderFlags1(shaderFlags1); material->SetShaderFlags2(shaderFlags2); if (alphaFlags != 0) { @@ -245,37 +410,7 @@ CDXNifMesh * CDXNifMesh::Create(ID3D11Device * pDevice, NiGeometry * geometry) return nifMesh; } -void CDXNifMesh::Pass(ID3D11Device * pDevice, UInt32 iPass, CDXShader * shader) +const char * CDXLegacyNifMesh::GetName() const { - ID3DXEffect * effect = shader->GetEffect(); - if (m_material) { - effect->SetValue(shader->m_hSpecular, m_material->GetSpecularColor(), sizeof(CDXVec3)); - effect->SetValue(shader->m_hAmbient, m_material->GetAmbientColor(), sizeof(CDXVec3)); - effect->SetValue(shader->m_hDiffuse, m_material->GetDiffuseColor(), sizeof(CDXVec3)); - effect->SetValue(shader->m_hWireframeColor, m_material->GetWireframeColor(), sizeof(CDXVec3)); - - UInt32 alphaFunc = mappedTestFunctions[m_material->GetTestMode()]; - UInt32 srcBlend = mappedAlphaFunctions[m_material->GetSrcBlendMode()]; - UInt32 destBlend = mappedAlphaFunctions[m_material->GetDestBlendMode()]; - - bool isDoubleSided = (m_material->GetShaderFlags2() & BSShaderProperty::kSLSF2_Double_Sided) == BSShaderProperty::kSLSF2_Double_Sided; - bool zBufferTest = (m_material->GetShaderFlags1() & BSShaderProperty::kSLSF1_ZBuffer_Test) == BSShaderProperty::kSLSF1_ZBuffer_Test; - bool zBufferWrite = (m_material->GetShaderFlags2() & BSShaderProperty::kSLSF2_ZBuffer_Write) == BSShaderProperty::kSLSF2_ZBuffer_Write; - - pDevice->SetRenderState(D3DRS_ZENABLE, zBufferTest ? TRUE : FALSE); - pDevice->SetRenderState(D3DRS_ZWRITEENABLE, zBufferWrite ? TRUE : FALSE); - pDevice->SetRenderState(D3DRS_CULLMODE, isDoubleSided ? D3DCULL_NONE : D3DCULL_CW); - pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, m_material->GetAlphaBlending() ? TRUE : FALSE); - pDevice->SetRenderState(D3DRS_ALPHATESTENABLE, m_material->GetAlphaTesting() ? TRUE : FALSE); - pDevice->SetRenderState(D3DRS_ALPHAREF, m_material->GetAlphaThreshold()); - pDevice->SetRenderState(D3DRS_ALPHAFUNC, alphaFunc); - pDevice->SetRenderState(D3DRS_SRCBLEND, srcBlend); - pDevice->SetRenderState(D3DRS_DESTBLEND, destBlend); - } - effect->CommitChanges(); - - CDXMesh::Pass(pDevice, iPass, shader); + return m_geometry ? m_geometry->m_name : ""; } - -#endif \ No newline at end of file diff --git a/skee/CDXNifMesh.h b/skee/CDXNifMesh.h index 614f454..facc296 100644 --- a/skee/CDXNifMesh.h +++ b/skee/CDXNifMesh.h @@ -1,5 +1,3 @@ -#ifdef FIXME - #ifndef __CDXNIFMESH__ #define __CDXNIFMESH__ @@ -8,30 +6,80 @@ #include "CDXEditableMesh.h" #include "CDXMaterial.h" -#include +#include "skse64/NiTypes.h" class NiGeometry; +class BSTriShape; class CDXScene; class CDXShader; +class CDXD3DDevice; class CDXNifMesh : public CDXEditableMesh { public: CDXNifMesh(); - ~CDXNifMesh(); + virtual ~CDXNifMesh(); + + virtual const char* GetName() const override { return ""; } + virtual NiGeometry* GetLegacyGeometry() { return nullptr; } + virtual BSTriShape* GetGeometry() { return nullptr; } + virtual bool IsMorphable() const + { +#ifdef CDX_MUTEX + std::lock_guard guard(m_mutex); +#endif + return m_morphable; + } + + virtual CDXMeshVert * LockVertices(const LockMode type = READ) override; + virtual CDXMeshIndex * LockIndices() override; - static CDXNifMesh * Create(ID3D11Device * pDevice, NiGeometry * geometry); + virtual void UnlockVertices(const LockMode type) override; + virtual void UnlockIndices(bool write = false) override; - virtual void Pass(ID3D11Device * pDevice, UInt32 iPass, CDXShader * shader); +protected: + bool m_morphable; +}; + +class CDXLegacyNifMesh : public CDXNifMesh +{ +public: + CDXLegacyNifMesh(); + virtual ~CDXLegacyNifMesh(); - NiGeometry * GetNifGeometry(); - bool IsMorphable(); + static CDXLegacyNifMesh * Create(CDXD3DDevice * pDevice, NiGeometry * geometry); + virtual const char* GetName() const override; + virtual NiGeometry* GetLegacyGeometry() override + { +#ifdef CDX_MUTEX + std::lock_guard guard(m_mutex); +#endif + return m_geometry; + } private: - bool m_morphable; - NiGeometry * m_geometry; + NiPointer m_geometry; }; +class CDXBSTriShapeMesh : public CDXNifMesh +{ +public: + CDXBSTriShapeMesh(); + virtual ~CDXBSTriShapeMesh(); + + static CDXBSTriShapeMesh * Create(CDXD3DDevice * pDevice, BSTriShape * geometry); + + virtual const char* GetName() const override; + virtual BSTriShape* GetGeometry() override + { +#ifdef CDX_MUTEX + std::lock_guard guard(m_mutex); #endif + return m_geometry; + } + +private: + NiPointer m_geometry; +}; #endif \ No newline at end of file diff --git a/skee/CDXNifScene.cpp b/skee/CDXNifScene.cpp index b6f376d..fe3965a 100644 --- a/skee/CDXNifScene.cpp +++ b/skee/CDXNifScene.cpp @@ -1,12 +1,16 @@ -#ifdef FIXME - +#include "CDXD3DDevice.h" +#include "CDXCamera.h" #include "CDXNifScene.h" #include "CDXNifMesh.h" #include "CDXNifBrush.h" #include "CDXMaterial.h" #include "CDXShader.h" +#include "CDXBrushMesh.h" + +#include "common/ICriticalSection.h" #include "skse64/GameTypes.h" +#include "skse64/GameStreams.h" #include "skse64/NiRenderer.h" #include "skse64/NiTextures.h" @@ -15,14 +19,25 @@ #include "skse64/ScaleformLoader.h" +#include "FileUtils.h" +#include "Utilities.h" + +#include + +extern float g_backgroundA; +extern float g_backgroundR; +extern float g_backgroundG; +extern float g_backgroundB; + CDXNifScene::CDXNifScene() : CDXEditableScene() { - m_textureGroup = NULL; + m_renderTexture = nullptr; + m_renderTargetView = nullptr; m_currentBrush = CDXBrush::kBrushType_Smooth; - m_actor = NULL; - - m_width = 512; - m_height = 512; + m_actor = nullptr; + m_depthStencilBuffer = nullptr; + m_depthStencilState = nullptr; + m_depthStencilView = nullptr; } void CDXNifScene::CreateBrushes() @@ -35,49 +50,220 @@ void CDXNifScene::CreateBrushes() m_brushes.push_back(new CDXNifMoveBrush); } -void CDXNifScene::Setup(ID3D11Device * pDevice) +bool CDXNifScene::Setup(const CDXInitParams & initParams) { - if (m_textureGroup) + ScopedCriticalSection locker(&g_renderManager->lock); + if (m_renderTexture) Release(); - CDXEditableScene::Setup(pDevice); + auto device = initParams.device->GetDevice(); + auto deviceContext = initParams.device->GetDeviceContext(); + + ShaderFileData brushShader; + + const char * shaderPath = "SKSE/Plugins/CharGen/brush.hlsl"; + + std::vector vsb; + BSResourceNiBinaryStream vs(shaderPath); + if (!vs.IsValid()) { + _ERROR("%s - Failed to read %s", __FUNCTION__, shaderPath); + return false; + } + BSFileUtil::ReadAll(&vs, vsb); + brushShader.pSourceName = "brush.hlsl"; + brushShader.pSrcData = &vsb.at(0); + brushShader.SrcDataSize = vsb.size(); + + CDXBrushMesh * bMesh = new CDXBrushMesh; + bMesh->Create(initParams.device, false, DirectX::XMVectorSet(1.0f, 1.0f, 1.0f, 1.0f), DirectX::XMVectorSet(1.0f, 0.0f, 0.0f, 1.0f), brushShader, brushShader); + bMesh->SetVisible(false); + CDXBrushMesh * bmMesh = new CDXBrushMesh; + bmMesh->Create(initParams.device, true, DirectX::XMVectorSet(1.0f, 1.0f, 1.0f, 1.0f), DirectX::XMVectorSet(1.0f, 0.0f, 1.0f, 1.0f), brushShader, brushShader); + bmMesh->SetVisible(false); + + AddMesh(bMesh); + AddMesh(bmMesh); + + bool ret = CDXEditableScene::Setup(initParams); + if (!ret) { + return false; + } + + return CreateRenderTarget(initParams.device, initParams.viewportWidth, initParams.viewportHeight); +} + +bool CDXNifScene::CreateRenderTarget(CDXD3DDevice * pDevice, UInt32 width, UInt32 height) +{ + auto device = pDevice->GetDevice(); BSScaleformImageLoader * imageLoader = GFxLoader::GetSingleton()->imageLoader; if (!imageLoader) { _ERROR("%s - No image loader found", __FUNCTION__); - return; + return false; + } + + m_renderTexture = CreateSourceTexture("headMesh"); + if (!m_renderTexture) { + _ERROR("%s - Failed to create head mesh", __FUNCTION__); + return false; + } + + auto rendererData = m_renderTexture->rendererData = new NiTexture::RendererData(width, height); + + D3D11_TEXTURE2D_DESC1 textureDesc; + ZeroMemory(&textureDesc, sizeof(textureDesc)); + + textureDesc.Width = width; + textureDesc.Height = height; + textureDesc.MipLevels = 1; + textureDesc.ArraySize = 1; + textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + textureDesc.SampleDesc.Count = 1; + textureDesc.Usage = D3D11_USAGE_DEFAULT; + textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; + textureDesc.CPUAccessFlags = 0; + textureDesc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D1(&textureDesc, NULL, &rendererData->texture); + if (FAILED(result)) { + _ERROR("%s - Failed to create render texture.", __FUNCTION__); + return false; + } + + D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc; + ZeroMemory(&renderTargetViewDesc, sizeof(renderTargetViewDesc)); + renderTargetViewDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + renderTargetViewDesc.Texture2D.MipSlice = 0; + + result = device->CreateRenderTargetView(rendererData->texture, &renderTargetViewDesc, &m_renderTargetView); + if (FAILED(result)) { + _ERROR("%s - Failed to create render target view.", __FUNCTION__); + return false; + } + + D3D11_SHADER_RESOURCE_VIEW_DESC1 shaderResourceViewDesc; + ZeroMemory(&shaderResourceViewDesc, sizeof(shaderResourceViewDesc)); + shaderResourceViewDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + shaderResourceViewDesc.Texture2D.MostDetailedMip = 0; + shaderResourceViewDesc.Texture2D.MipLevels = 1; + + result = device->CreateShaderResourceView1(rendererData->texture, &shaderResourceViewDesc, &rendererData->resourceView); + if (FAILED(result)) { + _ERROR("%s - Failed to create shader resource view.", __FUNCTION__); + return false; + } + + imageLoader->AddVirtualImage(&m_renderTexture.m_pObject); + + D3D11_TEXTURE2D_DESC depthBufferDesc; + D3D11_DEPTH_STENCIL_DESC depthStencilDesc; + D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc; + + // Initialize the description of the depth buffer. + ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc)); + + // Set up the description of the depth buffer. + depthBufferDesc.Width = width; + depthBufferDesc.Height = height; + depthBufferDesc.MipLevels = 1; + depthBufferDesc.ArraySize = 1; + depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; + depthBufferDesc.SampleDesc.Count = 1; + depthBufferDesc.SampleDesc.Quality = 0; + depthBufferDesc.Usage = D3D11_USAGE_DEFAULT; + depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + depthBufferDesc.CPUAccessFlags = 0; + depthBufferDesc.MiscFlags = 0; + + // Create the texture for the depth buffer using the filled out description. + result = device->CreateTexture2D(&depthBufferDesc, NULL, &m_depthStencilBuffer); + if (FAILED(result)) { + _ERROR("%s - Failed to create DepthStencilBuffer", __FUNCTION__); + return false; + } + + // Initialize the description of the stencil state. + ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc)); + + // Set up the description of the stencil state. + depthStencilDesc.DepthEnable = true; + depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS; + + depthStencilDesc.StencilEnable = true; + depthStencilDesc.StencilReadMask = 0xFF; + depthStencilDesc.StencilWriteMask = 0xFF; + + // Stencil operations if pixel is front-facing. + depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR; + depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + + // Stencil operations if pixel is back-facing. + depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR; + depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + + // Create the depth stencil state. + result = device->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilState); + if (FAILED(result)) + { + _ERROR("%s - Failed to create DepthStencilState", __FUNCTION__); + return false; } - NiTexture::FormatPrefs format; - format.mipMapped = 2; - format.alphaFormat = 2; - format.pixelLayout = 6; - BSFixedString meshTexture("headMesh"); - m_textureGroup = CreateRenderTargetGroup(&meshTexture, m_width, m_height, &format, 0, 1, 0, 0, 0, 0, 0); - if (!m_textureGroup) { - _ERROR("%s - Failed to create dynamic texture", __FUNCTION__); - return; + + // Initialize the depth stencil view. + ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc)); + + // Set up the depth stencil view description. + depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; + depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + depthStencilViewDesc.Texture2D.MipSlice = 0; + + // Create the depth stencil view. + result = device->CreateDepthStencilView(m_depthStencilBuffer, &depthStencilViewDesc, &m_depthStencilView); + if (FAILED(result)) + { + _ERROR("%s - Failed to create DepthStencilView", __FUNCTION__); + return false; } - m_textureGroup->renderedTexture[0]->name = meshTexture.data; - CALL_MEMBER_FN(imageLoader, AddVirtualImage)((NiTexture**)&m_textureGroup->renderedTexture[0]); + return true; } void CDXNifScene::Release() { - if(m_textureGroup) { - NiTexture * texture = m_textureGroup->renderedTexture[0]; - if(texture) { - BSScaleformImageLoader * imageLoader = GFxLoader::GetSingleton()->imageLoader; - UInt8 ret = CALL_MEMBER_FN(imageLoader, ReleaseVirtualImage)(&texture); - } - - m_textureGroup->DecRef(); + ScopedCriticalSection locker(&g_renderManager->lock); + if(m_renderTexture) { + BSScaleformImageLoader * imageLoader = GFxLoader::GetSingleton()->imageLoader; + UInt8 ret = imageLoader->ReleaseVirtualImage(&m_renderTexture.m_pObject); + m_renderTexture = nullptr; + } + if (m_renderTargetView) { + m_renderTargetView->Release(); + m_renderTargetView = nullptr; } ReleaseImport(); - m_textureGroup = NULL; - m_actor = NULL; + m_actor = nullptr; + + if (m_depthStencilBuffer) { + m_depthStencilBuffer->Release(); + m_depthStencilBuffer = nullptr; + } + if (m_depthStencilState) { + m_depthStencilState->Release(); + m_depthStencilState = nullptr; + } + if (m_depthStencilView) { + m_depthStencilView->Release(); + m_depthStencilView = nullptr; + } CDXEditableScene::Release(); } @@ -88,7 +274,102 @@ void CDXNifScene::ReleaseImport() m_importRoot->DecRef(); } - m_importRoot = NULL; + m_importRoot = nullptr; } -#endif \ No newline at end of file +void CDXNifScene::Begin(CDXCamera * camera, CDXD3DDevice * device) +{ + BackupRenderState(device); + + auto deviceContext = device->GetDeviceContext(); + + // Setup the viewport for rendering. + D3D11_VIEWPORT viewport; + viewport.Width = (float)camera->GetWidth(); + viewport.Height = (float)camera->GetHeight(); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + viewport.TopLeftX = 0.0f; + viewport.TopLeftY = 0.0f; + + // Create the viewport. + deviceContext->RSSetViewports(1, &viewport); + + deviceContext->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView); + + // Set the depth stencil state. + deviceContext->OMSetDepthStencilState(m_depthStencilState, 1); + + float color[4]; + // Setup the color to clear the buffer to. + color[0] = g_backgroundR; + color[1] = g_backgroundG; + color[2] = g_backgroundB; + color[3] = g_backgroundA; + + // Clear the back buffer. + deviceContext->ClearRenderTargetView(m_renderTargetView, color); + + // Clear the depth buffer. + deviceContext->ClearDepthStencilView(m_depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0); +} + +void CDXNifScene::End(CDXCamera * camera, CDXD3DDevice * device) +{ + RestoreRenderState(device); +} + +void CDXNifScene::BackupRenderState(CDXD3DDevice * device) +{ + auto ctx = device->GetDeviceContext(); + + ctx->OMGetRenderTargets(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT, m_backupState.RenderTargetViews, &m_backupState.DepthStencilView); + + m_backupState.ScissorRectsCount = m_backupState.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&m_backupState.ScissorRectsCount, m_backupState.ScissorRects); + ctx->RSGetViewports(&m_backupState.ViewportsCount, m_backupState.Viewports); + ctx->RSGetState(&m_backupState.RS); + ctx->OMGetBlendState(&m_backupState.BlendState, m_backupState.BlendFactor, &m_backupState.SampleMask); + ctx->OMGetDepthStencilState(&m_backupState.DepthStencilState, &m_backupState.StencilRef); + ctx->PSGetShaderResources(0, 1, &m_backupState.PSShaderResource); + ctx->PSGetSamplers(0, 1, &m_backupState.PSSampler); + m_backupState.PSInstancesCount = m_backupState.VSInstancesCount = 256; + ctx->PSGetShader(&m_backupState.PS, m_backupState.PSInstances, &m_backupState.PSInstancesCount); + ctx->VSGetShader(&m_backupState.VS, m_backupState.VSInstances, &m_backupState.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &m_backupState.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&m_backupState.PrimitiveTopology); + ctx->IAGetIndexBuffer(&m_backupState.IndexBuffer, &m_backupState.IndexBufferFormat, &m_backupState.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &m_backupState.VertexBuffer, &m_backupState.VertexBufferStride, &m_backupState.VertexBufferOffset); + ctx->IAGetInputLayout(&m_backupState.InputLayout); +} + +void CDXNifScene::RestoreRenderState(CDXD3DDevice * device) +{ + auto ctx = device->GetDeviceContext(); + + ctx->OMSetRenderTargets(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT, m_backupState.RenderTargetViews, m_backupState.DepthStencilView); + for (UInt32 i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) { + if (m_backupState.RenderTargetViews[i]) { + m_backupState.RenderTargetViews[i]->Release(); + } + } + if (m_backupState.DepthStencilView) m_backupState.DepthStencilView->Release(); + + // Restore modified DX state + ctx->RSSetScissorRects(m_backupState.ScissorRectsCount, m_backupState.ScissorRects); + ctx->RSSetViewports(m_backupState.ViewportsCount, m_backupState.Viewports); + ctx->RSSetState(m_backupState.RS); if (m_backupState.RS) m_backupState.RS->Release(); + ctx->OMSetBlendState(m_backupState.BlendState, m_backupState.BlendFactor, m_backupState.SampleMask); if (m_backupState.BlendState) m_backupState.BlendState->Release(); + ctx->OMSetDepthStencilState(m_backupState.DepthStencilState, m_backupState.StencilRef); if (m_backupState.DepthStencilState) m_backupState.DepthStencilState->Release(); + ctx->PSSetShaderResources(0, 1, &m_backupState.PSShaderResource); if (m_backupState.PSShaderResource) m_backupState.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &m_backupState.PSSampler); if (m_backupState.PSSampler) m_backupState.PSSampler->Release(); + ctx->PSSetShader(m_backupState.PS, m_backupState.PSInstances, m_backupState.PSInstancesCount); if (m_backupState.PS) m_backupState.PS->Release(); + for (UINT i = 0; i < m_backupState.PSInstancesCount; i++) if (m_backupState.PSInstances[i]) m_backupState.PSInstances[i]->Release(); + ctx->VSSetShader(m_backupState.VS, m_backupState.VSInstances, m_backupState.VSInstancesCount); if (m_backupState.VS) m_backupState.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &m_backupState.VSConstantBuffer); if (m_backupState.VSConstantBuffer) m_backupState.VSConstantBuffer->Release(); + for (UINT i = 0; i < m_backupState.VSInstancesCount; i++) if (m_backupState.VSInstances[i]) m_backupState.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(m_backupState.PrimitiveTopology); + ctx->IASetIndexBuffer(m_backupState.IndexBuffer, m_backupState.IndexBufferFormat, m_backupState.IndexBufferOffset); if (m_backupState.IndexBuffer) m_backupState.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &m_backupState.VertexBuffer, &m_backupState.VertexBufferStride, &m_backupState.VertexBufferOffset); if (m_backupState.VertexBuffer) m_backupState.VertexBuffer->Release(); + ctx->IASetInputLayout(m_backupState.InputLayout); if (m_backupState.InputLayout) m_backupState.InputLayout->Release(); +} \ No newline at end of file diff --git a/skee/CDXNifScene.h b/skee/CDXNifScene.h index b4a6c84..65bd9de 100644 --- a/skee/CDXNifScene.h +++ b/skee/CDXNifScene.h @@ -1,27 +1,34 @@ -#ifdef FIXME - #ifndef __CDXNIFSCENE__ #define __CDXNIFSCENE__ #pragma once #include "CDXEditableScene.h" +#include "skse64/NiTypes.h" +class CDXD3DDevice; class BSRenderTargetGroup; class BSScaleformImageLoader; class Actor; class NiNode; +class NiTexture; class CDXNifScene : public CDXEditableScene { public: CDXNifScene(); - virtual void Setup(ID3D11Device * pDevice); - virtual void Release(); - virtual void CreateBrushes(); + virtual bool Setup(const CDXInitParams & initParams) override; + virtual void Release() override; + virtual void CreateBrushes() override; + + virtual void Begin(CDXCamera * camera, CDXD3DDevice * device) override; + virtual void End(CDXCamera * camera, CDXD3DDevice * device) override; - BSRenderTargetGroup * GetTextureGroup() { return m_textureGroup; } + bool CreateRenderTarget(CDXD3DDevice * device, UInt32 width, UInt32 height); + + ID3D11RenderTargetView* GetRenderTargetView() { return m_renderTargetView; } + NiTexture* GetTexture() { return m_renderTexture; } void SetWorkingActor(Actor * actor) { m_actor = actor; } Actor* GetWorkingActor() { return m_actor; } @@ -31,12 +38,46 @@ class CDXNifScene : public CDXEditableScene void ReleaseImport(); + void BackupRenderState(CDXD3DDevice * device); + void RestoreRenderState(CDXD3DDevice * device); + protected: - Actor * m_actor; - BSRenderTargetGroup * m_textureGroup; - NiNode * m_importRoot; + Actor* m_actor; + NiPointer m_importRoot; + ID3D11RenderTargetView* m_renderTargetView; + NiPointer m_renderTexture; + + ID3D11Texture2D* m_depthStencilBuffer; + ID3D11DepthStencilState* m_depthStencilState; + ID3D11DepthStencilView* m_depthStencilView; + + struct BACKUP_DX11_STATE + { + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + UINT StencilRef; + ID3D11DepthStencilState* DepthStencilState; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + ID3D11RenderTargetView* RenderTargetViews[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT]; + ID3D11DepthStencilView* DepthStencilView; + }; + + BACKUP_DX11_STATE m_backupState; }; #endif - -#endif \ No newline at end of file diff --git a/skee/CDXPicker.h b/skee/CDXPicker.h index 494f9d7..17a36ed 100644 --- a/skee/CDXPicker.h +++ b/skee/CDXPicker.h @@ -1,8 +1,6 @@ #ifndef __CDXPICKER__ #define __CDXPICKER__ -#ifdef FIXME - #pragma once #include "CDXMesh.h" @@ -58,4 +56,3 @@ class CDXPicker }; #endif -#endif \ No newline at end of file diff --git a/skee/CDXResetMask.cpp b/skee/CDXResetMask.cpp index c1d88d6..88558bd 100644 --- a/skee/CDXResetMask.cpp +++ b/skee/CDXResetMask.cpp @@ -1,25 +1,23 @@ -#ifdef FIXME - #include "CDXResetMask.h" +#include + +using namespace DirectX; CDXResetMask::CDXResetMask(CDXMesh * mesh) { m_mesh = mesh; - CDXMeshVert* pVertices = NULL; - ID3D11Buffer * pVB = m_mesh->GetVertexBuffer(); + CDXMeshVert* pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); - pVB->Lock(0, 0, (void**)&pVertices, 0); - for (CDXMeshIndex i = 0; i < m_mesh->GetVertexCount(); i++) { - CDXColor unselected = COLOR_UNSELECTED; - if (pVertices[i].Color != unselected) { + for (CDXMeshIndex i = 0; i < m_mesh->GetVertexCount(); i++) { + if (XMVector3NotEqual(XMLoadFloat3(&pVertices[i].Color), COLOR_UNSELECTED)) { m_previous[i] = pVertices[i].Color; - pVertices[i].Color = unselected; - m_current[i] = unselected; + XMStoreFloat3(&pVertices[i].Color, COLOR_UNSELECTED); + XMStoreFloat3(&m_current[i], COLOR_UNSELECTED); } } - pVB->Unlock(); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); } CDXResetMask::~CDXResetMask() @@ -35,34 +33,22 @@ CDXUndoCommand::UndoType CDXResetMask::GetUndoType() void CDXResetMask::Redo() { - CDXMeshVert* pVertices = NULL; - CDXMeshIndex* pIndices = NULL; - - ID3D11Buffer * pVB = m_mesh->GetVertexBuffer(); - - pVB->Lock(0, 0, (void**)&pVertices, 0); + CDXMeshVert* pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); // Do what we have now for (auto it : m_current) pVertices[it.first].Color = it.second; - pVB->Unlock(); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); } void CDXResetMask::Undo() { - CDXMeshVert* pVertices = NULL; - CDXMeshIndex* pIndices = NULL; - - ID3D11Buffer * pVB = m_mesh->GetVertexBuffer(); - - pVB->Lock(0, 0, (void**)&pVertices, 0); + CDXMeshVert* pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); // Undo what we did for (auto it : m_previous) pVertices[it.first].Color = it.second; - pVB->Unlock(); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); } - -#endif \ No newline at end of file diff --git a/skee/CDXResetMask.h b/skee/CDXResetMask.h index 4c1a742..3af6dd0 100644 --- a/skee/CDXResetMask.h +++ b/skee/CDXResetMask.h @@ -1,5 +1,3 @@ -#ifdef FIXME - #ifndef __CDXRESETSELECTION__ #define __CDXRESETSELECTION__ @@ -24,6 +22,4 @@ class CDXResetMask : public CDXUndoCommand CDXMaskMap m_current; }; -#endif - #endif \ No newline at end of file diff --git a/skee/CDXScene.cpp b/skee/CDXScene.cpp index ce896f5..e9eafbb 100644 --- a/skee/CDXScene.cpp +++ b/skee/CDXScene.cpp @@ -1,5 +1,3 @@ -#ifdef FIXME - #include "CDXScene.h" #include "CDXCamera.h" #include "CDXMesh.h" @@ -8,18 +6,12 @@ #include "CDXPicker.h" #include "CDXBrush.h" -#include - -CDXModelViewerCamera g_Camera; +using namespace DirectX; CDXScene::CDXScene() { m_shader = new CDXShader; - m_pStateBlock = NULL; - m_pMeshDecl = NULL; m_visible = true; - m_width = 1024; - m_height = 1024; } CDXScene::~CDXScene() @@ -32,14 +24,6 @@ CDXScene::~CDXScene() void CDXScene::Release() { - if(m_pStateBlock) { - m_pStateBlock->Release(); - m_pStateBlock = NULL; - } - if(m_pMeshDecl) { - m_pMeshDecl->Release(); - m_pMeshDecl = NULL; - } if(m_shader) { m_shader->Release(); } @@ -52,139 +36,76 @@ void CDXScene::Release() m_meshes.clear(); } -void CDXScene::Setup(ID3D11Device * pDevice) +bool CDXScene::Setup(const CDXInitParams & initParams) { - pDevice->CreateVertexDeclaration(VertexDecl, &m_pMeshDecl); - - m_shader->CreateEffect(pDevice); + if (!m_shader->Initialize(initParams)) + { + return false; + } - // Setup the camera's view parameters - CDXVec3 vecEye(30.0f, 0.0f, 0.0f); - CDXVec3 vecAt (0.0f, 0.0f, 0.0f); - g_Camera.SetWindow(m_width, m_height); - g_Camera.SetViewParams(&vecEye, &vecAt); - g_Camera.Update(); + return true; } -void CDXScene::Begin(ID3D11Device * pDevice) +void CDXScene::Render(CDXCamera * camera, CDXD3DDevice * device) { - if(!m_pStateBlock) - pDevice->CreateStateBlock(D3DSBT_ALL,&m_pStateBlock); + CDXMatrix mWorld; + CDXMatrix mView; + CDXMatrix mProj; - m_pStateBlock->Capture(); -} + mWorld = *camera->GetWorldMatrix(); + mView = camera->GetViewMatrix(); + mProj = camera->GetProjMatrix(); -void CDXScene::End(ID3D11Device * pDevice) -{ - m_pStateBlock->Apply(); -} + // Setup the vector that points upwards. + /*XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); + float posX = 0.0f, posY = 32.0f, posZ = -8.0f; -void CDXScene::Render(ID3D11Device * pDevice) -{ - CDXMatrix16 mWorld; - CDXMatrix16 mView; - CDXMatrix16 mProj; - CDXMatrix16 mWorldViewProjection; - - pDevice->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,0,1.0f,0); - - ID3DXEffect * pEffect = m_shader->GetEffect(); - if(!pEffect) - return; - - mWorld = *g_Camera.GetWorldMatrix(); - mView = *g_Camera.GetViewMatrix(); - mProj = *g_Camera.GetProjMatrix(); - mWorldViewProjection = mWorld * mView * mProj; - - CDXVec3 vAmbient = CDXVec3(0.0f, 0.0f, 0.0f); - CDXVec3 vDiffuse = CDXVec3(1.0f, 1.0f, 1.0f); - CDXVec3 vSpecular = CDXVec3(1.0f, 1.0f, 1.0f); - int nShininess = 0; - float fAlpha = 1.0f; - - pEffect->SetMatrix(m_shader->m_hWorldViewProjection, &mWorldViewProjection); - pEffect->SetMatrix(m_shader->m_hWorld, &mWorld); - pEffect->SetValue(m_shader->m_hCameraPosition, g_Camera.GetEyePt(), sizeof(CDXVec3)); - pEffect->SetValue(m_shader->m_hAmbient, vAmbient, sizeof(CDXVec3)); - pEffect->SetValue(m_shader->m_hDiffuse, vDiffuse, sizeof(CDXVec3)); - pEffect->SetValue(m_shader->m_hSpecular, vSpecular, sizeof(CDXVec3)); - pEffect->SetFloat(m_shader->m_hOpacity, fAlpha); - pEffect->SetInt(m_shader->m_hSpecularPower, nShininess); - - pDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); - //pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); - pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - pDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); - pDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); - pDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); - pDevice->SetRenderState(D3DRS_LASTPIXEL, TRUE); - pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); - pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO); - pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); - pDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); - pDevice->SetRenderState(D3DRS_ALPHAREF, 0); - pDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_ALWAYS); - pDevice->SetRenderState(D3DRS_DITHERENABLE, FALSE); - pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - pDevice->SetRenderState(D3DRS_FOGENABLE, FALSE); - pDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE); - //pDevice->SetRenderState(D3DRS_FOGCOLOR, 0); - //pDevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE); - //pDevice->SetRenderState(D3DRS_FOGSTART, *((DWORD*) (&fFogStart))); - //pDevice->SetRenderState(D3DRS_FOGEND, *((DWORD*) (&fFogEnd)); - //pDevice->SetRenderState(D3DRS_FOGDENSITY, *((DWORD*) (&fFogDensity)); - pDevice->SetRenderState(D3DRS_RANGEFOGENABLE, FALSE); - pDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - pDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP); - pDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP); - pDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP); - pDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); - pDevice->SetRenderState(D3DRS_STENCILREF, 0); - pDevice->SetRenderState(D3DRS_STENCILMASK, 0xFFFFFFFF); - pDevice->SetRenderState(D3DRS_STENCILWRITEMASK, 0xFFFFFFFF); - pDevice->SetRenderState(D3DRS_TEXTUREFACTOR, 0xFFFFFFFF); - pDevice->SetRenderState(D3DRS_CLIPPING, TRUE); - pDevice->SetRenderState(D3DRS_LIGHTING, TRUE); - pDevice->SetRenderState(D3DRS_AMBIENT, 0); - pDevice->SetRenderState(D3DRS_COLORVERTEX, TRUE); - pDevice->SetRenderState(D3DRS_LOCALVIEWER, TRUE); - pDevice->SetRenderState(D3DRS_NORMALIZENORMALS, FALSE); - pDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1); - pDevice->SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2); - pDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL); - pDevice->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL); - pDevice->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_DISABLE); - pDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); - pDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); - pDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); - pDevice->SetRenderState(D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE); - pDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE); - pDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0x0000000F); - pDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); - pDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); - pDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); - pDevice->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, FALSE); - pDevice->SetRenderState(D3DRS_CCW_STENCILFAIL, D3DSTENCILOP_KEEP); - pDevice->SetRenderState(D3DRS_CCW_STENCILZFAIL, D3DSTENCILOP_KEEP); - pDevice->SetRenderState(D3DRS_CCW_STENCILPASS, D3DSTENCILOP_KEEP); - pDevice->SetRenderState(D3DRS_CCW_STENCILFUNC, D3DCMP_ALWAYS); - pDevice->SetRenderState(D3DRS_COLORWRITEENABLE1, 0x0000000f); - pDevice->SetRenderState(D3DRS_COLORWRITEENABLE2, 0x0000000f); - pDevice->SetRenderState(D3DRS_COLORWRITEENABLE3, 0x0000000f); - pDevice->SetRenderState(D3DRS_BLENDFACTOR, 0xffffffff); - pDevice->SetRenderState(D3DRS_SRGBWRITEENABLE, 0); - pDevice->SetRenderState(D3DRS_DEPTHBIAS, 0); - pDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); - pDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE); - pDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_ZERO); - pDevice->SetRenderState(D3DRS_BLENDOPALPHA, D3DBLENDOP_ADD); - - pDevice->SetVertexDeclaration( m_pMeshDecl ); + // Setup the position of the camera in the world. + XMVECTOR position = XMVectorSet(posX, posY, posZ, 0.0f); + + // Calculate the rotation in radians. + float radians = 0.0f * 0.0174532925f; + + // Setup where the camera is looking. + XMVECTOR lookAt = XMVectorSet(0, 0, 0, 0.0f); + + // Create the view matrix from the three vectors. + mView = XMMatrixLookAtLH(position, lookAt, up); + + float fieldOfView = (float)XM_PI / 4.0f; + float screenAspect = (float)1280 / (float)720; + + const float SCREEN_DEPTH = 1000.0f; + const float SCREEN_NEAR = 0.1f; + + // Create the projection matrix for 3D rendering. + mProj = XMMatrixPerspectiveFovLH(fieldOfView, screenAspect, SCREEN_NEAR, SCREEN_DEPTH); + + // Initialize the world matrix to the identity matrix. + mWorld = XMMatrixIdentity();*/ + + // Create an orthographic projection matrix for 2D rendering. + //m_orthoMatrix = XMMatrixOrthographicLH((float)screenWidth, (float)screenHeight, screenNear, screenDepth); + + + CDXShader::VertexBuffer params; + params.world = mWorld; + params.view = mView; + params.projection = mProj; + params.viewport = XMVectorSet((float)camera->GetWidth(), (float)camera->GetHeight(), 0, 0); + + m_shader->VSSetShaderBuffer(device, params); + + CDXShader::TransformBuffer xform; + xform.transform = XMMatrixIdentity(); for(auto mesh : m_meshes) { + xform.transform = mesh->GetTransform(); + + m_shader->VSSetTransformBuffer(device, xform); + if(mesh->IsVisible()) { - mesh->Render(pDevice, m_shader); + mesh->Render(device, m_shader); } } } @@ -195,45 +116,47 @@ void CDXScene::AddMesh(CDXMesh * mesh) m_meshes.push_back(mesh); } -bool CDXScene::Pick(int x, int y, CDXPicker & picker) +bool CDXScene::Pick(CDXCamera * camera, int x, int y, CDXPicker & picker) { CDXRayInfo rayInfo; CDXRayInfo mRayInfo; - CDXVec3 mousePoint; - mousePoint.x = x; - mousePoint.y = -y; - mousePoint.z = 1.0f; + CDXVec mousePoint = XMVectorSet((float)x, (float)-y, 1.0f, 0.0f); - const CDXMatrix* pmatProj = g_Camera.GetProjMatrix(); + CDXMatrix pmatProj = camera->GetProjMatrix(); // Compute the vector of the pick ray in screen space - CDXVec3 v; - v.x = (((2.0f * x) / g_Camera.GetWidth()) - 1) / pmatProj->_11; - v.y = -(((2.0f * y) / g_Camera.GetHeight()) - 1) / pmatProj->_22; - v.z = 1.0f; + CDXVec v = XMVectorSet( + (((2.0f * x) / camera->GetWidth()) - 1) / XMVectorGetX(pmatProj.r[0]), + -(((2.0f * y) / camera->GetHeight()) - 1) / XMVectorGetY(pmatProj.r[1]), + 1.0f, + 1.0f + ); + + CDXVec v2 = XMVectorSet((float)x, (float)y,1.0f,0.0f); + auto vRes = XMVector3Unproject(v2, 0, 0, camera->GetWidth(), camera->GetHeight(), 0.0f, 1.0f, camera->GetProjMatrix(), camera->GetViewMatrix(), *camera->GetWorldMatrix()); + auto dir = XMVector3Normalize(vRes); // Get the inverse view matrix - const CDXMatrix matView = *g_Camera.GetViewMatrix(); - const CDXMatrix matWorld = *g_Camera.GetWorldMatrix(); - CDXMatrix mWorldView = matWorld * matView; - CDXMatrix m; - DirectX::XMFLOAT4X4Inverse( &m, NULL, &mWorldView ); + CDXMatrix matView = camera->GetViewMatrix(); + const CDXMatrix * matWorld = camera->GetWorldMatrix(); + CDXMatrix mWorldView = XMMatrixMultiply(*matWorld, matView); + + CDXMatrix m = XMMatrixInverse(nullptr, mWorldView); + + CDXMatrix mRot = m; + mRot.r[3] = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f); + + //auto rot = XMQuaternionRotationMatrix(m); // Transform the screen space pick ray into 3D space - rayInfo.direction.x = v.x * m._11 + v.y * m._21 + v.z * m._31; - rayInfo.direction.y = v.x * m._12 + v.y * m._22 + v.z * m._32; - rayInfo.direction.z = v.x * m._13 + v.y * m._23 + v.z * m._33; - rayInfo.origin.x = m._41; - rayInfo.origin.y = m._42; - rayInfo.origin.z = m._43; - rayInfo.point.x = mousePoint.x * m._11 + mousePoint.y * m._21 + mousePoint.z * m._31; - rayInfo.point.y = mousePoint.x * m._12 + mousePoint.y * m._22 + mousePoint.z * m._32; - rayInfo.point.z = mousePoint.x * m._13 + mousePoint.y * m._23 + mousePoint.z * m._33; + rayInfo.direction = XMVector3Transform(v, mRot); + rayInfo.origin = XMVectorSetW(m.r[3], 0.0f); + rayInfo.point = XMVector3Transform(mousePoint, mRot); // Create mirror raycast mRayInfo = rayInfo; - mRayInfo.direction.x = -mRayInfo.direction.x; - mRayInfo.origin.x = -mRayInfo.origin.x; + mRayInfo.direction = XMVectorSetX(mRayInfo.direction, -XMVectorGetX(mRayInfo.direction)); + mRayInfo.origin = XMVectorSetX(mRayInfo.origin, -XMVectorGetX(mRayInfo.origin)); // Find closest collision points bool hitMesh = false; @@ -282,5 +205,3 @@ bool CDXScene::Pick(int x, int y, CDXPicker & picker) return hitVertices; } - -#endif \ No newline at end of file diff --git a/skee/CDXScene.h b/skee/CDXScene.h index dbc12b1..bb1ca67 100644 --- a/skee/CDXScene.h +++ b/skee/CDXScene.h @@ -1,23 +1,21 @@ -#ifdef FIXME - #ifndef __CDXSCENE__ #define __CDXSCENE__ #pragma once -#include "CDXCamera.h" -#include "CDXBrush.h" +#include "CDXTypes.h" #include +class CDXCamera; +class CDXD3DDevice; class CDXMesh; class CDXShader; class CDXPicker; class CDXBrush; class CDXMaskAddBrush; class CDXInflateBrush; +struct ShaderFileData; -typedef DirectX::XMFLOAT4X4A16 CDXMatrix16; -typedef DirectX::XMFLOAT4X4 CDXMatrix; typedef std::vector CDXMeshList; class CDXScene @@ -26,41 +24,28 @@ class CDXScene CDXScene(); ~CDXScene(); - virtual void Setup(ID3D11Device * pDevice); + virtual bool Setup(const CDXInitParams & initParams); virtual void Release(); - virtual void Render(ID3D11Device * pDevice); + virtual void Render(CDXCamera * camera, CDXD3DDevice * device); - virtual void Begin(ID3D11Device * pDevice); - virtual void End(ID3D11Device * pDevice); + virtual void Begin(CDXCamera * camera, CDXD3DDevice * device) { }; + virtual void End(CDXCamera * camera, CDXD3DDevice * device) { }; - UInt32 GetNumMeshes() { return m_meshes.size(); } + size_t GetNumMeshes() { return m_meshes.size(); } CDXMesh * GetNthMesh(UInt32 i) { return m_meshes.at(i); } void AddMesh(CDXMesh * mesh); - bool Pick(int x, int y, CDXPicker & picker); + bool Pick(CDXCamera * camera, int x, int y, CDXPicker & picker); CDXShader * GetShader() { return m_shader; } void SetVisible(bool visible) { m_visible = visible; } bool IsVisible() const { return m_visible; } - UInt32 GetWidth() const { return m_height; } - UInt32 GetHeight() const { return m_height; } - protected: bool m_visible; - - UInt32 m_width; - UInt32 m_height; - - CDXShader * m_shader; - - IDirect3DVertexDeclaration9* m_pMeshDecl; - IDirect3DStateBlock9* m_pStateBlock; - + CDXShader * m_shader; CDXMeshList m_meshes; }; #endif - -#endif \ No newline at end of file diff --git a/skee/CDXShader.cpp b/skee/CDXShader.cpp index 2228712..fe9e836 100644 --- a/skee/CDXShader.cpp +++ b/skee/CDXShader.cpp @@ -1,281 +1,553 @@ -#ifdef FIXME - +#include "CDXD3DDevice.h" #include "CDXShader.h" +#include "CDXShaderCompile.h" +#include "CDXMaterial.h" + +#include + +using namespace DirectX; CDXShader::CDXShader() { - m_pEffect = NULL; - m_hAmbient = NULL; - m_hDiffuse = NULL; - m_hSpecular = NULL; - m_hOpacity = NULL; - m_hSpecularPower = NULL; - m_hLightColor = NULL; - m_hLightPosition = NULL; - m_hCameraPosition = NULL; - m_hTexture = NULL; - m_hTime = NULL; - m_hWorld = NULL; - m_hWorldViewProjection = NULL; - m_hTransform = NULL; - m_hWireframeColor = NULL; + m_vertexShader = nullptr; + m_pixelShader = nullptr; + m_wireShader = nullptr; + m_layout = nullptr; + m_sampleState = nullptr; + m_matrixBuffer = nullptr; + m_transformBuffer = nullptr; + m_materialBuffer = nullptr; + m_solidState = nullptr; + m_wireState = nullptr; } void CDXShader::Release() { - if(m_pEffect) { - m_pEffect->Release(); - m_pEffect = NULL; + // Release the light constant buffer. + if (m_transformBuffer) + { + m_transformBuffer->Release(); + m_transformBuffer = nullptr; + } + + if (m_materialBuffer) + { + m_materialBuffer->Release(); + m_materialBuffer = nullptr; + } + + // Release the matrix constant buffer. + if (m_matrixBuffer) + { + m_matrixBuffer->Release(); + m_matrixBuffer = nullptr; + } + + // Release the sampler state. + if (m_sampleState) + { + m_sampleState->Release(); + m_sampleState = nullptr; + } + + // Release the layout. + if (m_layout) + { + m_layout->Release(); + m_layout = nullptr; + } + + // Release the pixel shader. + if (m_pixelShader) + { + m_pixelShader->Release(); + m_pixelShader = nullptr; + } + + // Release the vertex shader. + if (m_vertexShader) + { + m_vertexShader->Release(); + m_vertexShader = nullptr; + } + + if (m_solidState) + { + m_solidState->Release(); + m_solidState = nullptr; + } + if (m_wireState) + { + m_wireState->Release(); + m_wireState = nullptr; } } -void CDXShader::CreateEffect(ID3D11Device * pDevice) +bool CDXShader::Initialize(const CDXInitParams & initParams) { - /*const char* g_strBuffer = "float3 g_vMaterialAmbient : Ambient = float3( 0.2f, 0.2f, 0.2f ); // Material's ambient color\r\n" - "float3 g_vMaterialDiffuse : Diffuse = float3( 1.0f, 1.0f, 1.0f ); // Material's diffuse color\r\n" - "float3 g_vMaterialSpecular : Specular = float3( 1.0f, 1.0f, 1.0f ); // Material's specular color\r\n" - "float g_fMaterialAlpha : Opacity = 1.0f;\r\n" - "int g_nMaterialShininess : SpecularPower = 32;\r\n" - "float3 g_vLightColor : LightColor = float3( 1.0f, 1.0f, 1.0f ); // Light color\r\n" - "float3 g_vLightPosition : LightPosition = float3( 50.0f, 10.0f, 0.0f ); // Light position\r\n" - "float3 g_vCameraPosition : CameraPosition;\r\n" - "texture g_MeshTexture : Texture; // Color texture for mesh\r\n" - "float g_fTime : Time; // App's time in seconds\r\n" - "float4x4 g_mWorld : World; // World matrix\r\n" - "float4x4 g_mWorldViewProjection : WorldViewProjection; // World * View * Projection matrix\r\n" - "sampler MeshTextureSampler = \r\n" - " sampler_state\r\n" - "{\r\n" - " Texture = ;\r\n" - " MipFilter = LINEAR;\r\n" - " MinFilter = LINEAR;\r\n" - " MagFilter = LINEAR;\r\n" - "};\r\n" - "void Projection( float4 vPosObject: POSITION,\r\n" - " float3 vNormalObject: NORMAL,\r\n" - " float2 vTexCoordIn: TEXCOORD0,\r\n" - " out float4 vPosProj: POSITION,\r\n" - " out float2 vTexCoordOut: TEXCOORD0,\r\n" - " out float4 vColorOut: COLOR0,\r\n" - " uniform bool bSpecular\r\n" - " )\r\n" - "{\r\n" - " float4 vPosWorld = mul( vPosObject, g_mWorld );\r\n" - " vPosProj = mul( vPosObject, g_mWorldViewProjection );\r\n" - " float3 vNormalWorld = mul( vNormalObject, (float3x3)g_mWorld );\r\n" - " vTexCoordOut = vTexCoordIn;\r\n" - " float3 vLight = normalize( g_vLightPosition - vPosWorld.xyz );\r\n" - " vColorOut.rgb = g_vLightColor * g_vMaterialAmbient;\r\n" - " vColorOut.rgb += g_vLightColor * g_vMaterialDiffuse * saturate( dot( vLight, vNormalWorld ) );\r\n" - " if( bSpecular )\r\n" - " {\r\n" - " float3 vCamera = normalize(vPosWorld.xyz - g_vCameraPosition);\r\n" - " float3 vReflection = reflect( vLight, vNormalWorld );\r\n" - " float fPhongValue = saturate( dot( vReflection, vCamera ) );\r\n" - " vColorOut.rgb += g_vMaterialSpecular * pow(fPhongValue, g_nMaterialShininess);\r\n" - " }\r\n" - " vColorOut.a = g_fMaterialAlpha;\r\n" - "}\r\n" - "void Lighting( float2 vTexCoord: TEXCOORD0,\r\n" - " float4 vColorIn: COLOR0,\r\n" - " out float4 vColorOut: COLOR0,\r\n" - " uniform bool bTexture )\r\n" - "{\r\n" - " vColorOut = vColorIn;\r\n" - " if( bTexture )\r\n" - " vColorOut.rgb *= tex2D( MeshTextureSampler, vTexCoord );\r\n" - "}\r\n" - "technique Specular\r\n" - "{\r\n" - " pass P0\r\n" - " {\r\n" - " VertexShader = compile vs_2_0 Projection(true);\r\n" - " PixelShader = compile ps_2_0 Lighting(false);\r\n" - " }\r\n" - "}\r\n" - "technique NoSpecular\r\n" - "{\r\n" - " pass P0\r\n" - " {\r\n" - " VertexShader = compile vs_2_0 Projection(false);\r\n" - " PixelShader = compile ps_2_0 Lighting(false);\r\n" - " }\r\n" - "}\r\n" - "technique TexturedSpecular\r\n" - "{\r\n" - " pass P0\r\n" - " {\r\n" - " VertexShader = compile vs_2_0 Projection(true);\r\n" - " PixelShader = compile ps_2_0 Lighting(true);\r\n" - " }\r\n" - "}\r\n" - "technique TexturedNoSpecular\r\n" - "{\r\n" - " pass P0\r\n" - " {\r\n" - " VertexShader = compile vs_2_0 Projection(false);\r\n" - " PixelShader = compile ps_2_0 Lighting(true);\r\n" - " }\r\n" - "}\r\n";*/ - const char* g_strBuffer = "float3 g_vMaterialAmbient : Ambient = float3( 0.2f, 0.2f, 0.2f ); // Material's ambient color\r\n" - "float3 g_vMaterialDiffuse : Diffuse = float3( 1.0f, 1.0f, 1.0f ); // Material's diffuse color\r\n" - "float3 g_vMaterialSpecular : Specular = float3( 1.0f, 1.0f, 1.0f ); // Material's specular color\r\n" - "float g_fMaterialAlpha : Opacity = 1.0f;\r\n" - "float g_fMaterialAlphaThreshold : AlphaThreshold = 0.0f;\r\n" - "int g_nMaterialShininess : SpecularPower = 32;\r\n" - "float3 g_vLightColor : LightColor = float3( 1.0f, 1.0f, 1.0f ); // Light color\r\n" - "float3 g_vLightPosition : LightPosition = float3( 0.0f, -100.0f, 0.0f ); // Light position\r\n" - "float3 g_vCameraPosition : CameraPosition;\r\n" - "float3 g_vWireframe : WireframeColor = float3( 1.0f, 1.0f, 1.0f);\r\n" - "texture g_MeshTexture : Texture; // Color texture for mesh\r\n" - "float g_fTime : Time; // App's time in seconds\r\n" - "float4x4 g_mWorld : World; // World matrix\r\n" - "float4x4 g_mWorldViewProjection : WorldViewProjection; // World * View * Projection matrix\r\n" - "float4x4 g_mTransform: Transform;\r\n" - "sampler DiffuseSampler = \r\n" - " sampler_state\r\n" - "{\r\n" - " Texture = ;\r\n" - " MipFilter = LINEAR;\r\n" - " MinFilter = LINEAR;\r\n" - " MagFilter = LINEAR;\r\n" - " AddressU = WRAP;\r\n" - " AddressV = WRAP;\r\n" - " AddressW = WRAP;\r\n" - "};\r\n" - "void Basic( float4 vPosObject: POSITION0,\r\n" - " float3 vNormalObject: NORMAL0,\r\n" - " float2 vTexCoordIn: TEXCOORD0,\r\n" - " float4 vColorIn: COLOR0,\r\n" - " float4 vColorSelect: COLOR1,\r\n" - " out float4 vPosProj: POSITION,\r\n" - " out float2 vTexCoordOut: TEXCOORD0,\r\n" - " out float4 vColorOut: COLOR0,\r\n" - " uniform float fLine )\r\n" - "{\r\n" - " float4 vPosTransform = mul(vPosObject, g_mTransform);\r\n" - " vPosTransform.xyz *= fLine;\r\n" - " vPosProj = mul( vPosTransform, g_mWorldViewProjection );\r\n" - " vTexCoordOut = vTexCoordIn;\r\n" - " vColorOut.a = g_fMaterialAlpha;\r\n" - " vColorOut.rgb = g_vWireframe;\r\n" - "}\r\n" - "void Projection( float4 vPosObject: POSITION0,\r\n" - " float3 vNormalObject: NORMAL0,\r\n" - " float2 vTexCoordIn: TEXCOORD0,\r\n" - " float4 vColorIn: COLOR0,\r\n" - " out float4 vPosProj: POSITION,\r\n" - " out float2 vTexCoordOut: TEXCOORD0,\r\n" - " out float4 vColorOut: COLOR0,\r\n" - " uniform bool bSpecular )\r\n" - "{\r\n" - " float4 vPosTransform = mul(vPosObject, g_mTransform);\r\n" - " float4 vPosWorld = mul( vPosTransform, g_mWorld );\r\n" - " vPosProj = mul( vPosTransform, g_mWorldViewProjection );\r\n" - " float3 vNormalWorld = mul( vNormalObject, (float3x3)g_mWorld );\r\n" - " vTexCoordOut = vTexCoordIn;\r\n" - " float3 vLight = normalize( g_vLightPosition - vPosWorld.xyz );\r\n" - " vColorOut.rgb = g_vLightColor * g_vMaterialAmbient;\r\n" - " vColorOut.rgb += g_vLightColor * g_vMaterialDiffuse * saturate( dot( vLight, vNormalWorld ) );\r\n" - " if( bSpecular ) {\r\n" - " float3 vCamera = normalize(vPosWorld.xyz - g_vCameraPosition);\r\n" - " float3 vReflection = reflect( vLight, vNormalWorld );\r\n" - " float fPhongValue = saturate( dot( vReflection, vCamera ) );\r\n" - " vColorOut.rgb += g_vMaterialSpecular * pow(fPhongValue, g_nMaterialShininess);\r\n" - " }\r\n" - " vColorOut.a = g_fMaterialAlpha;\r\n" - " vColorOut *= vColorIn;\r\n" - "}\r\n" - "void Lighting( float4 vPos: POSITION0,\r\n" - " float2 vTexCoord: TEXCOORD0,\r\n" - " float4 vColorIn: COLOR0,\r\n" - " out float4 vColorOut: COLOR0,\r\n" - " uniform bool bTexture )\r\n" - "{\r\n" - " vColorOut = vColorIn;\r\n" - " if( bTexture )\r\n" - " vColorOut *= tex2D( DiffuseSampler, vTexCoord );\r\n" - "}\r\n" - "technique Specular\r\n" - "{\r\n" - " pass P0\r\n" - " {\r\n" - " VertexShader = compile vs_2_0 Projection(true);\r\n" - " PixelShader = compile ps_2_0 Lighting(false);\r\n" - " }\r\n" - "}\r\n" - "technique Wireframe\r\n" - "{\r\n" - " pass P0\r\n" - " {\r\n" - " VertexShader = compile vs_2_0 Basic(1.000f);\r\n" - " PixelShader = compile ps_2_0 Lighting(false);\r\n" - " }\r\n" - " pass P1\r\n" - " {\r\n" - " VertexShader = compile vs_2_0 Basic(1.002f);\r\n" - " PixelShader = compile ps_2_0 Lighting(false);\r\n" - " }\r\n" - " pass P2\r\n" - " {\r\n" - " VertexShader = compile vs_2_0 Basic(1.004f);\r\n" - " PixelShader = compile ps_2_0 Lighting(false);\r\n" - " }\r\n" - "}\r\n" - "technique NoSpecular\r\n" - "{\r\n" - " pass P0\r\n" - " {\r\n" - " VertexShader = compile vs_2_0 Projection(false);\r\n" - " PixelShader = compile ps_2_0 Lighting(false);\r\n" - " }\r\n" - "}\r\n" - "technique TexturedSpecular\r\n" - "{\r\n" - " pass P0\r\n" - " {\r\n" - " VertexShader = compile vs_2_0 Projection(true);\r\n" - " PixelShader = compile ps_2_0 Lighting(true);\r\n" - " }\r\n" - "}\r\n" - "technique TexturedNoSpecular\r\n" - "{\r\n" - " pass P0\r\n" - " {\r\n" - " VertexShader = compile vs_2_0 Projection(false);\r\n" - " PixelShader = compile ps_2_0 Lighting(true);\r\n" - " }\r\n" - "}\r\n"; - - UINT dwBufferSize = ( UINT )strlen( g_strBuffer ) + 1; - - try + HRESULT result; + ID3DBlob* errorMessage; + ID3DBlob* vertexShaderBuffer; + ID3DBlob* pixelShaderBuffer; + D3D11_INPUT_ELEMENT_DESC polygonLayout[4]; + unsigned int numElements; + D3D11_SAMPLER_DESC samplerDesc; + D3D11_BUFFER_DESC bufferDesc; + + auto pDevice = initParams.device->GetDevice(); + + // Initialize the pointers this function will use to null. + errorMessage = 0; + vertexShaderBuffer = 0; + pixelShaderBuffer = 0; + + std::stringstream errors; + + // Compile the vertex shader code. + result = CompileShaderFromData(initParams.vertexShader.pSrcData, initParams.vertexShader.SrcDataSize, initParams.vertexShader.pSourceName, "LightVertexShader", "vs_5_0", &vertexShaderBuffer, &errorMessage); + if (FAILED(result)) + { + // If the shader failed to compile it should have writen something to the error message. + if (errorMessage) + { + OutputShaderErrorMessage(errorMessage, errors); + } + _ERROR("%s - Failed to compile vertex shader %s", __FUNCTION__, errors.str().c_str()); + return false; + } + + // Create the vertex shader from the buffer. + result = pDevice->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &m_vertexShader); + if (FAILED(result)) + { + _ERROR("%s - Failed to create vertex shader", __FUNCTION__); + return false; + } + + + // Compile the pixel shader code. + result = CompileShaderFromData(initParams.pixelShader.pSrcData, initParams.pixelShader.SrcDataSize, initParams.pixelShader.pSourceName, "LightPixelShader", "ps_5_0", &pixelShaderBuffer, &errorMessage); + if (FAILED(result)) + { + // If the shader failed to compile it should have writen something to the error message. + if (errorMessage) + { + OutputShaderErrorMessage(errorMessage, errors); + } + _ERROR("%s - Failed to compile pixel shader %s", __FUNCTION__, errors.str().c_str()); + return false; + } + + // Create the vertex shader from the buffer. + result = pDevice->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &m_pixelShader); + if (FAILED(result)) { - if (D3DXCreateEffect(pDevice, g_strBuffer, dwBufferSize, NULL, NULL, D3DXFX_NOT_CLONEABLE, NULL, &m_pEffect, NULL) == D3D_OK) + _ERROR("%s - Failed to create pixel shader", __FUNCTION__); + return false; + } + + // Compile the pixel shader code. + result = CompileShaderFromData(initParams.pixelShader.pSrcData, initParams.pixelShader.SrcDataSize, initParams.pixelShader.pSourceName, "WireframePixelShader", "ps_5_0", &pixelShaderBuffer, &errorMessage); + if (FAILED(result)) + { + // If the shader failed to compile it should have writen something to the error message. + if (errorMessage) { - if (m_pEffect) { - m_hAmbient = m_pEffect->GetParameterBySemantic(0, "Ambient"); - m_hDiffuse = m_pEffect->GetParameterBySemantic(0, "Diffuse"); - m_hSpecular = m_pEffect->GetParameterBySemantic(0, "Specular"); - m_hOpacity = m_pEffect->GetParameterBySemantic(0, "Opacity"); - m_hSpecularPower = m_pEffect->GetParameterBySemantic(0, "SpecularPower"); - m_hLightColor = m_pEffect->GetParameterBySemantic(0, "LightColor"); - m_hLightPosition = m_pEffect->GetParameterBySemantic(0, "LightPosition"); - m_hCameraPosition = m_pEffect->GetParameterBySemantic(0, "CameraPosition"); - m_hTexture = m_pEffect->GetParameterBySemantic(0, "Texture"); - m_hTime = m_pEffect->GetParameterBySemantic(0, "Time"); - m_hWorld = m_pEffect->GetParameterBySemantic(0, "World"); - m_hWorldViewProjection = m_pEffect->GetParameterBySemantic(0, "WorldViewProjection"); - m_hWireframeColor = m_pEffect->GetParameterBySemantic(0, "WireframeColor"); - m_hTransform = m_pEffect->GetParameterBySemantic(0, "Transform"); + OutputShaderErrorMessage(errorMessage, errors); + } + + _ERROR("%s - Failed to compile wireframe shader %s", __FUNCTION__, errors.str().c_str()); + return false; + } + + // Create the vertex shader from the buffer. + result = pDevice->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &m_wireShader); + if (FAILED(result)) + { + _ERROR("%s - Failed to create wireframe shader", __FUNCTION__); + return false; + } +#if 0 + { + // Compile the vertex shader code. + result = CompileShader(L"./light.gs", "VS", "vs_5_0", &vertexShaderBuffer, &errorMessage); + if (FAILED(result)) + { + // If the shader failed to compile it should have writen something to the error message. + if (errorMessage) + { + OutputShaderErrorMessage(errorMessage, errors); } + return false; + } + + // Create the vertex shader from the buffer. + result = pDevice->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &m_ws.vs); + if (FAILED(result)) + { + return false; } + + + // Compile the pixel shader code. + result = CompileShader(L"./light.gs", "PSSolidWire", "ps_5_0", &pixelShaderBuffer, &errorMessage); + if (FAILED(result)) + { + // If the shader failed to compile it should have writen something to the error message. + if (errorMessage) + { + OutputShaderErrorMessage(errorMessage, errors); + } + + return false; + } + + // Create the vertex shader from the buffer. + result = pDevice->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &m_ws.ps); + if (FAILED(result)) + { + return false; + } + + // Compile the pixel shader code. + result = CompileShader(L"./light.gs", "GSSolidWire", "gs_5_0", &pixelShaderBuffer, &errorMessage); + if (FAILED(result)) + { + // If the shader failed to compile it should have writen something to the error message. + if (errorMessage) + { + OutputShaderErrorMessage(errorMessage, errors); + } + + return false; + } + + // Create the vertex shader from the buffer. + result = pDevice->CreateGeometryShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &m_ws.gs); + if (FAILED(result)) + { + return false; + } + } +#endif + + // Create the vertex input layout description. + // This setup needs to match the VertexType stucture in the ModelClass and in the shader. + polygonLayout[0].SemanticName = "POSITION"; + polygonLayout[0].SemanticIndex = 0; + polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; + polygonLayout[0].InputSlot = 0; + polygonLayout[0].AlignedByteOffset = 0; + polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[0].InstanceDataStepRate = 0; + + polygonLayout[1].SemanticName = "TEXCOORD"; + polygonLayout[1].SemanticIndex = 0; + polygonLayout[1].Format = DXGI_FORMAT_R32G32_FLOAT; + polygonLayout[1].InputSlot = 0; + polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[1].InstanceDataStepRate = 0; + + polygonLayout[2].SemanticName = "NORMAL"; + polygonLayout[2].SemanticIndex = 0; + polygonLayout[2].Format = DXGI_FORMAT_R32G32B32_FLOAT; + polygonLayout[2].InputSlot = 0; + polygonLayout[2].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + polygonLayout[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[2].InstanceDataStepRate = 0; + + polygonLayout[3].SemanticName = "COLOR"; + polygonLayout[3].SemanticIndex = 0; + polygonLayout[3].Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + polygonLayout[3].InputSlot = 0; + polygonLayout[3].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + polygonLayout[3].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[3].InstanceDataStepRate = 0; + + // Get a count of the elements in the layout. + numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]); + + // Create the vertex input layout. + result = pDevice->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), + vertexShaderBuffer->GetBufferSize(), &m_layout); + if (FAILED(result)) + { + _ERROR("%s - Failed to create input layout", __FUNCTION__); + return false; + } + + // Release the vertex shader buffer and pixel shader buffer since they are no longer needed. + vertexShaderBuffer->Release(); + vertexShaderBuffer = 0; + + pixelShaderBuffer->Release(); + pixelShaderBuffer = 0; + + // Create a texture sampler state description. + samplerDesc.Filter = D3D11_FILTER_ANISOTROPIC; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.MipLODBias = 0.0f; + samplerDesc.MaxAnisotropy = 16; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + samplerDesc.BorderColor[0] = 0; + samplerDesc.BorderColor[1] = 0; + samplerDesc.BorderColor[2] = 0; + samplerDesc.BorderColor[3] = 0; + samplerDesc.MinLOD = 0; + samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; + + // Create the texture sampler state. + result = pDevice->CreateSamplerState(&samplerDesc, &m_sampleState); + if (FAILED(result)) + { + _ERROR("%s - Failed to create sampler state", __FUNCTION__); + return false; + } + + // Setup the description of the matrix dynamic constant buffer that is in the vertex shader. + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + bufferDesc.ByteWidth = sizeof(VertexBuffer); + + // Create the matrix constant buffer pointer so we can access the vertex shader constant buffer from within this class. + result = pDevice->CreateBuffer(&bufferDesc, NULL, &m_matrixBuffer); + if (FAILED(result)) + { + _ERROR("%s - Failed to create matrix buffer", __FUNCTION__); + return false; + } + + bufferDesc.ByteWidth = sizeof(TransformBuffer); + + // Create the matrix constant buffer pointer so we can access the vertex shader constant buffer from within this class. + result = pDevice->CreateBuffer(&bufferDesc, NULL, &m_transformBuffer); + if (FAILED(result)) + { + _ERROR("%s - Failed to create transform buffer", __FUNCTION__); + return false; + } + + // Setup the description of the light dynamic constant buffer that is in the pixel shader. + // Note that ByteWidth always needs to be a multiple of 16 if using D3D11_BIND_CONSTANT_BUFFER or CreateBuffer will fail. + bufferDesc.ByteWidth = sizeof(MaterialBuffer); + + // Create the constant buffer pointer so we can access the vertex shader constant buffer from within this class. + result = pDevice->CreateBuffer(&bufferDesc, NULL, &m_materialBuffer); + if (FAILED(result)) + { + _ERROR("%s - Failed to create material buffer", __FUNCTION__); + return false; + } + + // Setup the raster description which will determine how and what polygons will be drawn. + D3D11_RASTERIZER_DESC rasterDesc; + rasterDesc.AntialiasedLineEnable = false; + rasterDesc.CullMode = D3D11_CULL_BACK; + rasterDesc.DepthBias = 0; + rasterDesc.DepthBiasClamp = 0.0f; + rasterDesc.DepthClipEnable = true; + rasterDesc.FillMode = D3D11_FILL_SOLID; + rasterDesc.FrontCounterClockwise = false; + rasterDesc.MultisampleEnable = false; + rasterDesc.ScissorEnable = false; + rasterDesc.SlopeScaledDepthBias = 0.0f; + + // Create the rasterizer state from the description we just filled out. + result = pDevice->CreateRasterizerState(&rasterDesc, &m_solidState); + if (FAILED(result)) + { + _ERROR("%s - Failed to create solid rasterizer state", __FUNCTION__); + return false; + } + + rasterDesc.MultisampleEnable = true; + rasterDesc.AntialiasedLineEnable = true; + rasterDesc.DepthClipEnable = false; + rasterDesc.DepthBias = -1000; + rasterDesc.CullMode = D3D11_CULL_NONE; + rasterDesc.FillMode = D3D11_FILL_WIREFRAME; + result = pDevice->CreateRasterizerState(&rasterDesc, &m_wireState); + if (FAILED(result)) + { + _ERROR("%s - Failed to create wire rasterizer state", __FUNCTION__); + return false; + } + + return true; +} + +void CDXShader::OutputShaderErrorMessage(ID3D10Blob* errorMessage, std::stringstream & output) +{ + char* compileErrors; + size_t bufferSize, i; + + // Get a pointer to the error message text buffer. + compileErrors = (char*)(errorMessage->GetBufferPointer()); + + // Get the length of the message. + bufferSize = errorMessage->GetBufferSize(); + + // Write out the error message. + for (i = 0; iRelease(); + errorMessage = 0; +} + + +bool CDXShader::VSSetShaderBuffer(CDXD3DDevice * device, VertexBuffer & params) +{ + HRESULT result; + D3D11_MAPPED_SUBRESOURCE mappedResource; + VertexBuffer* dataPtr; + + auto pDeviceContext = device->GetDeviceContext(); + + // Lock the matrix constant buffer so it can be written to. + result = pDeviceContext->Map(m_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + _ERROR("%s - Failed to map matrix buffer", __FUNCTION__); + return false; } - catch ( ... ) + + // Get a pointer to the data in the constant buffer. + dataPtr = (VertexBuffer*)mappedResource.pData; + + // Transpose the matrices to prepare them for the shader. + params.world = XMMatrixTranspose(params.world); + params.view = XMMatrixTranspose(params.view); + params.projection = XMMatrixTranspose(params.projection); + + *dataPtr = params; + + // Unlock the matrix constant buffer. + pDeviceContext->Unmap(m_matrixBuffer, 0); + pDeviceContext->VSSetConstantBuffers(0, 1, &m_matrixBuffer); + return true; +} + +bool CDXShader::VSSetTransformBuffer(CDXD3DDevice * device, TransformBuffer & params) +{ + HRESULT result; + D3D11_MAPPED_SUBRESOURCE mappedResource; + TransformBuffer* dataPtr; + + auto pDeviceContext = device->GetDeviceContext(); + + // Lock the matrix constant buffer so it can be written to. + result = pDeviceContext->Map(m_transformBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) { - _ERROR("%s - Fatal error creating D3D Effect.", __FUNCTION__); - m_pEffect = nullptr; + _ERROR("%s - Failed to map transform buffer", __FUNCTION__); + return false; } + + // Get a pointer to the data in the constant buffer. + dataPtr = (TransformBuffer*)mappedResource.pData; + + *dataPtr = params; + + // Unlock the matrix constant buffer. + pDeviceContext->Unmap(m_transformBuffer, 0); + pDeviceContext->VSSetConstantBuffers(1, 1, &m_transformBuffer); + return true; } -#endif \ No newline at end of file +bool CDXShader::PSSetMaterialBuffers(CDXD3DDevice * device, MaterialBuffer & params) +{ + HRESULT result; + D3D11_MAPPED_SUBRESOURCE mappedResource; + MaterialBuffer* dataPtr; + + auto pDeviceContext = device->GetDeviceContext(); + + // Lock the light constant buffer so it can be written to. + result = pDeviceContext->Map(m_materialBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + _ERROR("%s - Failed to map material buffer", __FUNCTION__); + return false; + } + + // Get a pointer to the data in the constant buffer. + dataPtr = (MaterialBuffer*)mappedResource.pData; + + // Copy the lighting variables into the constant buffer. + *dataPtr = params; + + // Unlock the constant buffer. + pDeviceContext->Unmap(m_materialBuffer, 0); + pDeviceContext->PSSetConstantBuffers(0, 1, &m_materialBuffer); + return true; +} + +void CDXShader::RenderShader(CDXD3DDevice * device, CDXMaterial * material) +{ + auto pDeviceContext = device->GetDeviceContext(); + // Set the vertex input layout. + pDeviceContext->IASetInputLayout(m_layout); + + // Set the vertex and pixel shaders that will be used to render this triangle. + + CDXShader::MaterialBuffer mat; + + ID3D11RasterizerState * state = m_solidState; + ID3D11VertexShader * vshader = m_vertexShader; + ID3D11PixelShader * pshader = m_pixelShader; + ID3D11BlendState * blendingState = material->GetBlendingState(device); + + float blendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + if (material->IsWireframe()) + { + mat.hasNormal = false; + mat.hasSpecular = false; + mat.hasDetailMap = false; + mat.hasTintMask = false; + mat.tintColor = XMFLOAT4(0, 0, 0, 0); + mat.wireColor = material->GetWireframeColor(); + mat.alphaThreshold = material->GetAlphaBlending() ? 0.0f : material->GetAlphaThreshold() / 255.0f; + state = m_wireState; + pshader = m_wireShader; + } + else + { + mat.hasNormal = material->HasNormal(); + mat.hasSpecular = material->HasSpecular(); + mat.hasDetailMap = material->HasDetail(); + mat.hasTintMask = material->HasTintMask(); + mat.tintColor = material->GetTintColor(); + mat.wireColor = XMFLOAT4(0, 0, 0, 0); + mat.alphaThreshold = material->GetAlphaBlending() ? 0.0f : material->GetAlphaThreshold() / 255.0f; + } + + PSSetMaterialBuffers(device, mat); + + pDeviceContext->OMSetBlendState(blendingState, blendFactor, 0xffffffff); + + pDeviceContext->RSSetState(state); + + Microsoft::WRL::ComPtr vs; + pDeviceContext->VSGetShader(&vs, nullptr, nullptr); + Microsoft::WRL::ComPtr ps; + pDeviceContext->PSGetShader(&ps, nullptr, nullptr); + + if(vs.Get() != vshader) pDeviceContext->VSSetShader(vshader, nullptr, 0); + if(ps.Get() != pshader) pDeviceContext->PSSetShader(pshader, nullptr, 0); + + // Set shader texture resource in the pixel shader. + pDeviceContext->PSSetShaderResources(0, 5, material->GetTextures()); + + // Set the sampler state in the pixel shader. + pDeviceContext->PSSetSamplers(0, 1, &m_sampleState); +} \ No newline at end of file diff --git a/skee/CDXShader.h b/skee/CDXShader.h index 14f3e9c..d711e75 100644 --- a/skee/CDXShader.h +++ b/skee/CDXShader.h @@ -1,40 +1,77 @@ -#ifdef FIXME - #ifndef __CDXSHADER__ #define __CDXSHADER__ #pragma once -#include +#include "CDXTypes.h" +#include + +class CDXD3DDevice; +class CDXMaterial; +class CDXMesh; class CDXShader { public: CDXShader(); - void CreateEffect(ID3D11Device * pDevice); + bool Initialize(const CDXInitParams & initParams); void Release(); - D3DXHANDLE m_hAmbient; - D3DXHANDLE m_hDiffuse; - D3DXHANDLE m_hSpecular; - D3DXHANDLE m_hOpacity; - D3DXHANDLE m_hSpecularPower; - D3DXHANDLE m_hLightColor; - D3DXHANDLE m_hLightPosition; - D3DXHANDLE m_hCameraPosition; - D3DXHANDLE m_hTexture; - D3DXHANDLE m_hTime; - D3DXHANDLE m_hWorld; - D3DXHANDLE m_hWorldViewProjection; - D3DXHANDLE m_hTransform; - D3DXHANDLE m_hWireframeColor; - - ID3DXEffect * GetEffect() { return m_pEffect; } + struct VertexBuffer + { + DirectX::XMMATRIX world; + DirectX::XMMATRIX view; + DirectX::XMMATRIX projection; + DirectX::XMVECTOR viewport; + }; + + struct TransformBuffer + { + DirectX::XMMATRIX transform; + }; + + struct MaterialBuffer + { + DirectX::XMFLOAT4 wireColor; + DirectX::XMFLOAT4 tintColor; + int hasNormal = 0; + int hasSpecular = 0; + int hasDetailMap = 0; + int hasTintMask = 0; + float alphaThreshold = 0.0f; + float padding1 = 0.0f; + float padding2 = 0.0f; + float padding3 = 0.0f; + }; + + void RenderShader(CDXD3DDevice * device, CDXMaterial * material); + + bool VSSetShaderBuffer(CDXD3DDevice * device, VertexBuffer & params); + bool VSSetTransformBuffer(CDXD3DDevice * device, TransformBuffer & transform); + bool PSSetMaterialBuffers(CDXD3DDevice * device, MaterialBuffer & material); protected: - ID3DXEffect * m_pEffect; -}; + void OutputShaderErrorMessage(ID3D10Blob* errorMessage, std::stringstream & output); + ID3D11VertexShader * m_vertexShader; + ID3D11PixelShader* m_pixelShader; + ID3D11PixelShader* m_wireShader; +#if 0 + struct WireShaders + { + ID3D11VertexShader * vs; + ID3D11GeometryShader* gs; + ID3D11PixelShader* ps; + }; + WireShaders m_ws; #endif + ID3D11InputLayout* m_layout; + ID3D11SamplerState* m_sampleState; + ID3D11RasterizerState* m_solidState; + ID3D11RasterizerState* m_wireState; + ID3D11Buffer* m_matrixBuffer; + ID3D11Buffer* m_transformBuffer; + ID3D11Buffer* m_materialBuffer; +}; -#endif \ No newline at end of file +#endif diff --git a/skee/CDXShaderCompile.cpp b/skee/CDXShaderCompile.cpp new file mode 100644 index 0000000..f4bb49f --- /dev/null +++ b/skee/CDXShaderCompile.cpp @@ -0,0 +1,82 @@ +#include "CDXShaderCompile.h" + +#include + +typedef HRESULT (*_D3DCompile)(LPCVOID pSrcData,SIZE_T SrcDataSize, LPCSTR pSourceName, const D3D_SHADER_MACRO* pDefines, ID3DInclude* pInclude, LPCSTR pEntrypoint, LPCSTR pTarget, UINT Flags1, UINT Flags2, ID3DBlob** ppCode, ID3DBlob** ppErrorMsgs); + +HRESULT CompileShaderFromData(LPCVOID pSrcData, _In_ SIZE_T SrcDataSize, _In_opt_ LPCSTR pSourceName, _In_ LPCSTR entryPoint, _In_ LPCSTR profile, _Outptr_ ID3DBlob** blob, _Outptr_ ID3DBlob** errorBlob) +{ + if (!pSrcData || !entryPoint || !profile || !blob) + return E_INVALIDARG; + + *blob = nullptr; + + UINT flags = D3DCOMPILE_ENABLE_STRICTNESS; +#if defined( DEBUG ) || defined( _DEBUG ) + flags |= D3DCOMPILE_DEBUG; +#endif + + const D3D_SHADER_MACRO defines[] = + { + NULL, NULL + }; + + HMODULE d3dcompiler = GetModuleHandle("d3dcompiler_43.dll"); // Try to find the compiler matching the DirectX version Skyrim SE is built on + if (!d3dcompiler) { + d3dcompiler = GetModuleHandle("d3dcompiler_42.dll"); // Alt that seems to also be shipped with SE + } + + _D3DCompile compile = (_D3DCompile)GetProcAddress(d3dcompiler, "D3DCompile"); + if (!compile) { + _ERROR("Failed to find d3dcompiler"); + return ERROR_API_UNAVAILABLE; + } + + ID3DBlob* shaderBlob = nullptr; + HRESULT hr = compile(pSrcData, SrcDataSize, pSourceName, defines, nullptr, entryPoint, profile, flags, 0, &shaderBlob, errorBlob); + if (FAILED(hr)) + { + if (shaderBlob) + shaderBlob->Release(); + + return hr; + } + + *blob = shaderBlob; + + return hr; +} + +HRESULT CompileShader(_In_ LPCWSTR srcFile, _In_ LPCSTR entryPoint, _In_ LPCSTR profile, _Outptr_ ID3DBlob** blob, _Outptr_ ID3DBlob** errorBlob) +{ + if (!srcFile || !entryPoint || !profile || !blob) + return E_INVALIDARG; + + *blob = nullptr; + + UINT flags = D3DCOMPILE_ENABLE_STRICTNESS; +#if defined( DEBUG ) || defined( _DEBUG ) + flags |= D3DCOMPILE_DEBUG; +#endif + + const D3D_SHADER_MACRO defines[] = + { + NULL, NULL + }; + + ID3DBlob* shaderBlob = nullptr; + HRESULT hr = D3DCompileFromFile(srcFile, defines, D3D_COMPILE_STANDARD_FILE_INCLUDE, + entryPoint, profile, + flags, 0, &shaderBlob, errorBlob); + if (FAILED(hr)) + { + if (shaderBlob) + shaderBlob->Release(); + + return hr; + } + + *blob = shaderBlob; + + return hr; +} \ No newline at end of file diff --git a/skee/CDXShaderCompile.h b/skee/CDXShaderCompile.h new file mode 100644 index 0000000..fa90b72 --- /dev/null +++ b/skee/CDXShaderCompile.h @@ -0,0 +1,8 @@ +#pragma once + +#pragma comment(lib,"d3dcompiler.lib") + +#include + +HRESULT CompileShaderFromData(LPCVOID pSrcData, _In_ SIZE_T SrcDataSize, _In_opt_ LPCSTR pSourceName, _In_ LPCSTR entryPoint, _In_ LPCSTR profile, _Outptr_ ID3DBlob** blob, _Outptr_ ID3DBlob** errorBlob); +HRESULT CompileShader(_In_ LPCWSTR srcFile, _In_ LPCSTR entryPoint, _In_ LPCSTR profile, _Outptr_ ID3DBlob** blob, _Outptr_ ID3DBlob** errorBlob); \ No newline at end of file diff --git a/skee/CDXStroke.cpp b/skee/CDXStroke.cpp index a3eedf0..52081c8 100644 --- a/skee/CDXStroke.cpp +++ b/skee/CDXStroke.cpp @@ -1,13 +1,13 @@ -#ifdef FIXME - #include "CDXStroke.h" #include "CDXBrush.h" +using namespace DirectX; + CDXStroke::CDXStroke(CDXBrush * brush, CDXEditableMesh * mesh) { m_brush = brush; m_mesh = mesh; - m_origin = CDXVec3(0.0f, 0.0f, 0.0f); + m_origin = XMVectorZero(); m_mirror = false; } @@ -23,28 +23,28 @@ void CDXBasicStroke::Begin(CDXPickInfo & pickInfo) void CDXBasicHitStroke::Redo() { - CDXMeshVert* pVertices = m_mesh->LockVertices(); + CDXMeshVert* pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); if (!pVertices) return; // Do what we have now for (auto it : m_current) - pVertices[it.first].Position += it.second; + XMStoreFloat3(&pVertices[it.first].Position, XMVectorAdd(XMLoadFloat3(&pVertices[it.first].Position), it.second)); - m_mesh->UnlockVertices(); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); } void CDXBasicHitStroke::Undo() { - CDXMeshVert* pVertices = m_mesh->LockVertices(); + CDXMeshVert* pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); if (!pVertices) return; // Undo what we did for (auto it : m_current) - pVertices[it.first].Position -= it.second; + XMStoreFloat3(&pVertices[it.first].Position, XMVectorSubtract(XMLoadFloat3(&pVertices[it.first].Position), it.second)); - m_mesh->UnlockVertices(); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); } CDXMaskAddStroke::~CDXMaskAddStroke() @@ -60,7 +60,7 @@ CDXStroke::StrokeType CDXMaskAddStroke::GetStrokeType() void CDXMaskAddStroke::Redo() { - CDXMeshVert* pVertices = m_mesh->LockVertices(); + CDXMeshVert* pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); if (!pVertices) return; @@ -68,12 +68,12 @@ void CDXMaskAddStroke::Redo() for (auto it : m_current) pVertices[it.first].Color = it.second; - m_mesh->UnlockVertices(); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); } void CDXMaskAddStroke::Undo() { - CDXMeshVert* pVertices = m_mesh->LockVertices(); + CDXMeshVert* pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); if (!pVertices) return; @@ -81,24 +81,25 @@ void CDXMaskAddStroke::Undo() for (auto it : m_previous) pVertices[it.first].Color = it.second; - m_mesh->UnlockVertices(); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); } void CDXMaskAddStroke::Update(CDXStroke::Info * info) { - CDXMeshVert * pVertices = m_mesh->LockVertices(); + CDXMeshVert * pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); if (!pVertices) return; // Place the new info in the new map, update the colors - CDXColor color = COLOR_SELECTED; + CDXColor color; + XMStoreFloat3(&color, COLOR_SELECTED); auto ret = m_current.emplace(info->index, color); if (ret.second) m_previous.emplace(info->index, pVertices[info->index].Color); pVertices[info->index].Color = color; - m_mesh->UnlockVertices(); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); } CDXStroke::StrokeType CDXMaskSubtractStroke::GetStrokeType() @@ -108,20 +109,22 @@ CDXStroke::StrokeType CDXMaskSubtractStroke::GetStrokeType() void CDXMaskSubtractStroke::Update(CDXStroke::Info * info) { - CDXMeshVert * pVertices = m_mesh->LockVertices(); + CDXMeshVert * pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); if (!pVertices) return; // Place the new info in the new map, update the colors - CDXColor color = COLOR_UNSELECTED; - if (pVertices[info->index].Color != color) { + CDXColor color; + XMStoreFloat3(&color, COLOR_UNSELECTED); + + if (XMVector3NotEqual(XMLoadFloat3(&pVertices[info->index].Color), XMLoadFloat3(&color))) { auto ret = m_current.emplace(info->index, color); if (ret.second) m_previous.emplace(info->index, pVertices[info->index].Color); pVertices[info->index].Color = color; } - m_mesh->UnlockVertices(); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); } CDXInflateStroke::~CDXInflateStroke() @@ -136,17 +139,17 @@ CDXStroke::StrokeType CDXInflateStroke::GetStrokeType() void CDXInflateStroke::Update(CDXStroke::Info * info) { - CDXMeshVert * pVertices = m_mesh->LockVertices(); + CDXMeshVert * pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); if (!pVertices) return; - CDXVec3 vertexNormal = ((InflateInfo*)info)->normal; - CDXVec3 difference = vertexNormal * info->strength * info->falloff; + CDXVec vertexNormal = ((InflateInfo*)info)->normal; + CDXVec difference = vertexNormal * (float)(info->strength * info->falloff); - m_current.emplace(info->index, CDXVec3(0, 0, 0)); + m_current.emplace(info->index, XMVectorZero()); m_current[info->index] += difference; - pVertices[info->index].Position += difference; - m_mesh->UnlockVertices(); + XMStoreFloat3(&pVertices[info->index].Position, XMVectorAdd(XMLoadFloat3(&pVertices[info->index].Position), difference)); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); } CDXStroke::StrokeType CDXDeflateStroke::GetStrokeType() @@ -156,17 +159,17 @@ CDXStroke::StrokeType CDXDeflateStroke::GetStrokeType() void CDXDeflateStroke::Update(CDXStroke::Info * info) { - CDXMeshVert * pVertices = m_mesh->LockVertices(); + CDXMeshVert * pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); if (!pVertices) return; - CDXVec3 vertexNormal = ((InflateInfo*)info)->normal; - CDXVec3 difference = vertexNormal * info->strength * info->falloff; + CDXVec vertexNormal = ((InflateInfo*)info)->normal; + CDXVec difference = vertexNormal * (float)(info->strength * info->falloff); - m_current.emplace(info->index, CDXVec3(0, 0, 0)); + m_current.emplace(info->index, XMVectorZero()); m_current[info->index] -= difference; - pVertices[info->index].Position -= difference; - m_mesh->UnlockVertices(); + XMStoreFloat3(&pVertices[info->index].Position, XMVectorSubtract(XMLoadFloat3(&pVertices[info->index].Position), difference)); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); } CDXSmoothStroke::~CDXSmoothStroke() @@ -181,11 +184,11 @@ CDXStroke::StrokeType CDXSmoothStroke::GetStrokeType() void CDXSmoothStroke::Update(CDXStroke::Info * info) { - CDXMeshVert * pVertices = m_mesh->LockVertices(); + CDXMeshVert * pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); if (!pVertices) return; - CDXVec3 newPos = CDXVec3(0, 0, 0); + CDXVec newPos = XMVectorZero(); UInt32 totalCount = 0; m_mesh->VisitAdjacencies(info->index, [&](CDXMeshFace & face) @@ -202,20 +205,20 @@ void CDXSmoothStroke::Update(CDXStroke::Info * info) if (m3 >= m_mesh->GetVertexCount()) return false; - CDXVec3 sum = pVertices[m1].Position + pVertices[m2].Position + pVertices[m3].Position; + CDXVec sum = XMLoadFloat3(&pVertices[m1].Position) + XMLoadFloat3(&pVertices[m2].Position) + XMLoadFloat3(&pVertices[m3].Position); newPos += sum / 3; totalCount++; return false; }); - newPos /= totalCount; + newPos /= (float)totalCount; - CDXVec3 difference = (newPos - pVertices[info->index].Position) * info->strength * info->falloff; + CDXVec difference = (newPos - XMLoadFloat3(&pVertices[info->index].Position)) * (float)(info->strength * info->falloff); - m_current.emplace(info->index, CDXVec3(0,0,0)); + m_current.emplace(info->index, XMVectorZero()); m_current[info->index] += difference; - pVertices[info->index].Position += difference; - m_mesh->UnlockVertices(); + XMStoreFloat3(&pVertices[info->index].Position, XMVectorAdd(XMLoadFloat3(&pVertices[info->index].Position), difference)); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); } CDXMoveStroke::~CDXMoveStroke() @@ -238,48 +241,46 @@ void CDXMoveStroke::Begin(CDXPickInfo & pickInfo) void CDXMoveStroke::Redo() { - CDXMeshVert* pVertices = m_mesh->LockVertices(); + CDXMeshVert* pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); if (!pVertices) return; // Do what we have now for (auto it : m_current) - pVertices[it.first].Position += it.second; + XMStoreFloat3(&pVertices[it.first].Position, XMVectorAdd(XMLoadFloat3(&pVertices[it.first].Position), it.second)); - m_mesh->UnlockVertices(); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); } void CDXMoveStroke::Undo() { - CDXMeshVert* pVertices = m_mesh->LockVertices(); + CDXMeshVert* pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); if (!pVertices) return; // Undo what we did for (auto it : m_current) - pVertices[it.first].Position -= it.second; + XMStoreFloat3(&pVertices[it.first].Position, XMVectorSubtract(XMLoadFloat3(&pVertices[it.first].Position), it.second)); - m_mesh->UnlockVertices(); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); } void CDXMoveStroke::Update(CDXStroke::Info * info) { - CDXMeshVert * pVertices = m_mesh->LockVertices(); + CDXMeshVert * pVertices = m_mesh->LockVertices(CDXMesh::LockMode::WRITE); - m_previous.emplace(info->index, pVertices[info->index].Position); - CDXVec3 newPosition = m_previous[info->index] + ((MoveInfo*)info)->offset * info->strength * info->falloff; - CDXVec3 difference = newPosition - pVertices[info->index].Position; + m_previous.emplace(info->index, XMLoadFloat3(&pVertices[info->index].Position)); + CDXVec newPosition = m_previous[info->index] + ((MoveInfo*)info)->offset * (float)(info->strength * info->falloff); + CDXVec difference = newPosition - XMLoadFloat3(&pVertices[info->index].Position); - m_current.emplace(info->index, CDXVec3(0, 0, 0)); + m_current.emplace(info->index, XMVectorZero()); m_current[info->index] += difference; - pVertices[info->index].Position += difference; + XMStoreFloat3(&pVertices[info->index].Position, XMVectorAdd(XMLoadFloat3(&pVertices[info->index].Position), difference)); - m_mesh->UnlockVertices(); + m_mesh->UnlockVertices(CDXMesh::LockMode::WRITE); } void CDXMoveStroke::End() { m_hitIndices.clear(); } - -#endif \ No newline at end of file diff --git a/skee/CDXStroke.h b/skee/CDXStroke.h index 80819ef..ae4d143 100644 --- a/skee/CDXStroke.h +++ b/skee/CDXStroke.h @@ -1,5 +1,3 @@ -#ifdef FIXME - #ifndef __CDXSTROKE__ #define __CDXSTROKE__ @@ -41,15 +39,15 @@ class CDXStroke : public CDXUndoCommand virtual void Update(Info * pickInfo) = 0; virtual void End() = 0; virtual void Apply(SInt32 i) = 0; - virtual UInt32 Length() = 0; + virtual size_t Length() = 0; - CDXVec3 GetOrigin() { return m_origin; } + CDXVec GetOrigin() { return m_origin; } void SetMirror(bool m) { m_mirror = m; } bool IsMirror() const { return m_mirror; } CDXEditableMesh * GetMesh() { return m_mesh; } protected: - CDXVec3 m_origin; + CDXVec m_origin; CDXEditableMesh * m_mesh; CDXBrush * m_brush; bool m_mirror; @@ -76,7 +74,7 @@ class CDXBasicHitStroke : public CDXBasicStroke virtual void Undo(); virtual void Redo(); - virtual UInt32 Length() { return m_current.size(); } + virtual size_t Length() { return m_current.size(); } protected: CDXVectorMap m_current; @@ -92,7 +90,7 @@ class CDXMaskAddStroke : public CDXBasicStroke virtual void Update(Info * strokeInfo); virtual void Undo(); virtual void Redo(); - virtual UInt32 Length() { return m_current.size(); } + virtual size_t Length() { return m_current.size(); } protected: CDXMaskMap m_previous; @@ -117,7 +115,7 @@ class CDXInflateStroke : public CDXBasicHitStroke class InflateInfo : public CDXStroke::Info { public: - CDXVec3 normal; + CDXVec normal; }; virtual StrokeType GetStrokeType(); @@ -153,7 +151,7 @@ class CDXMoveStroke : public CDXBasicStroke class MoveInfo : public CDXStroke::Info { public: - CDXVec3 offset; + CDXVec offset; }; virtual void Begin(CDXPickInfo & pickInfo); @@ -162,7 +160,7 @@ class CDXMoveStroke : public CDXBasicStroke virtual void End(); virtual void Undo(); virtual void Redo(); - virtual UInt32 Length() { return m_current.size(); } + virtual size_t Length() { return m_current.size(); } CDXRayInfo & GetRayInfo() { return m_rayInfo; } @@ -177,5 +175,3 @@ class CDXMoveStroke : public CDXBasicStroke }; #endif - -#endif \ No newline at end of file diff --git a/skee/CDXTypes.h b/skee/CDXTypes.h index 48c6b97..9b18007 100644 --- a/skee/CDXTypes.h +++ b/skee/CDXTypes.h @@ -3,6 +3,27 @@ #include #include #include +#include + +class CDXCamera; +class CDXD3DDevice; + +struct ShaderFileData +{ + LPCVOID pSrcData; + SIZE_T SrcDataSize; + LPCSTR pSourceName; +}; + +struct CDXInitParams +{ + CDXD3DDevice * device; + CDXCamera * camera; + ShaderFileData vertexShader; + ShaderFileData pixelShader; + int viewportWidth; + int viewportHeight; +}; typedef DirectX::XMMATRIX CDXMatrix; typedef unsigned short CDXMeshIndex; @@ -13,7 +34,7 @@ typedef DirectX::XMFLOAT2 CDXVec2; typedef DirectX::XMFLOAT3 CDXColor; typedef std::set CDXMeshIndexSet; -typedef std::map CDXHitIndexMap; +typedef std::unordered_map CDXHitIndexMap; struct CDXMeshEdge { @@ -88,7 +109,7 @@ namespace std { struct CDXMeshVert { CDXVec3 Position; - CDXVec3 Normal; CDXVec2 Tex; + CDXVec3 Normal; CDXColor Color; }; \ No newline at end of file diff --git a/skee/CDXUndo.cpp b/skee/CDXUndo.cpp index 6c24da9..bc77a51 100644 --- a/skee/CDXUndo.cpp +++ b/skee/CDXUndo.cpp @@ -1,5 +1,3 @@ -#ifdef FIXME - #include "CDXUndo.h" CDXUndoStack g_undoStack; @@ -19,7 +17,7 @@ void CDXUndoStack::Release() SInt32 CDXUndoStack::Push(CDXUndoCommandPtr action) { CDXUndoStack::iterator actionIt; - int maxState = size() - 1; + SInt32 maxState = (SInt32)size() - 1; if(m_index != maxState) { // Not at the end, erase everything from now til the end erase(begin() + (m_index + 1), end()); m_index++; @@ -45,7 +43,7 @@ SInt32 CDXUndoStack::Undo(bool doUpdate) SInt32 CDXUndoStack::Redo(bool doUpdate) { - SInt32 maxState = size() - 1; + SInt32 maxState = (SInt32)size() - 1; if(m_index < maxState) { m_index++; if(doUpdate) @@ -69,5 +67,3 @@ SInt32 CDXUndoStack::GoTo(SInt32 index, bool doUpdate) return result; } - -#endif \ No newline at end of file diff --git a/skee/CDXUndo.h b/skee/CDXUndo.h index c165a95..d233649 100644 --- a/skee/CDXUndo.h +++ b/skee/CDXUndo.h @@ -1,10 +1,10 @@ -#ifdef FIXME - #ifndef __CDXUNDO__ #define __CDXUNDO__ #pragma once +#include "CDXTypes.h" + #include #include @@ -52,5 +52,3 @@ class CDXUndoStack : public std::vector extern CDXUndoStack g_undoStack; #endif - -#endif \ No newline at end of file diff --git a/skee/FaceMorphInterface.cpp b/skee/FaceMorphInterface.cpp index 7015068..58b295c 100644 --- a/skee/FaceMorphInterface.cpp +++ b/skee/FaceMorphInterface.cpp @@ -427,7 +427,7 @@ SliderInternalPtr FaceMorphInterface::GetSliderByIndex(TESRace * race, UInt32 in return NULL; } -float ValueMap::GetMorphValueByName(TESNPC* npc, SKEEFixedString name) +float ValueMap::GetMorphValueByName(TESNPC* npc, const SKEEFixedString & name) { ValueMap::iterator it = find(npc); if(it != end()) { @@ -437,7 +437,7 @@ float ValueMap::GetMorphValueByName(TESNPC* npc, SKEEFixedString name) return 0.0; } -void ValueMap::SetMorphValue(TESNPC* npc, SKEEFixedString name, float value) +void ValueMap::SetMorphValue(TESNPC* npc, const SKEEFixedString & name, float value) { ValueMap::iterator it = find(npc); if(it != end()) { @@ -449,7 +449,7 @@ void ValueMap::SetMorphValue(TESNPC* npc, SKEEFixedString name, float value) } } -void ValueSet::SetValue(SKEEFixedString name, float value) +void ValueSet::SetValue(const SKEEFixedString & name, float value) { ValueSet::iterator val = find(g_stringTable.GetString(name)); if (val != end()) @@ -458,14 +458,14 @@ void ValueSet::SetValue(SKEEFixedString name, float value) emplace(g_stringTable.GetString(name), value); } -void ValueSet::ClearValue(SKEEFixedString name) +void ValueSet::ClearValue(const SKEEFixedString & name) { ValueSet::iterator val = find(g_stringTable.GetString(name)); if(val != end()) erase(val); } -float ValueSet::GetValue(SKEEFixedString name) +float ValueSet::GetValue(const SKEEFixedString & name) { ValueSet::iterator val = find(g_stringTable.GetString(name)); if(val != end()) @@ -491,12 +491,12 @@ void ValueMap::EraseNPC(TESNPC * npc) erase(it); } -float FaceMorphInterface::GetMorphValueByName(TESNPC* npc, SKEEFixedString name) +float FaceMorphInterface::GetMorphValueByName(TESNPC* npc, const SKEEFixedString & name) { return m_valueMap.GetMorphValueByName(npc, name); } -void FaceMorphInterface::SetMorphValue(TESNPC* npc, SKEEFixedString name, float value) +void FaceMorphInterface::SetMorphValue(TESNPC* npc, const SKEEFixedString & name, float value) { return m_valueMap.SetMorphValue(npc, name, value); } @@ -609,7 +609,7 @@ bool FaceMorphInterface::CacheHeadPartModel(BGSHeadPart * headPart, bool cacheTR return true; } -bool FaceMorphInterface::GetModelTri(SKEEFixedString filePath, TRIModelData & modelData) +bool FaceMorphInterface::GetModelTri(const SKEEFixedString & filePath, TRIModelData & modelData) { ModelMap::iterator it = m_modelMap.find(filePath); if (it != m_modelMap.end()) { @@ -620,11 +620,11 @@ bool FaceMorphInterface::GetModelTri(SKEEFixedString filePath, TRIModelData & mo return false; } -TRIModelData & FaceMorphInterface::GetExtendedModelTri(SKEEFixedString morphName, bool cacheTRI) +TRIModelData & FaceMorphInterface::GetExtendedModelTri(const SKEEFixedString & morphName, bool cacheTRI) { std::string filePath(SLIDER_DIRECTORY); filePath.append(morphName.c_str()); - SKEEFixedString morphFile(filePath.c_str()); + BSFixedString morphFile(filePath.c_str()); ModelMap::iterator it = m_modelMap.find(morphFile); if(it == m_modelMap.end()) { void* memory = Heap_Allocate(sizeof(TESModelTri)); @@ -877,7 +877,7 @@ void FaceMorphInterface::ApplyPresetData(Actor * actor, PresetDataPtr presetData g_bodyMorphInterface.UpdateModelWeight(actor); } -bool MorphMap::Visit(SKEEFixedString key, Visitor & visitor) +bool MorphMap::Visit(const SKEEFixedString & key, Visitor & visitor) { MorphMap::iterator it = find(key); if(it != end()) @@ -910,13 +910,13 @@ bool MorphMap::Visit(SKEEFixedString key, Visitor & visitor) -bool FaceMorphInterface::VisitMorphMap(SKEEFixedString key, MorphMap::Visitor & visitor) +bool FaceMorphInterface::VisitMorphMap(const SKEEFixedString & key, MorphMap::Visitor & visitor) { //key = toLower(key); return m_morphMap.Visit(key, visitor); } -void MorphMap::AddMorph(SKEEFixedString key, SKEEFixedString value) +void MorphMap::AddMorph(const SKEEFixedString & key, const SKEEFixedString & value) { //key = toLower(key); MorphMap::iterator it = find(key); @@ -940,7 +940,7 @@ void FaceMorphInterface::ReadMorphs(std::string fixedPath, std::string modName, UInt32 lineCount = 0; std::string str = ""; - while(BSReadLine(&file, &str)) + while(BSFileUtil::ReadLine(&file, &str)) { lineCount++; str = std::trim(str); @@ -978,7 +978,7 @@ void FaceMorphInterface::ReadMorphs(std::string fixedPath, std::string modName, #ifdef _DEBUG_DATAREADER _DMESSAGE("ReadMorphs Info - Line (%d) added %s morph to %s from %s.", lineCount, params[i].c_str(), key.c_str(), fullPath.c_str()); #endif - m_morphMap.AddMorph(SKEEFixedString(key.c_str()), SKEEFixedString(params[i].c_str())); + m_morphMap.AddMorph(key, params[i]); } } } @@ -995,7 +995,7 @@ void FaceMorphInterface::ReadRaces(std::string fixedPath, std::string modPath, s UInt32 lineCount = 0; std::string str = ""; - while(BSReadLine(&file, &str)) + while(BSFileUtil::ReadLine(&file, &str)) { lineCount++; str = std::trim(str); @@ -1051,7 +1051,7 @@ void FaceMorphInterface::ReadRaces(std::string fixedPath, std::string modPath, s } } -void SliderMap::AddSlider(SKEEFixedString key, UInt8 gender, SliderInternal & sliderInternal) +void SliderMap::AddSlider(const SKEEFixedString & key, UInt8 gender, SliderInternal & sliderInternal) { SliderMap::iterator it = find(key); if(it != end()) { @@ -1079,7 +1079,7 @@ SliderMapPtr FaceMorphInterface::ReadSliders(std::string fixedPath, std::string UInt8 gender = 0; UInt32 lineCount = 0; std::string str = ""; - while(BSReadLine(&file, &str)) + while(BSFileUtil::ReadLine(&file, &str)) { lineCount++; str = std::trim(str); @@ -1471,12 +1471,12 @@ void FaceMorphInterface::ApplyMorphs(TESNPC * npc, BSFaceGenNiNode * faceNode) } } -void FaceMorphInterface::SetMorph(TESNPC * npc, BSFaceGenNiNode * faceNode, const char * name, float relative) +void FaceMorphInterface::SetMorph(TESNPC * npc, BSFaceGenNiNode * faceNode, const SKEEFixedString & name, float relative) { #ifdef _DEBUG_MORPH _DMESSAGE("Applying Morph %s", name); #endif - BSFixedString morphName(name); + BSFixedString morphName(name.c_str()); FaceGenApplyMorph(FaceGen::GetSingleton(), faceNode, npc, &morphName, relative); } @@ -1588,6 +1588,9 @@ void FaceMorphInterface::Save(SKSESerializationInterface * intfc, UInt32 kVersio } intfc->WriteRecordData(&numValidParts, sizeof(numValidParts)); +#ifdef _DEBUG + _DMESSAGE("%s - Saving %d sculpts", __FUNCTION__, numValidParts); +#endif if (numValidParts > 0) { for (auto part : *sculptData) { UInt16 diffCount = part.second->size(); @@ -1596,6 +1599,10 @@ void FaceMorphInterface::Save(SKSESerializationInterface * intfc, UInt32 kVersio g_stringTable.WriteString(intfc, part.first); intfc->WriteRecordData(&diffCount, sizeof(diffCount)); +#ifdef _DEBUG + _DMESSAGE("%s - Saving sculpt to %s with %d diffs", __FUNCTION__, part.first->c_str(), diffCount); +#endif + for (auto diff : *part.second) { intfc->WriteRecordData(&diff.first, sizeof(diff.first)); intfc->WriteRecordData(&diff.second, sizeof(NiPoint3)); @@ -1618,18 +1625,24 @@ void FaceMorphInterface::Save(SKSESerializationInterface * intfc, UInt32 kVersio if (numMorphs > 0) { intfc->OpenRecord('MRST', kVersion); intfc->WriteRecordData(&numMorphs, sizeof(numMorphs)); +#ifdef _DEBUG + _DMESSAGE("%s - Saving %d morphs", __FUNCTION__, numMorphs); +#endif for (auto it = valueSet->begin(); it != valueSet->end(); ++it) { if (it->second != 0.0) { intfc->OpenRecord('MRPH', kVersion); g_stringTable.WriteString(intfc, it->first); intfc->WriteRecordData(&it->second, sizeof(it->second)); +#ifdef _DEBUG + _DMESSAGE("%s - Saving %s with %f", __FUNCTION__, it->first->c_str(), it->second); +#endif } } } } } -bool FaceMorphInterface::LoadMorphData(SKSESerializationInterface * intfc, UInt32 kVersion, const std::unordered_map & stringTable) +bool FaceMorphInterface::LoadMorphData(SKSESerializationInterface * intfc, UInt32 kVersion, const StringIdMap & stringTable) { UInt32 type; UInt32 length; @@ -1647,20 +1660,24 @@ bool FaceMorphInterface::LoadMorphData(SKSESerializationInterface * intfc, UInt3 return true; } +#ifdef _DEBUG + _DMESSAGE("%s - Loading %d morphs", __FUNCTION__, numMorphs); +#endif + for (UInt32 i = 0; i < numMorphs; i++) { StringTableItem sculptName; UInt32 index = 0; float value = 0.0; + UInt32 subVersion = 0; - if (intfc->GetNextRecordInfo(&type, &kVersion, &length)) + if (intfc->GetNextRecordInfo(&type, &subVersion, &length)) { switch (type) { case 'MRPH': { - - if (kVersion >= BodyMorphInterface::kSerializationVersion3) + if (kVersion >= FaceMorphInterface::kSerializationVersion2) { sculptName = StringTable::ReadString(intfc, stringTable); if (!sculptName) @@ -1670,7 +1687,7 @@ bool FaceMorphInterface::LoadMorphData(SKSESerializationInterface * intfc, UInt3 return true; } } - else if (kVersion >= BodyMorphInterface::kSerializationVersion2) + else if (kVersion >= FaceMorphInterface::kSerializationVersion1) { char * name = NULL; UInt16 nameLength = 0; @@ -1698,7 +1715,7 @@ bool FaceMorphInterface::LoadMorphData(SKSESerializationInterface * intfc, UInt3 } break; default: - _MESSAGE("unhandled type %08X", type); + _MESSAGE("%s - unhandled type %08X", __FUNCTION__, type); error = true; break; } @@ -1713,7 +1730,7 @@ bool FaceMorphInterface::LoadMorphData(SKSESerializationInterface * intfc, UInt3 return error; } -bool FaceMorphInterface::LoadSculptData(SKSESerializationInterface * intfc, UInt32 kVersion, const std::unordered_map & stringTable) +bool FaceMorphInterface::LoadSculptData(SKSESerializationInterface * intfc, UInt32 kVersion, const StringIdMap & stringTable) { UInt32 type; UInt32 length; @@ -1732,14 +1749,15 @@ bool FaceMorphInterface::LoadSculptData(SKSESerializationInterface * intfc, UInt for (UInt32 i = 0; i < numParts; i++) { - if (intfc->GetNextRecordInfo(&type, &kVersion, &length)) + UInt32 subVersion = 0; + if (intfc->GetNextRecordInfo(&type, &subVersion, &length)) { switch (type) { case 'SCPT': { StringTableItem sculptName; - if (kVersion >= BodyMorphInterface::kSerializationVersion3) + if (kVersion >= FaceMorphInterface::kSerializationVersion2) { sculptName = StringTable::ReadString(intfc, stringTable); if (!sculptName) @@ -1749,7 +1767,7 @@ bool FaceMorphInterface::LoadSculptData(SKSESerializationInterface * intfc, UInt return true; } } - else if (kVersion >= BodyMorphInterface::kSerializationVersion2) + else if (kVersion >= FaceMorphInterface::kSerializationVersion1) { UInt16 nameLength = 0; if (!intfc->ReadRecordData(&nameLength, sizeof(nameLength))) { @@ -1882,7 +1900,7 @@ bool FaceMorphInterface::SaveJsonPreset(const char * filePath) if (headPart && !headPart->IsExtraPart()) { ModInfo * modInfo = GetModInfoByFormID(headPart->formID, false); if (modInfo) { - modListLegacy.emplace(modInfo->modIndex, modInfo->name); + modListLegacy.emplace(modInfo->GetPartialIndex(), modInfo->name); } partList.emplace(i, headPart); @@ -2415,7 +2433,7 @@ bool FaceMorphInterface::LoadJsonPreset(const char * filePath, PresetDataPtr pre } std::string in; - BSReadAll(&file, &in); + BSFileUtil::ReadAll(&file, in); Json::Features features; features.all(); @@ -2499,11 +2517,11 @@ bool FaceMorphInterface::LoadJsonPreset(const char * filePath, PresetDataPtr pre UInt32 formId = part["formId"].asUInt(); UInt32 modIndex = formId >> 24; - auto it = modList.find(modIndex); + auto it = modList.find(modIndex != 0xFE ? modIndex : (formId >> 12)); if (it != modList.end()) { - UInt8 gameIndex = dataHandler->GetLoadedModIndex(it->second.c_str()); - if (gameIndex != 255) { - formId = (formId & 0x00FFFFFF) | (gameIndex << 24); + const ModInfo * modInfo = dataHandler->LookupModByName(it->second.c_str()); + if (modInfo && modInfo->IsActive()) { + formId = modInfo->GetFormID(formId); TESForm * headPartForm = LookupFormByID(formId); if (headPartForm) { BGSHeadPart * headPart = DYNAMIC_CAST(headPartForm, TESForm, BGSHeadPart); @@ -2737,14 +2755,10 @@ bool FaceMorphInterface::LoadJsonPreset(const char * filePath, PresetDataPtr pre // If the keys were mapped by mod name, skip them if they arent in load order std::string strKey(key); SKEEFixedString ext(strKey.substr(strKey.find_last_of(".") + 1).c_str()); - if (ext == SKEEFixedString("esp") || ext == SKEEFixedString("esm")) - { - if (!dataHandler->LookupLoadedModByName(key.c_str())) - continue; - } - else if (ext == SKEEFixedString("esl")) + if (ext == SKEEFixedString("esp") || ext == SKEEFixedString("esm") || ext == SKEEFixedString("esl")) { - if (!dataHandler->LookupLoadedLightModByName(key.c_str())) + const ModInfo * modInfo = dataHandler->LookupModByName(key.c_str()); + if (!modInfo || !modInfo->IsActive()) continue; } @@ -2830,12 +2844,12 @@ bool FaceMorphInterface::LoadBinaryPreset(const char * filePath, PresetDataPtr p UInt32 formId = 0; file.Read(&formId, sizeof(formId)); - UInt8 modIndex = formId >> 24; - auto it = modList.find(modIndex); - if(it != modList.end()) { - UInt8 gameIndex = dataHandler->GetLoadedModIndex(it->second.c_str()); - if(gameIndex != 255) { - formId = (formId & 0x00FFFFFF) | (gameIndex << 24); + UInt32 modIndex = formId >> 24; + auto it = modList.find(modIndex != 0xFE ? modIndex : (formId >> 12)); + if (it != modList.end()) { + const ModInfo * modInfo = dataHandler->LookupModByName(it->second.c_str()); + if (modInfo && modInfo->IsActive()) { + formId = modInfo->GetFormID(formId); TESForm * headPartForm = LookupFormByID(formId); if(headPartForm) { BGSHeadPart * headPart = DYNAMIC_CAST(headPartForm, TESForm, BGSHeadPart); diff --git a/skee/FaceMorphInterface.h b/skee/FaceMorphInterface.h index fc25c82..3836d2f 100644 --- a/skee/FaceMorphInterface.h +++ b/skee/FaceMorphInterface.h @@ -120,11 +120,11 @@ class MorphMap : public std::map class Visitor { public: - virtual bool Accept(SKEEFixedString morphName) { return false; }; + virtual bool Accept(const SKEEFixedString & morphName) { return false; }; }; - void AddMorph(SKEEFixedString key, SKEEFixedString value); - bool Visit(SKEEFixedString key, Visitor & visitor); + void AddMorph(const SKEEFixedString & key, const SKEEFixedString & value); + bool Visit(const SKEEFixedString & key, Visitor & visitor); void Revert(); #ifdef _DEBUG_DATADUMP @@ -146,7 +146,7 @@ class SliderMap : public std::unordered_map public: SliderMap::SliderMap() : std::unordered_map(){ } - void AddSlider(SKEEFixedString key, UInt8 gender, SliderInternal & slider); + void AddSlider(const SKEEFixedString & key, UInt8 gender, SliderInternal & slider); #ifdef _DEBUG_DATADUMP void DumpMap(); @@ -181,9 +181,9 @@ class RaceMap : public std::unordered_map class ValueSet : public std::unordered_map { public: - void SetValue(SKEEFixedString name, float value); - void ClearValue(SKEEFixedString name); - float GetValue(SKEEFixedString name); + void SetValue(const SKEEFixedString & name, float value); + void ClearValue(const SKEEFixedString & name); + float GetValue(const SKEEFixedString & name); }; class ValueMap : public std::unordered_map @@ -192,8 +192,8 @@ class ValueMap : public std::unordered_map ValueSet * GetValueSet(TESNPC* npc); void EraseNPC(TESNPC * npc); - float GetMorphValueByName(TESNPC* npc, SKEEFixedString name); - void SetMorphValue(TESNPC* npc, SKEEFixedString name, float value); + float GetMorphValueByName(TESNPC* npc, const SKEEFixedString & name); + void SetMorphValue(TESNPC* npc, const SKEEFixedString & name, float value); }; #define VERTEX_THRESHOLD 0.00001 @@ -354,10 +354,10 @@ class FaceMorphInterface : public IPluginInterface void LoadMods(); - virtual float GetMorphValueByName(TESNPC* npc, SKEEFixedString name); - virtual void SetMorphValue(TESNPC* npc, SKEEFixedString name, float value); + virtual float GetMorphValueByName(TESNPC* npc, const SKEEFixedString & name); + virtual void SetMorphValue(TESNPC* npc, const SKEEFixedString & name, float value); - void SetMorph(TESNPC * npc, BSFaceGenNiNode * faceNode, const char * name, float relative); + void SetMorph(TESNPC * npc, BSFaceGenNiNode * faceNode, const SKEEFixedString & name, float relative); void ApplyMorph(TESNPC * npc, BGSHeadPart * headPart, BSFaceGenNiNode * faceNode); void ApplyMorphs(TESNPC * npc, BSFaceGenNiNode * faceNode); @@ -374,11 +374,11 @@ class FaceMorphInterface : public IPluginInterface SliderList * CreateSliderList(TESRace * race, UInt8 gender); void AddSlider(TESRace * race, SliderInternalPtr & slider); - bool VisitMorphMap(SKEEFixedString key, MorphMap::Visitor & visitor); + bool VisitMorphMap(const SKEEFixedString & key, MorphMap::Visitor & visitor); bool CacheHeadPartModel(BGSHeadPart * headPart, bool cacheTRI = false); - bool GetModelTri(SKEEFixedString filePath, TRIModelData & modelData); - TRIModelData & GetExtendedModelTri(SKEEFixedString morphName, bool cacheTRI = false); + bool GetModelTri(const SKEEFixedString & filePath, TRIModelData & modelData); + TRIModelData & GetExtendedModelTri(const SKEEFixedString & morphName, bool cacheTRI = false); inline SculptDataPtr GetSculptTarget(TESNPC * npc, bool create = true) { diff --git a/skee/FileUtils.cpp b/skee/FileUtils.cpp index 2617fff..0c15b21 100644 --- a/skee/FileUtils.cpp +++ b/skee/FileUtils.cpp @@ -49,7 +49,9 @@ namespace std } } -bool BSReadLine(BSResourceNiBinaryStream* fin, std::string* str) +namespace BSFileUtil +{ +bool ReadLine(BSResourceNiBinaryStream* fin, std::string* str) { char buf[1024]; UInt32 ret = 0; @@ -62,15 +64,6 @@ bool BSReadLine(BSResourceNiBinaryStream* fin, std::string* str) } return false; } - -void BSReadAll(BSResourceNiBinaryStream* fin, std::string* str) -{ - char ch; - UInt32 ret = fin->Read(&ch, 1); - while (ret > 0) { - str->push_back(ch); - ret = fin->Read(&ch, 1); - } } TESRace * GetRaceByName(std::string & raceName) @@ -170,19 +163,12 @@ TESForm * GetFormFromIdentifier(const std::string & formIdentifier) UInt32 formId = 0; sscanf_s(modForm.c_str(), "%X", &formId); - UInt8 modIndex = (*g_dataHandler)->GetLoadedModIndex(modName.c_str()); - if (modIndex != 0xFF) { - formId |= ((UInt32)modIndex) << 24; - } - else - { - UInt16 lightModIndex = (*g_dataHandler)->GetLoadedLightModIndex(modName.c_str()); - if (lightModIndex != 0xFFFF) { - formId |= 0xFE000000 | (UInt32(lightModIndex) << 12); - } + const ModInfo * modInfo = (*g_dataHandler)->LookupModByName(modName.c_str()); + if (!modInfo || !modInfo->IsActive()) { + return nullptr; } - return LookupFormByID(formId); + return LookupFormByID(modInfo->GetFormID(formId)); } void VisitLeveledCharacter(TESLevCharacter * character, std::function functor) diff --git a/skee/FileUtils.h b/skee/FileUtils.h index 0852966..8f354ee 100644 --- a/skee/FileUtils.h +++ b/skee/FileUtils.h @@ -23,9 +23,20 @@ namespace std { std::vector explode(const std::string& str, const char& ch); } +namespace BSFileUtil { + bool ReadLine(BSResourceNiBinaryStream* fin, std::string * str); -bool BSReadLine(BSResourceNiBinaryStream* fin, std::string* str); -void BSReadAll(BSResourceNiBinaryStream* fin, std::string* str); + template + void ReadAll(BSResourceNiBinaryStream* fin, Container & c) + { + char ch; + UInt32 ret = fin->Read(&ch, 1); + while (ret > 0) { + c.push_back(ch); + ret = fin->Read(&ch, 1); + } + } +} TESRace * GetRaceByName(std::string & raceName); BGSHeadPart * GetHeadPartByName(std::string & headPartName); diff --git a/skee/Hooks_chargen.cpp b/skee/Hooks_chargen.cpp deleted file mode 100644 index 6359025..0000000 --- a/skee/Hooks_chargen.cpp +++ /dev/null @@ -1,1118 +0,0 @@ -#include "Hooks.h" -#include "MorphHandler.h" -#include "PartHandler.h" - -#include "skse/SafeWrite.h" -#include "skse/NiObjects.h" -#include "skse/GameData.h" -#include "skse/GameRTTI.h" - -#include "common/IFileStream.h" -#include "skse/GameStreams.h" -#include "skse/HashUtil.h" - -#include "skse/NiGeometry.h" - -#include - -bool CacheTempTRI(UInt32 hash, const char * originalPath); - -extern MorphHandler g_morphHandler; -extern PartSet g_partSet; -extern UInt32 g_customDataMax; -extern bool g_externalHeads; -extern bool g_extendedMorphs; -extern bool g_allowAllMorphs; - -static const UInt32 kInstallRegenHeadHook_Base = 0x005A4B80 + 0x49B; -static const UInt32 kInstallRegenHeadHook_Entry_retn = kInstallRegenHeadHook_Base + 0x8; - -enum -{ - kRegenHeadHook_EntryStackOffset1 = 0x20, - kRegenHeadHook_EntryStackOffset2 = 0xA8, - - kRegenHeadHook_VarHeadPart = 0x08, - kRegenHeadHook_VarFaceGenNode = 0x04, - kRegenHeadHook_VarNPC = 0x0C -}; - -void __stdcall ApplyPreset(TESNPC * npc, BSFaceGenNiNode * headNode, BGSHeadPart * headPart) -{ - g_morphHandler.ApplyPreset(npc, headNode, headPart); -} - -__declspec(naked) void InstallRegenHeadHook_Entry(void) -{ - __asm - { - pushad - mov eax, [esp + kRegenHeadHook_EntryStackOffset1 + kRegenHeadHook_EntryStackOffset2 + kRegenHeadHook_VarHeadPart] - push eax - mov eax, [esp + kRegenHeadHook_EntryStackOffset1 + kRegenHeadHook_EntryStackOffset2 + kRegenHeadHook_VarFaceGenNode + 0x04] - push eax - mov eax, [esp + kRegenHeadHook_EntryStackOffset1 + kRegenHeadHook_EntryStackOffset2 + kRegenHeadHook_VarNPC + 0x08] - push eax - call ApplyPreset - popad - - pop edi - pop ebx - add esp, 0xA0 - jmp[kInstallRegenHeadHook_Entry_retn] - } -} - -static const UInt32 kInstallForceRegenHeadHook_Base = 0x0056AEB0 + 0x35; -static const UInt32 kInstallForceRegenHeadHook_Entry_retn = kInstallForceRegenHeadHook_Base + 0x7; // Standard execution - -enum -{ - kForceRegenHeadHook_EntryStackOffset = 0x10, -}; - -bool * g_useFaceGenPreProcessedHeads = (bool*)0x0125D280; - -bool __stdcall IsHeadGenerated(TESNPC * npc) -{ - // For some reason the NPC vanilla preset data is reset when the actor is disable/enabled - auto presetData = g_morphHandler.GetPreset(npc); - if (presetData) { - if (!npc->faceMorph) - npc->faceMorph = (TESNPC::FaceMorphs*)FormHeap_Allocate(sizeof(TESNPC::FaceMorphs)); - - UInt32 i = 0; - for (auto & preset : presetData->presets) { - npc->faceMorph->presets[i] = preset; - i++; - } - - i = 0; - for (auto & morph : presetData->morphs) { - npc->faceMorph->option[i] = morph; - i++; - } - } - return (presetData != NULL) || !(*g_useFaceGenPreProcessedHeads); -} - -__declspec(naked) void InstallForceRegenHeadHook_Entry(void) -{ - __asm - { - push esi - call IsHeadGenerated - cmp al, 1 - jmp[kInstallForceRegenHeadHook_Entry_retn] - } -} - -typedef void(*_LoadActorValues)(); -const _LoadActorValues LoadActorValues = (_LoadActorValues)0x00692FA0; - -#ifdef USE_TRICACHE -void RemoveCachedTRIFiles() -{ - std::vector files; - WIN32_FIND_DATA findFileData; - - std::string cacheDirectory("Data\\meshes\\"); - cacheDirectory.append(MORPH_CACHE_PATH); - std::string findDirectory = cacheDirectory; - findDirectory.append("*"); - - HANDLE hFindFile = FindFirstFile(findDirectory.c_str(), &findFileData); - if (hFindFile) - { - do - { - std::string filePath = findFileData.cFileName; - if (_strnicmp(filePath.substr(filePath.find_last_of(".") + 1).c_str(), "tri", 3) == 0) { - files.push_back(filePath); - } - } while (FindNextFile(hFindFile, &findFileData)); - FindClose(hFindFile); - } - - for (std::vector::iterator it = files.begin(); it != files.end(); ++it) - { - std::string filePath = cacheDirectory; - filePath.append(*it); - _DMESSAGE("Removing cached tri - %s", filePath.c_str()); - DeleteFile(filePath.c_str()); - } -} -#endif - -class ExtendedMorphCache : public MorphMap::Visitor -{ -public: - virtual bool Accept(BSFixedString morphName) - { - g_morphHandler.GetExtendedModelTri(morphName); - return false; - } -}; - -SInt32 GetGameSettingInt(const char * key) -{ - Setting * setting = (*g_gameSettingCollection)->Get(key); - if (setting && setting->GetType() == Setting::kType_Integer) - return setting->data.s32; - - return 0; -} - -void _cdecl LoadActorValues_Hook() -{ - LoadActorValues(); - -#ifdef USE_TRICACHE - RemoveCachedTRIFiles(); -#endif - - DataHandler * dataHandler = DataHandler::GetSingleton(); - if (dataHandler) - { - UInt8 modCount = dataHandler->modList.loadedModCount; - for (UInt32 i = 0; i < modCount; i++) - { - ModInfo * modInfo = dataHandler->modList.loadedMods[i]; - std::string fixedPath = "Meshes\\"; - fixedPath.append(SLIDER_MOD_DIRECTORY); - std::string modPath = modInfo->name; - modPath.append("\\"); - - g_morphHandler.ReadRaces(fixedPath, modPath, "races.ini"); - if (g_extendedMorphs) - g_morphHandler.ReadMorphs(fixedPath, modPath, "morphs.ini"); - - ReadPartReplacements(fixedPath, modPath, "replacements.ini"); - } - - - /*for(MorphMap::iterator it = g_morphHandler.m_morphMap.begin(); it != g_morphHandler.m_morphMap.end(); ++it) - { - std::string beginLine = "extension = "; - beginLine.append(it->first.data); - for(MorphSet::iterator sit = it->second.begin(); sit != it->second.end(); ++sit) - { - beginLine.append(", "); - beginLine.append(sit->data); - } - _MESSAGE("%s", beginLine.c_str()); - }*/ - - if (g_extendedMorphs) { - BGSHeadPart * part = NULL; - for (UInt32 i = 0; i < dataHandler->headParts.count; i++) - { - if (dataHandler->headParts.GetNthItem(i, part)) { - if (g_morphHandler.CacheHeadPartModel(part)) { - - BSFixedString key = part->chargenMorph.GetModelName(); - - // Cache all of the extended morphs - ExtendedMorphCache extendedCache; - g_morphHandler.VisitMorphMap(key, extendedCache); - } - } - } - } - - // Create default slider maps - TESRace * race = NULL; - for (UInt32 i = 0; i < dataHandler->races.count; i++) - { - if (dataHandler->races.GetNthItem(i, race)) { - - if (g_allowAllMorphs) { - for (UInt32 i = 0; i <= 1; i++) { - if (race->chargenData[i]) { - for (UInt32 t = 0; t < FacePresetList::kNumPresets; t++) { - const char * gameSetting = FacePresetList::GetSingleton()->presets[t].data->gameSettingName; - race->chargenData[i]->presetFlags[t][0] = 0xFFFFFFFF; - race->chargenData[i]->presetFlags[t][1] = 0xFFFFFFFF; - race->chargenData[i]->totalPresets[t] = GetGameSettingInt(gameSetting); - } - } - } - } - if ((race->data.raceFlags & TESRace::kRace_FaceGenHead) == TESRace::kRace_FaceGenHead) - g_morphHandler.m_raceMap.CreateDefaultMap(race); - } - } - /* - std::set uniqueTris; - for (UInt32 i = 0; i < dataHandler->headParts.count; i++) - { - BGSHeadPart * headPart = NULL; - if (dataHandler->headParts.GetNthItem(i, headPart)) { - BSFixedString chargenPath(headPart->chargenMorph.GetModelName()); - if (chargenPath == BSFixedString("")) - continue; - uniqueTris.insert(chargenPath); - } - } - - for (auto tri : uniqueTris) - { - std::string lowerStr(tri.data); - std::transform(lowerStr.begin(), lowerStr.end(), lowerStr.begin(), ::tolower); - UInt32 hash = HashUtil::CRC32(lowerStr.c_str()); - - char buffer[0x20]; - memset(buffer, 0, 0x20); - sprintf_s(buffer, 0x20, MORPH_CACHE_TEMPLATE, hash); - - std::string path(MORPH_CACHE_DIR); - path.append(buffer); - BSFixedString cachePath(path.c_str()); - - //CacheTempTRI(hash, tri.data); - - g_morphHandler.m_morphMap.AddMorph(tri, cachePath); - }*/ - } -} - -typedef void(*_ClearFaceGenCache)(); -const _ClearFaceGenCache ClearFaceGenCache = (_ClearFaceGenCache)0x00886B50; - -void _cdecl ClearFaceGenCache_Hooked() -{ - ClearFaceGenCache(); - - g_morphHandler.RevertInternals(); - g_partSet.Revert(); // Cleanup HeadPart List before loading new ones -} - -bool _cdecl CacheTRIFile_Hook(const char * filePath, BSFaceGenDB::TRI::DBTraits::MorphSet ** morphSet, UInt32 * unk1) -{ -#ifdef _DEBUG_HOOK - //_MESSAGE("Caching TRI: '%s'", filePath); -#endif - - bool ret = CacheTRIFile(filePath, morphSet, unk1); -#ifdef __DEBUG - _MESSAGE("External Cache - %s - %s - MorphSet: %08X", ret ? "Failed" : "Succeeded", filePath, morphSet); -#endif - // Add additional morphs here based on morph path instead - -#ifdef __DEBUG - BSFaceGenDB::TRI::DBTraits::MorphSet * foundSet = *morphSet; - if (foundSet) - { - BSFaceGenDB::TRI::DBTraits::MorphData morphEntry; - - _MESSAGE("Set - %s MorphCount: %d Capacity: %d", foundSet->fileName, foundSet->morphData.count, foundSet->morphData.arr.capacity); - - gLog.Indent(); - for (UInt32 n = 0; n < foundSet->morphData.count; n++) { - BSFaceGenDB::TRI::DBTraits::MorphData morphEntry; - if (foundSet->morphData.GetNthItem(n, morphEntry)) { - _MESSAGE("Morph %d - %s baseDiff: %f DiffVertNum: %d BaseVertNum: %d DiffVertPosNum: %d\t\t04 : %d\t0C : %d\t10 : %d", n, morphEntry.morphName, morphEntry.baseDiff, morphEntry.diffVertexNum, morphEntry.baseVertexNum, morphEntry.diffVertexPosNum, morphEntry.unk04, morphEntry.unk0C, morphEntry.unk10); - // for(UInt32 i = 0; i < morphEntry.baseVertexNum; i++) - // { - // _MESSAGE("Vertex %d - X: %d Y: %d Z: %d \t\t Floating Point - X: %f Y: %f Z: %f", i, morphEntry.diffData[i].x, morphEntry.diffData[i].y, morphEntry.diffData[i].z, morphEntry.diffData[i].x * morphEntry.baseDiff, morphEntry.diffData[i].y * morphEntry.baseDiff, morphEntry.diffData[i].z * morphEntry.baseDiff); - // } - } - } - gLog.Outdent(); - } -#endif - -#ifdef USE_TRICACHE - std::string pathStr(filePath); - std::transform(pathStr.begin(), pathStr.end(), pathStr.begin(), ::tolower); - if (pathStr.compare(0, sizeof(MORPH_CACHE_PATH)-1, MORPH_CACHE_PATH) == 0) { - pathStr.erase(0, sizeof(MORPH_CACHE_PATH)-1); - UInt32 hash = 0; - sscanf_s(pathStr.c_str(), "%08X.tri", &hash); - auto morphData = g_morphHandler.GetSculptFromHost(hash); - if (morphData) { - BSFaceGenDB::TRI::DBTraits::MorphSet * foundSet = *morphSet; - if (foundSet) { - g_morphHandler.WriteMorphsToDatabase(morphData, foundSet); - } - } - } -#endif - - return ret; -} - -void TESNPC_Hooked::UpdateMorphs_Hooked(void * unk1, BSFaceGenNiNode * faceNode) -{ - CALL_MEMBER_FN(this, UpdateMorphs)(unk1, faceNode); -#ifdef _DEBUG_HOOK - _DMESSAGE("UpdateMorphs_Hooked - Applying custom morphs"); -#endif - try - { - g_morphHandler.ApplyMorphs(this, faceNode); - } - catch (...) - { - _DMESSAGE("%s - Fatal error", __FUNCTION__); - } -} - -void TESNPC_Hooked::UpdateMorph_Hooked(BGSHeadPart * headPart, BSFaceGenNiNode * faceNode) -{ - CALL_MEMBER_FN(this, UpdateMorph)(headPart, faceNode); -#ifdef _DEBUG_HOOK - _DMESSAGE("UpdateMorph_Hooked - Applying single custom morph"); -#endif - try - { - g_morphHandler.ApplyMorph(this, headPart, faceNode); - } - catch (...) - { - _DMESSAGE("%s - Fatal error", __FUNCTION__); - } -} - -void FxResponseArgsList_Hooked::AddArgument_Hooked(GFxValue * value) -{ - CALL_MEMBER_FN(this, AddArgument)(value); -#ifdef _DEBUG_HOOK - _DMESSAGE("AddArgument_Hooked - Loading Category..."); -#endif - GFxValue arg; - arg.SetString("$EXTRA"); - CALL_MEMBER_FN(this, AddArgument)(&arg); - arg.SetNumber(SLIDER_CATEGORY_EXTRA); - CALL_MEMBER_FN(this, AddArgument)(&arg); - - arg.SetString("$EXPRESSIONS"); - CALL_MEMBER_FN(this, AddArgument)(&arg); - arg.SetNumber(SLIDER_CATEGORY_EXPRESSIONS); - CALL_MEMBER_FN(this, AddArgument)(&arg); -#ifdef _DEBUG_HOOK - _DMESSAGE("AddArgument_Hooked - Loaded Category."); -#endif -} - -UInt32 SliderArray::AddSlider_Hooked(RaceMenuSlider * slider) -{ - UInt32 ret = CALL_MEMBER_FN(this, AddSlider)(slider); -#ifdef _DEBUG_HOOK - _DMESSAGE("AddSlider_Hooked - Loading Sliders..."); -#endif - g_morphHandler.LoadSliders(this, slider); -#ifdef _DEBUG_HOOK - _DMESSAGE("AddSlider_Hooked - Loaded Sliders."); -#endif - return ret; -} - -/*UInt32 RaceSexMenu_Hooked::OpenMenu_Hooked(UInt32 unk1) -{ - UInt32 ret = CALL_MEMBER_FN(this, OpenMenu)(unk1); - - return ret; -}*/ - -#ifdef _DEBUG_HOOK -class DumpPartVisitor : public PartSet::Visitor -{ -public: - bool Accept(UInt32 key, BGSHeadPart * headPart) - { - _DMESSAGE("DumpPartVisitor - Key: %d Part: %s", key, headPart->partName.data); - return false; - } -}; -#endif - -void DataHandler_Hooked::GetValidPlayableHeadParts_Hooked(UInt32 unk1, void * unk2) -{ -#ifdef _DEBUG_HOOK - _DMESSAGE("Reverting Parts:"); - DumpPartVisitor dumpVisitor; - g_partSet.Visit(dumpVisitor); -#endif - - g_partSet.Revert(); // Cleanup HeadPart List before loading new ones - - CALL_MEMBER_FN(this, GetValidPlayableHeadParts)(unk1, unk2); -} - -// Pre-filtered by ValidRace and Gender -UInt8 BGSHeadPart_Hooked::IsPlayablePart_Hooked() -{ - UInt8 ret = CALL_MEMBER_FN(this, IsPlayablePart)(); - -#ifdef _DEBUG_HOOK - _DMESSAGE("IsPlayablePart_Hooked - Reading Part: %08X : %s", this->formID, this->partName.data); -#endif - - if(this->type >= BGSHeadPart::kNumTypes) { - if((this->partFlags & BGSHeadPart::kFlagExtraPart) == 0) { // Skip Extra Parts - if(strcmp(this->model.GetModelName(), "") == 0) - g_partSet.SetDefaultPart(this->type, this); - else - g_partSet.AddPart(this->type, this); - } - return false; // Prevents hanging if the HeadPart is marked as Playable - } - else if ((this->partFlags & BGSHeadPart::kFlagExtraPart) == 0 && ret) - { - // Sets the default part of this type - if (g_partSet.GetDefaultPart(this->type) == NULL) { - auto playeRace = (*g_thePlayer)->race; - if (playeRace) { - TESNPC * npc = DYNAMIC_CAST((*g_thePlayer)->baseForm, TESForm, TESNPC); - UInt8 gender = CALL_MEMBER_FN(npc, GetSex)(); - - auto chargenData = playeRace->chargenData[gender]; - if (chargenData) { - auto headParts = chargenData->headParts; - if (headParts) { - for (UInt32 i = 0; i < headParts->count; i++) { - BGSHeadPart * part; - headParts->GetNthItem(i, part); - if (part->type == this->type) - g_partSet.SetDefaultPart(part->type, part); - } - } - } - } - } - - // maps the pre-existing part to this type - g_partSet.AddPart(this->type, this); - } - - return ret; -} - -#ifdef _DEBUG -#pragma warning (push) -#pragma warning (disable : 4200) -struct RTTIType -{ - void * typeInfo; - UInt32 pad; - char name[0]; -}; - -struct RTTILocator -{ - UInt32 sig, offset, cdOffset; - RTTIType * type; -}; -#pragma warning (pop) - -const char * GetObjectClassName(void * objBase) -{ - const char * result = ""; - - __try - { - void ** obj = (void **)objBase; - RTTILocator ** vtbl = (RTTILocator **)obj[0]; - RTTILocator * rtti = vtbl[-1]; - RTTIType * type = rtti->type; - - // starts with ,? - if((type->name[0] == '.') && (type->name[1] == '?')) - { - // is at most 100 chars long - for(UInt32 i = 0; i < 100; i++) - { - if(type->name[i] == 0) - { - // remove the .?AV - result = type->name + 4; - break; - } - } - } - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - // return the default - } - - return result; -} - -void DumpClass(void * theClassPtr, UInt32 nIntsToDump) -{ - UInt32* basePtr = (UInt32*)theClassPtr; - _DMESSAGE("DumpClass: %X", basePtr); - - gLog.Indent(); - - if (!theClassPtr) return; - for (UInt32 ix = 0; ix < nIntsToDump; ix++ ) { - UInt32* curPtr = basePtr+ix; - const char* curPtrName = NULL; - UInt32 otherPtr = 0; - float otherFloat = 0.0; - const char* otherPtrName = NULL; - if (curPtr) { - curPtrName = GetObjectClassName((void*)curPtr); - - __try - { - otherPtr = *curPtr; - otherFloat = *(float*)(curPtr); - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - // - } - - if (otherPtr) { - otherPtrName = GetObjectClassName((void*)otherPtr); - } - } - - _DMESSAGE("%3d +%03X ptr: 0x%08X: %32s *ptr: 0x%08x | %f: %32s", ix, ix*4, curPtr, curPtrName, otherPtr, otherFloat, otherPtrName); - } - - gLog.Outdent(); -} -#endif - -class MorphVisitor : public MorphMap::Visitor -{ -public: - MorphVisitor::MorphVisitor(BSFaceGenModel * model, const char ** morphName, NiAVObject ** headNode, float relative, UInt8 unk1) - { - m_model = model; - m_morphName = morphName; - m_headNode = headNode; - m_relative = relative; - m_unk1 = unk1; - } - bool Accept(BSFixedString morphName) - { - TRIModelData & morphData = g_morphHandler.GetExtendedModelTri(morphName, true); - if (morphData.morphModel && morphData.triFile) { - NiGeometry * geometry = NULL; - if (m_headNode && (*m_headNode)) - geometry = (*m_headNode)->GetAsNiGeometry(); - - if (geometry) - morphData.triFile->Apply(geometry, *m_morphName, m_relative); - } - //UInt8 ret = CALL_MEMBER_FN(m_model, ApplyMorph)(m_morphName, morphData.morphModel, m_headNode, m_relative, m_unk1); - - /*BSFaceGenDB::TRI::DBTraits::MorphSet * mset = NULL; - UInt32 unk1 = 0; - if (CacheTRIFile_Hook(newMorph->GetModelName(), &mset, &unk1) == 0) { - if (!mset) // Why? - return false; - - auto modelObj = m_model->unk08; - if (modelObj) { - auto morphData = modelObj->unk10; - if (morphData != mset->faceMorphData) { - if (morphData) - morphData->DecRef(); - - modelObj->unk10 = mset->faceMorphData; - if (modelObj->unk10) - modelObj->unk10->IncRef(); - } - morphData = modelObj->unk10; - if (modelObj) { - NiGeometry * geometry = (*m_headNode)->GetAsNiGeometry(); - NiGeometryData * geometryData = niptr_cast(geometry->m_spModelData); - if (geometryData) { - NiGeometryData::Data0 data; - data.unk00 = 0; - data.unk04 = 0; - data.unk08 = 0; - if (CALL_MEMBER_FN(geometryData, Unk1)(1) && CALL_MEMBER_FN(geometryData, Unk2)(&data)) { - CALL_MEMBER_FN(morphData, ApplyMorph)(m_morphName, geometry, m_relative, m_unk1); - CALL_MEMBER_FN(geometryData, Unk3)(1); - } - } - } - } - }*/ - - - return false; - } -private: - BSFaceGenModel * m_model; - const char ** m_morphName; - NiAVObject ** m_headNode; - float m_relative; - UInt8 m_unk1; -}; - -UInt8 BSFaceGenModel_Hooked::ApplyRaceMorph_Hooked(const char ** morphName, TESModelTri * modelMorph, NiAVObject ** headNode, float relative, UInt8 unk1) -{ - //BGSHeadPart * headPart = (BGSHeadPart *)((UInt32)modelMorph - offsetof(BGSHeadPart, raceMorph)); - UInt8 ret = CALL_MEMBER_FN(this, ApplyMorph)(morphName, modelMorph, headNode, relative, unk1); -#ifdef _DEBUG - //_MESSAGE("%08X - Applying %s from %s : %s", this, morphName[0], modelMorph->name.data, headPart->partName.data); -#endif - - try - { - MorphVisitor morphVisitor(this, morphName, headNode, relative, unk1); - g_morphHandler.VisitMorphMap(modelMorph->GetModelName(), morphVisitor); - } - catch (...) - { - _ERROR("%s - fatal error while applying morph (%s)", __FUNCTION__, *morphName); - } - - - - return ret; -} - -#ifdef USE_TRICACHE -// Writes a CustomMorph file for overwriting -bool CacheTempTRI(UInt32 hash, const char * originalPath) -{ - if(originalPath[0] == 0 || hash == 0) { - _ERROR("%s - Invalid hash or path", __FUNCTION__); - return true; - } - - std::string path("meshes\\"); - path.append(MORPH_CACHE_PATH); - - char pathBuffer[MAX_PATH]; - memset(pathBuffer, 0, 0x20); - sprintf_s(pathBuffer, 0x20, "%08X.tri", hash); - path.append(pathBuffer); - - BSFixedString newPath(path.c_str()); - - // Cached file already exists, load it - BSResourceNiBinaryStream cached(newPath.data); - if (cached.IsValid()) { -#ifdef _DEBUG - //_DMESSAGE("%s - Loaded cached TRI %s", __FUNCTION__, newPath.data); -#endif - return false; - } - - memset(pathBuffer, 0, MAX_PATH); - sprintf_s(pathBuffer, MAX_PATH, "meshes\\%s", originalPath); - BSFixedString originalFile(pathBuffer); - - memset(pathBuffer, 0, MAX_PATH); - sprintf_s(pathBuffer, MAX_PATH, "Data\\%s", newPath.data); - BSFixedString fullPath(pathBuffer); - - // Load up original file - BSResourceNiBinaryStream file(originalFile.data); - if (!file.IsValid()) { - _ERROR("%s - Couldn't open morph for reading: %s", __FUNCTION__, originalFile.data); - return true; - } - - IFileStream currentFile; - IFileStream::MakeAllDirs(fullPath.data); - - if(!currentFile.Create(fullPath.data)) - { - _ERROR("%s - Couldn't open morph for writing: %s", __FUNCTION__, fullPath.data); - return true; - } - try - { - char buffer[MAX_PATH]; - memset(buffer, 0, MAX_PATH); - - _DMESSAGE("%s - Writing from %s to %s", __FUNCTION__, originalFile.data, fullPath.data); - - UInt32 vertexNum = 0, faceNum = 0, UVNum = 0, morphNum = 0; - UInt32 baseNum = 0; - - // Header - file.Read(buffer, 0x08); - currentFile.WriteBuf(buffer, 0x08); - - // Vertices - file.Read(&vertexNum, sizeof(vertexNum)); - currentFile.Write32(vertexNum); - - // Faces - file.Read(&faceNum, sizeof(faceNum)); - currentFile.Write32(faceNum); - - // Polyquads, unknown 2, 3 - file.Read(buffer, 0x0C); - currentFile.WriteBuf(buffer, 0x0C); - - // UV - file.Read(&UVNum, sizeof(UVNum)); - currentFile.Write32(UVNum); - - // Flags - file.Read(buffer, 0x04); - currentFile.WriteBuf(buffer, 0x04); - - // Num morphs - file.Read(&morphNum, sizeof(morphNum)); - SInt64 morphOffset = currentFile.GetOffset(); - currentFile.Write32(morphNum); - - // Num modifiers - file.Read(buffer, 0x04); - currentFile.WriteBuf(buffer, 0x04); - - // Mod vertices - file.Read(buffer, 0x04); - currentFile.WriteBuf(buffer, 0x04); - - // Unknown 7-10 - file.Read(buffer, 0x04 * 4); - currentFile.WriteBuf(buffer, 0x04 * 4); - - // Base mesh - for (UInt32 i = 0; i < vertexNum; i++) - { - float x, y, z; - file.Read(&x, sizeof(x)); - currentFile.WriteFloat(x); - file.Read(&y, sizeof(y)); - currentFile.WriteFloat(y); - file.Read(&z, sizeof(z)); - currentFile.WriteFloat(z); - } - - // Faces - for (UInt32 i = 0; i < faceNum; i++) - { - UInt32 x, y, z; - file.Read(&x, sizeof(x)); - currentFile.Write32(x); - file.Read(&y, sizeof(y)); - currentFile.Write32(y); - file.Read(&z, sizeof(z)); - currentFile.Write32(z); - } - - // UV coords - for (UInt32 i = 0; i < UVNum; i++) - { - float x, y; - file.Read(&x, sizeof(x)); - currentFile.WriteFloat(x); - file.Read(&y, sizeof(y)); - currentFile.WriteFloat(y); - } - - // Texture tris - for (UInt32 i = 0; i < faceNum; i++) - { - UInt32 x, y, z; - file.Read(&x, sizeof(x)); - currentFile.Write32(x); - file.Read(&y, sizeof(y)); - currentFile.Write32(y); - file.Read(&z, sizeof(z)); - currentFile.Write32(z); - } - - // Write the morph count - morphNum = g_customDataMax; - SInt64 currentOffset = currentFile.GetOffset(); - currentFile.SetOffset(morphOffset); - currentFile.Write32(morphNum); - currentFile.SetOffset(currentOffset); - - // Write morphs - for(UInt32 i = 0; i < morphNum; i++) - { - memset(buffer, 0, MAX_PATH); - sprintf_s(buffer, MAX_PATH, "CustomMorph%d", i); - UInt32 strLength = strlen(buffer) + 1; - currentFile.Write32(strLength); - currentFile.WriteBuf(buffer, strLength); - currentFile.WriteFloat(0); // Base Diff - - // Write vertex data - for(UInt32 j = 0; j < vertexNum; j++) - { - currentFile.Write16(0); // DiffX - currentFile.Write16(0); // DiffY - currentFile.Write16(0); // DiffZ - } - } - } - catch(...) - { - _ERROR("%s - exception during tri write.", __FUNCTION__); - } - - currentFile.Close(); - return false; -} -#endif - -UInt8 BSFaceGenModel_Hooked::ApplyChargenMorph_Hooked(const char ** morphName, TESModelTri * modelMorph, NiAVObject ** headNode, float relative, UInt8 unk1) -{ -#ifdef _DEBUG - //_MESSAGE("%08X - Applying %s from %s : %s - %f", this, morphName[0], modelMorph->name.data, headPart->partName.data, relative); -#endif - - UInt8 ret = CALL_MEMBER_FN(this, ApplyMorph)(morphName, modelMorph, headNode, relative, unk1); - -#ifdef USE_TRICACHE - std::string lowerStr(modelMorph->GetModelName()); - std::transform(lowerStr.begin(), lowerStr.end(), lowerStr.begin(), ::tolower); - - UInt32 hash = HashUtil::CRC32(lowerStr.c_str()); - CacheTempTRI(hash, lowerStr.c_str()); -#endif - - try - { - MorphVisitor morphVisitor(this, morphName, headNode, relative, unk1); - g_morphHandler.VisitMorphMap(BSFixedString(modelMorph->GetModelName()), morphVisitor); - } - catch (...) - { - _ERROR("%s - fatal error while applying morph (%s)", __FUNCTION__, *morphName); - } - - - - return ret; -} - -void RaceSexMenu_Hooked::DoubleMorphCallback_Hooked(float newValue, UInt32 sliderId) -{ - RaceMenuSlider * slider = NULL; - RaceSexMenu::RaceComponent * raceData = NULL; - - UInt8 gender = 0; - PlayerCharacter * player = (*g_thePlayer); - TESNPC * actorBase = DYNAMIC_CAST(player->baseForm, TESForm, TESNPC); - if(actorBase) - gender = CALL_MEMBER_FN(actorBase, GetSex)(); - BSFaceGenNiNode * faceNode = player->GetFaceGenNiNode(); - - if(raceIndex < sliderData[gender].count) - raceData = &sliderData[gender][raceIndex]; - if(raceData && sliderId < raceData->sliders.count) - slider = &raceData->sliders[sliderId]; - - if(raceData && slider) { -#ifdef _DEBUG_HOOK - _DMESSAGE("Name: %s Value: %f Callback: %s Index: %d", slider->name, slider->value, slider->callback, slider->index); -#endif - if(slider->index >= SLIDER_OFFSET) { - UInt32 sliderIndex = slider->index - SLIDER_OFFSET; - SliderInternalPtr sliderInternal = g_morphHandler.GetSliderByIndex(player->race, sliderIndex); - if(!sliderInternal) - return; - - float currentValue = g_morphHandler.GetMorphValueByName(actorBase, sliderInternal->name); - float relative = newValue - currentValue; - - if(relative == 0.0 && sliderInternal->type != SliderInternal::kTypeHeadPart) { - // Nothing to morph here -#ifdef _DEBUG_HOOK - _DMESSAGE("Skipping Morph %s", sliderInternal->name.data); -#endif - return; - } - - if(sliderInternal->type == SliderInternal::kTypePreset) - { - slider->value = newValue; - - char buffer[MAX_PATH]; - slider->value = newValue; - sprintf_s(buffer, MAX_PATH, "%s%d", sliderInternal->lowerBound.data, (UInt32)currentValue); - g_morphHandler.SetMorph(actorBase, faceNode, buffer, -1.0); - memset(buffer, 0, MAX_PATH); - sprintf_s(buffer, MAX_PATH, "%s%d", sliderInternal->lowerBound.data, (UInt32)newValue); - g_morphHandler.SetMorph(actorBase, faceNode, buffer, 1.0); - - g_morphHandler.SetMorphValue(actorBase, sliderInternal->name, newValue); - return; - } - - if(sliderInternal->type == SliderInternal::kTypeHeadPart) - { - slider->value = newValue; - - UInt8 partType = sliderInternal->presetCount; - - HeadPartList * partList = g_partSet.GetPartList(partType); - if(partList) - { - if(newValue == 0.0) { - BGSHeadPart * oldPart = actorBase->GetCurrentHeadPartByType(partType); - if(oldPart) { - BGSHeadPart * defaultPart = g_partSet.GetDefaultPart(partType); - if(defaultPart && oldPart != defaultPart) { - CALL_MEMBER_FN(actorBase, ChangeHeadPart)(defaultPart); - ChangeActorHeadPart(player, oldPart, defaultPart); - } - } - return; - } - BGSHeadPart * targetPart = g_partSet.GetPartByIndex(partList, (UInt32)newValue - 1); - if(targetPart) { - BGSHeadPart * oldPart = actorBase->GetCurrentHeadPartByType(partType); - if (oldPart != targetPart) { - CALL_MEMBER_FN(actorBase, ChangeHeadPart)(targetPart); - ChangeActorHeadPart(player, oldPart, targetPart); - } - } - } - - return; - } - - - // Cross from positive to negative - if(newValue < 0.0 && currentValue > 0.0) { - // Undo the upper morph - SetRelativeMorph(actorBase, faceNode, sliderInternal->upperBound, -abs(currentValue)); -#ifdef _DEBUG_HOOK - _DMESSAGE("Undoing Upper Morph: New: %f Old: %f Relative %f Remaining %f", newValue, currentValue, relative, relative - currentValue); -#endif - relative = newValue; - } - - // Cross from negative to positive - if(newValue > 0.0 && currentValue < 0.0) { - // Undo the lower morph - SetRelativeMorph(actorBase, faceNode, sliderInternal->lowerBound, -abs(currentValue)); -#ifdef _DEBUG_HOOK - _DMESSAGE("Undoing Lower Morph: New: %f Old: %f Relative %f Remaining %f", newValue, currentValue, relative, relative - currentValue); -#endif - relative = newValue; - } - -#ifdef _DEBUG_HOOK - _DMESSAGE("CurrentValue: %f Relative: %f SavedValue: %f", currentValue, relative, slider->value); -#endif - slider->value = newValue; - - BSFixedString bound = sliderInternal->lowerBound; - if(newValue < 0.0) { - bound = sliderInternal->lowerBound; - relative = -relative; - } else if(newValue > 0.0) { - bound = sliderInternal->upperBound; - } else { - if(currentValue > 0.0) { - bound = sliderInternal->upperBound; - } else { - bound = sliderInternal->lowerBound; - relative = -relative; - } - } - -#ifdef _DEBUG_HOOK - _DMESSAGE("Morphing %d - %s Relative: %f", sliderIndex, bound.data, relative); -#endif - - SetRelativeMorph(actorBase, faceNode, bound, relative); - g_morphHandler.SetMorphValue(actorBase, sliderInternal->name, newValue); - return; - } - } - - CALL_MEMBER_FN(this, DoubleMorphCallback)(newValue, sliderId); -} - -void RaceSexMenu_Hooked::SetRelativeMorph(TESNPC * npc, BSFaceGenNiNode * faceNode, BSFixedString name, float relative) -{ - float absRel = abs(relative); - if(absRel > 1.0) { - float max = 0.0; - if(relative < 0.0) - max = -1.0; - if(relative > 0.0) - max = 1.0; - UInt32 count = (UInt32)absRel; - for(UInt32 i = 0; i < count; i++) { - g_morphHandler.SetMorph(npc, faceNode, name.data, max); - relative -= max; - } - } - g_morphHandler.SetMorph(npc, faceNode, name.data, relative); -} - -#include "CDXNifScene.h" -#include "CDXNifMesh.h" - -#include "CDXCamera.h" - -#include "skse/NiRenderer.h" -#include "skse/NiTextures.h" -#include -#pragma comment(lib, "d3dx9.lib") - - -CDXNifScene g_World; -extern CDXModelViewerCamera g_Camera; // A model viewing camera - -void RaceSexMenu_Hooked::RenderMenu_Hooked(void) -{ - CALL_MEMBER_FN(this, RenderMenu)(); - - LPDIRECT3DDEVICE9 pDevice = NiDX9Renderer::GetSingleton()->m_pkD3DDevice9; - if (!pDevice) // This shouldnt happen - return; - - if(g_World.IsVisible() && g_World.GetTextureGroup()) { - NiRenderedTexture * renderedTexture = g_World.GetTextureGroup()->renderedTexture[0]; - if(renderedTexture) { - g_World.Begin(pDevice); - LPDIRECT3DSURFACE9 oldTarget; - pDevice->GetRenderTarget(0,&oldTarget); - LPDIRECT3DSURFACE9 pRenderSurface = NULL; - LPDIRECT3DTEXTURE9 pRenderTexture = (LPDIRECT3DTEXTURE9)((NiTexture::NiDX9TextureData*)renderedTexture->rendererData)->texture; - pRenderTexture->GetSurfaceLevel(0, &pRenderSurface); - pDevice->SetRenderTarget(0, pRenderSurface); - g_World.Render(pDevice); - pDevice->SetRenderTarget(0, oldTarget); - g_World.End(pDevice); - } - } -} - -void InstallHooks() -{ - WriteRelCall(DATA_ADDR(0x00699100, 0x275), (UInt32)&LoadActorValues_Hook); // Hook for loading initial data on startup - - /*WriteRelCall(DATA_ADDR(0x005A5B70, 0x48), (UInt32)&CacheTRIFile_Hook); // Used to cache internal morph set - WriteRelCall(DATA_ADDR(0x005A5E70, 0x20C), (UInt32)&CacheTRIFile_Hook); - WriteRelCall(DATA_ADDR(0x005A93E0, 0x3A), (UInt32)&CacheTRIFile_Hook);*/ - - WriteRelCall(DATA_ADDR(0x00882290, 0x185), GetFnAddr(&DataHandler_Hooked::GetValidPlayableHeadParts_Hooked)); // Cleans up HeadPart List - WriteRelCall(DATA_ADDR(0x00886C70, 0x97), (UInt32)&ClearFaceGenCache_Hooked); // RaceMenu dtor Cleans up HeadPart List - WriteRelCall(DATA_ADDR(0x00881320, 0x67), GetFnAddr(&BGSHeadPart_Hooked::IsPlayablePart_Hooked)); // Custom head part insertion - - if (g_extendedMorphs) { - WriteRelCall(DATA_ADDR(0x005A4070, 0xBE), GetFnAddr(&BSFaceGenModel_Hooked::ApplyChargenMorph_Hooked)); // Load and apply extended morphs - WriteRelCall(DATA_ADDR(0x005A5CE0, 0x39), GetFnAddr(&BSFaceGenModel_Hooked::ApplyRaceMorph_Hooked)); // Load and apply extended morphs - } - WriteRelCall(DATA_ADDR(0x005A4AC0, 0x67), GetFnAddr(&TESNPC_Hooked::UpdateMorphs_Hooked)); // Updating all morphs when head is regenerated - WriteRelCall(DATA_ADDR(0x005AA230, 0x5C), GetFnAddr(&TESNPC_Hooked::UpdateMorph_Hooked)); // ChangeHeadPart to update morph on single part - WriteRelCall(DATA_ADDR(0x00882290, 0x2E26), GetFnAddr(&SliderArray::AddSlider_Hooked)); // Create Slider - WriteRelCall(DATA_ADDR(0x00881DD0, 0x436), GetFnAddr(&FxResponseArgsList_Hooked::AddArgument_Hooked)); // Add Slider - - WriteRelCall(DATA_ADDR(0x00882290, 0x337C), GetFnAddr(&RaceSexMenu_Hooked::DoubleMorphCallback_Hooked)); // Change Slider OnLoad - WriteRelCall(DATA_ADDR(0x0087FA50, 0x93), GetFnAddr(&RaceSexMenu_Hooked::DoubleMorphCallback_Hooked)); // Change Slider OnCallback - - SafeWrite32(DATA_ADDR(0x010E7404, 0x18), GetFnAddr(&RaceSexMenu_Hooked::RenderMenu_Hooked)); // Hooks RaceMenu renderer - - if (!g_externalHeads) { - WriteRelJump(kInstallRegenHeadHook_Base, (UInt32)&InstallRegenHeadHook_Entry); // FaceGen Regenerate HeadPart Hook - WriteRelJump(kInstallForceRegenHeadHook_Base, (UInt32)&InstallForceRegenHeadHook_Entry); // Preprocessed Head Hook - } -} \ No newline at end of file diff --git a/skee/MorphHandler.cpp b/skee/MorphHandler.cpp deleted file mode 100644 index 7b989ae..0000000 --- a/skee/MorphHandler.cpp +++ /dev/null @@ -1,3206 +0,0 @@ -#include "common/IFileStream.h" -#include "skse64_common/skse_version.h" - -#include "skse64/PluginAPI.h" - -#include "skse64/GameAPI.h" -#include "skse64/GameData.h" -#include "skse64/GameObjects.h" -#include "skse64/GameMenus.h" -#include "skse64/GameRTTI.h" -#include "skse64/GameResources.h" -#include "skse64/GameStreams.h" - -#include "skse64/NiNodes.h" -#include "skse64/NiGeometry.h" -#include "skse64/NiMaterial.h" -#include "skse64/NiProperties.h" -#include "skse64/NiExtraData.h" -#include "skse64/NiSerialization.h" - -#include "skse64/ScaleformMovie.h" - -#include "skse64/HashUtil.h" - -#include "MorphHandler.h" -#include "PartHandler.h" -#include "ScaleformFunctions.h" -#include "NifUtils.h" -#include "SKEEHooks.h" - -#include "OverrideVariant.h" -#include "OverrideInterface.h" -#include "NiTransformInterface.h" -#include "BodyMorphInterface.h" -#include "OverlayInterface.h" - -extern OverrideInterface g_overrideInterface; -extern NiTransformInterface g_transformInterface; -extern BodyMorphInterface g_bodyMorphInterface; -extern OverlayInterface g_overlayInterface; - -#include -#include - -extern float g_sliderMultiplier; -extern float g_sliderInterval; -extern PartSet g_partSet; -extern MorphHandler g_morphHandler; -extern std::string g_raceTemplate; -extern bool g_extendedMorphs; - -extern SKSEMessagingInterface * g_messaging; -extern PluginHandle g_pluginHandle; - -void RaceMap::Revert() -{ - clear(); -} - -void MorphHandler::Revert() -{ - m_valueMap.clear(); - m_sculptStorage.clear(); -} - -void MorphHandler::RevertInternals() -{ - m_internalMap.clear(); -} - -bool SliderSet::for_each_slider(std::function func) -{ - // Iterate the list of SliderSet - for (auto rit = begin(); rit != end(); ++rit) - { - // Iterate the SliderMap - for (auto it = (*rit)->begin(); it != (*rit)->end(); ++it) - { - if (func(it->second)) - return true; - } - } - - return false; -} - -SliderSetPtr RaceMap::GetSliderSet(TESRace * race) -{ - RaceMap::iterator it = find(race); - if(it != end()) - return it->second; - - return NULL; -} - -SInt32 ReadTRIVertexCount(const char * triPath) -{ - if(triPath[0] == 0) { - return -1; - } - - char filePath[MAX_PATH]; - memset(filePath, 0, MAX_PATH); - sprintf_s(filePath, MAX_PATH, "Meshes\\%s", triPath); - BSFixedString newPath(filePath); - - // Cached file already exists, load it - BSResourceNiBinaryStream file(newPath.data); - if (!file.IsValid()) { - return -1; - } - - char header[0x08]; - file.Read(header, 0x08); - if(strncmp(header, "FRTRI003", 8) != 0) - return -1; - - UInt32 vertexNum = 0; - file.Read(&vertexNum, sizeof(vertexNum)); - return vertexNum; -} - - -bool TRIFile::Load(const char * triPath) -{ - if (triPath[0] == 0) { - return -1; - } - - char filePath[MAX_PATH]; - memset(filePath, 0, MAX_PATH); - sprintf_s(filePath, MAX_PATH, "Meshes\\%s", triPath); - BSFixedString newPath(filePath); - - BSResourceNiBinaryStream file(newPath.data); - if (!file.IsValid()) { - return false; - } - - char header[0x08]; - file.Read(header, 0x08); - if (strncmp(header, "FRTRI003", 8) != 0) - return false; - - file.Read(&vertexCount, sizeof(vertexCount)); - - UInt32 polytris = 0, polyquads = 0, unk2 = 0, unk3 = 0, - uvverts = 0, flags = 0, numMorphs = 0, numMods = 0, - modVerts = 0, unk7 = 0, unk8 = 0, unk9 = 0, unk10 = 0; - - file.Read(&polytris, sizeof(polytris)); - file.Read(&polyquads, sizeof(polyquads)); - file.Read(&unk2, sizeof(unk2)); - file.Read(&unk3, sizeof(unk3)); - file.Read(&uvverts, sizeof(uvverts)); - file.Read(&flags, sizeof(flags)); - file.Read(&numMorphs, sizeof(numMorphs)); - file.Read(&numMods, sizeof(numMods)); - file.Read(&modVerts, sizeof(modVerts)); - file.Read(&unk7, sizeof(unk7)); - file.Read(&unk8, sizeof(unk8)); - file.Read(&unk9, sizeof(unk9)); - file.Read(&unk10, sizeof(unk10)); - - // Skip reference verts - file.Seek(vertexCount * 3 * sizeof(float)); - - // Skip polytris - file.Seek(polytris * 3 * sizeof(UInt32)); - - // Skip UV - if (uvverts > 0) - file.Seek(uvverts * 2 * sizeof(float)); - - // Skip text coords - file.Seek(polytris * 3 * sizeof(UInt32)); - - for (UInt32 i = 0; i < numMorphs; i++) - { - UInt32 strLen = 0; - file.Read(&strLen, sizeof(strLen)); - - char * name = new char[strLen+1]; - for (UInt32 l = 0; l < strLen; l++) - { - file.Read(&name[l], sizeof(char)); - } - name[strLen] = 0; - - float mult = 0.0f; - file.Read(&mult, sizeof(mult)); - - Morph morph; - morph.name = BSFixedString(name); - morph.multiplier = mult; - - for (UInt32 v = 0; v < vertexCount; v++) - { - Morph::Vertex vert; - file.Read(&vert, sizeof(vert)); - morph.vertices.push_back(vert); - } - - morphs.insert(std::make_pair(morph.name, morph)); - } - - return true; -} - -bool TRIFile::Apply(BSGeometry * geometry, BSFixedString morphName, float relative) -{ - BSFaceGenBaseMorphExtraData * extraData = (BSFaceGenBaseMorphExtraData *)geometry->GetExtraData("FOD"); - if (!extraData) - return false; - - // Found morph doesn't match the cached morph - if (extraData->vertexCount != vertexCount) - return false; - - // Morph name wasn't found - auto & morph = morphs.find(morphName); - if (morph == morphs.end()) - return false; - - // What? - if (extraData->vertexCount != morph->second.vertices.size()) - return false; - - UInt32 size = morph->second.vertices.size(); - for (UInt32 i = 0; i < size; i++) - { - auto & vert = morph->second.vertices.at(i); - extraData->vertexData[i].x += (float)((double)vert.x * (double)morph->second.multiplier * (double)relative); - extraData->vertexData[i].y += (float)((double)vert.y * (double)morph->second.multiplier * (double)relative); - extraData->vertexData[i].z += (float)((double)vert.z * (double)morph->second.multiplier * (double)relative); - } - - UpdateModelFace(geometry); - return true; -} - -class RacePartVisitor -{ -public: - virtual bool Accept(BGSHeadPart * headPart) = 0; -}; - -void VisitRaceParts(TESRace * race, UInt32 gender, RacePartVisitor & visitor) -{ - TESRace::CharGenData * chargenData = race->chargenData[gender]; - if(chargenData) { - tArray * headParts = chargenData->headParts; - if(headParts) { - for(UInt32 i = 0; i < headParts->count; i++) { - BGSHeadPart* headPart = NULL; - if(headParts->GetNthItem(i, headPart)) { - if(visitor.Accept(headPart)) - break; - } - } - } - } -} - -class RacePartByType : public RacePartVisitor -{ -public: - RacePartByType::RacePartByType(UInt32 partType) : m_type(partType), m_headPart(NULL) {} - virtual bool Accept(BGSHeadPart * headPart) - { - if(headPart->type == m_type) { - m_headPart = headPart; - return true; - } - - return false; - } - - UInt32 m_type; - BGSHeadPart * m_headPart; -}; - -class RacePartDefaultGen : public RacePartVisitor -{ -public: - RacePartDefaultGen::RacePartDefaultGen(TESRace * sourceRace, TESRace * targetRace, std::vector * parts, UInt32 gender) : m_sourceRace(sourceRace), m_targetRace(targetRace), m_gender(gender), m_partList(parts), m_acceptDefault(false) {} - - virtual bool Accept(BGSHeadPart * headPart) - { - BSFixedString sourceMorphPath(headPart->chargenMorph.GetModelName()); - if(sourceMorphPath == BSFixedString("")) - return false; - - auto it = std::find(m_partList->begin(), m_partList->end(), sourceMorphPath); - if (it != m_partList->end()) { // Found part tri file - if(headPart->type == BGSHeadPart::kTypeFace) - m_acceptDefault = true; - } else { - RacePartByType racePart(headPart->type); - VisitRaceParts(m_targetRace, m_gender, racePart); - - BGSHeadPart * targetPart = racePart.m_headPart; - if(targetPart) { - BSFixedString targetMorphPath(targetPart->chargenMorph.GetModelName()); - if(targetMorphPath == BSFixedString("")) { - _ERROR("%s - Could not bind default morphs for %s on %s[%d] using %s. No valid morph path.", __FUNCTION__, headPart->partName.data, m_sourceRace->editorId.data, m_gender, m_targetRace->editorId.data, sourceMorphPath.data); - return false; - } - - TRIModelData sourceData, targetData; - g_morphHandler.GetModelTri(sourceMorphPath, sourceData); - g_morphHandler.GetModelTri(targetMorphPath, targetData); - - if (sourceData.vertexCount == targetData.vertexCount && sourceData.vertexCount > 0 && targetData.vertexCount > 0) { - // Bind additional morphs here, the source and target morphs are identical - _DMESSAGE("%s - Binding default morphs for %s (%s) on %s[%d] using %s. (%s - %d | %s - %d)", __FUNCTION__, headPart->partName.data, sourceMorphPath.data, m_sourceRace->editorId.data, m_gender, m_targetRace->editorId.data, sourceMorphPath.data, sourceData.vertexCount, targetMorphPath.data, targetData.vertexCount); - auto titer = g_morphHandler.m_morphMap.find(targetMorphPath); - if(titer != g_morphHandler.m_morphMap.end()) - g_morphHandler.m_morphMap.emplace(sourceMorphPath, titer->second); - if(headPart->type == BGSHeadPart::kTypeFace) - m_acceptDefault = true; - } else if(sourceData.vertexCount == 0 || targetData.vertexCount == 0) { - _ERROR("%s - Could not bind default morphs for %s on %s[%d] using %s. Invalid vertex count (%s - %d | %s - %d).", __FUNCTION__, headPart->partName.data, m_sourceRace->editorId.data, m_gender, m_targetRace->editorId.data, sourceMorphPath.data, sourceData.vertexCount, targetMorphPath.data, targetData.vertexCount); - } else { - _ERROR("%s - Could not bind default morphs for %s on %s[%d] using %s. Vertex mismatch (%s - %d | %s - %d).", __FUNCTION__, headPart->partName.data, m_sourceRace->editorId.data, m_gender, m_targetRace->editorId.data, sourceMorphPath.data, sourceData.vertexCount, targetMorphPath.data, targetData.vertexCount); - } - } - } - - return false; - } - - UInt32 m_gender; - TESRace * m_sourceRace; - TESRace * m_targetRace; - std::vector * m_partList; - bool m_acceptDefault; -}; - -class RacePartFiles : public RacePartVisitor -{ -public: - RacePartFiles::RacePartFiles(std::vector * parts) : m_parts(parts) {} - virtual bool Accept(BGSHeadPart * headPart) - { - if (headPart->chargenMorph.name.data != BSFixedString("").data) - m_parts->push_back(headPart->chargenMorph.name); - if (headPart->raceMorph.name.data != BSFixedString("").data) - m_parts->push_back(headPart->raceMorph.name); - - return false; - } - - std::vector * m_parts; -}; - -bool RaceMap::CreateDefaultMap(TESRace * race) -{ - TESRace * templateRace = GetRaceByName(g_raceTemplate); - RaceMap::iterator rit = find(templateRace); - if(rit != end()) { // Found NordRace slider maps - - std::vector templateFiles; - for (UInt32 gender = 0; gender <= 1; gender++) { - RacePartFiles parts(&templateFiles); - VisitRaceParts(templateRace, gender, parts); - } - - bool acceptDefault = false; - for(UInt32 gender = 0; gender <= 1; gender++) { // Iterate genders - RacePartDefaultGen defaultGen(race, templateRace, &templateFiles, gender); - VisitRaceParts(race, gender, defaultGen); - acceptDefault = defaultGen.m_acceptDefault; - } - - if(acceptDefault) { - SliderSetPtr sliderMaps = rit->second; - if(sliderMaps->size() > 0) { - UInt32 addedMaps = 0; - for(auto smit = sliderMaps->begin(); smit != sliderMaps->end(); ++smit) { - if(AddSliderMap(race, *smit)) - addedMaps++; - } - if(addedMaps > 0) { - _DMESSAGE("%s - Added default slider maps for %s from %s", __FUNCTION__, race->editorId.data, rit->first->editorId.data); - return true; - } - } - } - } - - return false; -} - -bool RaceMap::AddSliderMap(TESRace * race, SliderMapPtr sliderMap) -{ - RaceMap::iterator it = find(race); - if(it != end()) { - //std::pair ret; - auto ret = it->second->insert(sliderMap); - return ret.second; - } else { - SliderSetPtr sliderMaps = std::make_shared(); - sliderMaps->insert(sliderMap); - emplace(race, sliderMaps); - return true; - } - - return false; -} - -SliderInternalPtr MorphHandler::GetSliderByIndex(TESRace * race, UInt32 index) -{ - RaceSliders::iterator it = m_internalMap.find(race); - if(it != m_internalMap.end()) { - if(index < it->second.size()) - return it->second.at(index); - } - return NULL; -} - -float ValueMap::GetMorphValueByName(TESNPC* npc, BSFixedString name) -{ - ValueMap::iterator it = find(npc); - if(it != end()) { - return it->second.GetValue(name); - } - - return 0.0; -} - -void ValueMap::SetMorphValue(TESNPC* npc, BSFixedString name, float value) -{ - ValueMap::iterator it = find(npc); - if(it != end()) { - it->second.SetValue(name, value); - } else { - ValueSet newSet; - newSet.emplace(name, value); - emplace(npc, newSet); - } -} - -void ValueSet::SetValue(BSFixedString name, float value) -{ - ValueSet::iterator val = find(name); - if (val != end()) - val->second = value; - else - emplace(name, value); -} - -void ValueSet::ClearValue(BSFixedString name) -{ - ValueSet::iterator val = find(name); - if(val != end()) - erase(val); -} - -float ValueSet::GetValue(BSFixedString name) -{ - ValueSet::iterator val = find(name); - if(val != end()) - return val->second; - - return 0.0; -} - -ValueSet * ValueMap::GetValueSet(TESNPC* npc) -{ - ValueMap::iterator it = find(npc); - if(it != end()) { - return &it->second; - } - - return NULL; -} - -void ValueMap::EraseNPC(TESNPC * npc) -{ - auto it = find(npc); - if (it != end()) - erase(it); -} - -float MorphHandler::GetMorphValueByName(TESNPC* npc, BSFixedString name) -{ - return m_valueMap.GetMorphValueByName(npc, name); -} - -void MorphHandler::SetMorphValue(TESNPC* npc, BSFixedString name, float value) -{ - return m_valueMap.SetMorphValue(npc, name, value); -} - -void MorphMap::Revert() -{ - clear(); -} - -class ExtendedMorphCache : public MorphMap::Visitor -{ -public: - virtual bool Accept(BSFixedString morphName) - { - g_morphHandler.GetExtendedModelTri(morphName); - return false; - } -}; - -void MorphHandler::LoadMods() -{ - DataHandler * dataHandler = DataHandler::GetSingleton(); - if (dataHandler) - { - ForEachMod([&](ModInfo * modInfo) - { - std::string fixedPath = "Meshes\\"; - fixedPath.append(SLIDER_MOD_DIRECTORY); - std::string modPath = modInfo->name; - modPath.append("\\"); - - ReadRaces(fixedPath, modPath, "races.ini"); - if (g_extendedMorphs) - ReadMorphs(fixedPath, modPath, "morphs.ini"); - - ReadPartReplacements(fixedPath, modPath, "replacements.ini"); - }); - - if (g_extendedMorphs) { - BGSHeadPart * part = NULL; - for (UInt32 i = 0; i < dataHandler->headParts.count; i++) - { - if (dataHandler->headParts.GetNthItem(i, part)) { - if (CacheHeadPartModel(part)) { - - BSFixedString key = part->chargenMorph.GetModelName(); - - // Cache all of the extended morphs - ExtendedMorphCache extendedCache; - VisitMorphMap(key, extendedCache); - } - } - } - } - - // Create default slider maps - TESRace * race = NULL; - for (UInt32 i = 0; i < dataHandler->races.count; i++) - { - if (dataHandler->races.GetNthItem(i, race)) { - -#ifdef FIXME - if (g_allowAllMorphs) { - for (UInt32 i = 0; i <= 1; i++) { - if (race->chargenData[i]) { - for (UInt32 t = 0; t < FacePresetList::kNumPresets; t++) { - const char * gameSetting = FacePresetList::GetSingleton()->presets[t].data->gameSettingName; - race->chargenData[i]->presetFlags[t][0] = 0xFFFFFFFF; - race->chargenData[i]->presetFlags[t][1] = 0xFFFFFFFF; - race->chargenData[i]->totalPresets[t] = GetGameSettingInt(gameSetting); - } - } - } - } -#endif - if ((race->data.raceFlags & TESRace::kRace_FaceGenHead) == TESRace::kRace_FaceGenHead) - m_raceMap.CreateDefaultMap(race); - } - } - } -} - -bool MorphHandler::CacheHeadPartModel(BGSHeadPart * headPart, bool cacheTRI) -{ - BSFixedString modelPath = headPart->chargenMorph.GetModelName(); - if (modelPath == BSFixedString("")) - return false; - - ModelMap::iterator it = m_modelMap.find(modelPath); - if (it == m_modelMap.end()) { - TRIModelData data; - - data.morphModel = &headPart->chargenMorph; - if (!cacheTRI) { - data.vertexCount = ReadTRIVertexCount(modelPath.data); - } - else { - data.triFile = std::make_shared(); - data.triFile->Load(modelPath.data); - data.vertexCount = data.triFile->vertexCount; - } - - m_modelMap.emplace(modelPath, data); - } - else if (cacheTRI && !it->second.triFile) { - it->second.triFile = std::make_shared(); - it->second.triFile->Load(modelPath.data); - } - - return true; -} - -bool MorphHandler::GetModelTri(BSFixedString filePath, TRIModelData & modelData) -{ - ModelMap::iterator it = m_modelMap.find(filePath); - if (it != m_modelMap.end()) { - modelData = it->second; - return true; - } - - return false; -} - -TRIModelData & MorphHandler::GetExtendedModelTri(BSFixedString morphName, bool cacheTRI) -{ - std::string filePath(SLIDER_DIRECTORY); - filePath.append(morphName.data); - BSFixedString morphFile(filePath.c_str()); - ModelMap::iterator it = m_modelMap.find(morphFile); - if(it == m_modelMap.end()) { - void* memory = Heap_Allocate(sizeof(TESModelTri)); - memset(memory, 0, sizeof(TESModelTri)); - ((uintptr_t*)memory)[0] = TESModelTri_vtbl.GetUIntPtr(); - TESModelTri* xData = (TESModelTri*)memory; - xData->SetModelName(morphFile.data); - - TRIModelData data; - data.morphModel = xData; - if (!cacheTRI) { - data.vertexCount = ReadTRIVertexCount(morphFile.data); - } - else { - data.triFile = std::make_shared(); - data.triFile->Load(morphFile.data); - data.vertexCount = data.triFile->vertexCount; - } - - auto ret = m_modelMap.emplace(morphFile, data); - return ret.first->second; - } - else if(cacheTRI && !it->second.triFile) { - it->second.triFile = std::make_shared(); - it->second.triFile->Load(morphFile.data); - } - - return it->second; -} - -PresetDataPtr MorphHandler::GetPreset(TESNPC* npc) -{ - auto it = m_mappedPreset.find(npc); - if (it != m_mappedPreset.end()) - return it->second; - - return NULL; -} - -void MorphHandler::AssignPreset(TESNPC * npc, PresetDataPtr presetData) -{ - ErasePreset(npc); - m_mappedPreset.emplace(npc, presetData); -} - -bool MorphHandler::ErasePreset(TESNPC * npc) -{ - auto it = m_mappedPreset.find(npc); - if (it != m_mappedPreset.end()) { - m_mappedPreset.erase(it); - return true; - } - - return false; -} - -void MorphHandler::ClearPresets() -{ - m_mappedPreset.clear(); -} - -void MorphHandler::ApplyPreset(TESNPC * npc, BSFaceGenNiNode * faceNode, BGSHeadPart * headPart) -{ - PresetDataPtr presetData = GetPreset(npc); - if (presetData && faceNode && headPart) { - NiAVObject * object = faceNode->GetObjectByName(&headPart->partName.data); - if (object) { - BSGeometry * geometry = object->GetAsBSGeometry(); - if (geometry) { - BSShaderProperty * shaderProperty = niptr_cast(geometry->m_spEffectState); - if (shaderProperty) { - if (ni_is_type(shaderProperty->GetRTTI(), BSLightingShaderProperty)) { - BSLightingShaderProperty * lightingShader = (BSLightingShaderProperty *)shaderProperty; - BSLightingShaderMaterial * material = (BSLightingShaderMaterial *)shaderProperty->material; - if (headPart->type == BGSHeadPart::kTypeFace) { - for (auto & texture : presetData->faceTextures) - material->textureSet->SetTexturePath(texture.index, texture.name.data); - material->textureSet->SetTexturePath(6, presetData->tintTexture.data); - material->ReleaseTextures(); - CALL_MEMBER_FN(lightingShader, InvalidateTextures)(0); - CALL_MEMBER_FN(lightingShader, InitializeShader)(geometry); - } - else if (material->GetShaderType() == BSLightingShaderMaterial::kShaderType_HairTint) { - BSLightingShaderMaterialHairTint * tintedMaterial = (BSLightingShaderMaterialHairTint *)material; // I don't know what this * 2.0 bullshit is. - tintedMaterial->tintColor.r = (((presetData->hairColor >> 16) & 0xFF) / 255.0) * 2.0; - tintedMaterial->tintColor.g = (((presetData->hairColor >> 8) & 0xFF) / 255.0) * 2.0; - tintedMaterial->tintColor.b = ((presetData->hairColor & 0xFF) / 255.0) * 2.0; - } - } - } - } - } - } -} - -class ValidRaceFinder : public BGSListForm::Visitor -{ -public: - ValidRaceFinder::ValidRaceFinder(TESRace * race) : m_race(race) { } - virtual bool Accept(TESForm * form) - { - if (m_race == form) - return true; - - return false; - }; - TESRace * m_race; -}; - -void MorphHandler::ApplyPresetData(Actor * actor, PresetDataPtr presetData, bool setSkinColor, ApplyTypes applyType) -{ - PlayerCharacter * player = (*g_thePlayer); - TESNPC * npc = DYNAMIC_CAST(actor->baseForm, TESForm, TESNPC); - TESRace * race = npc->race.race; - - // Wipe the HeadPart list and replace it with the default race list - UInt8 gender = CALL_MEMBER_FN(npc, GetSex)(); - TESRace::CharGenData * chargenData = race->chargenData[gender]; - if (chargenData) { - BGSHeadPart ** headParts = npc->headparts; - tArray * headPartList = race->chargenData[gender]->headParts; - if (headParts && headPartList) { - Heap_Free(headParts); - npc->numHeadParts = headPartList->count; - headParts = (BGSHeadPart **)Heap_Allocate(npc->numHeadParts * sizeof(BGSHeadPart*)); - for (UInt32 i = 0; i < headPartList->count; i++) - headPartList->GetNthItem(i, headParts[i]); - npc->headparts = headParts; - } - } - - // Replace the old parts with the new parts if they are the right sex - for (auto & part : presetData->headParts) { - if ((gender == 0 && (part->partFlags & BGSHeadPart::kFlagMale) == BGSHeadPart::kFlagMale) || - (gender == 1 && (part->partFlags & BGSHeadPart::kFlagFemale) == BGSHeadPart::kFlagFemale)) - { - ValidRaceFinder partFinder(race); - if (part->validRaces) { - if (part->validRaces->Visit(partFinder)) - CALL_MEMBER_FN(npc, ChangeHeadPart)(part); - } - } - } - - npc->weight = presetData->weight; - - if (!npc->faceMorph) - npc->faceMorph = (TESNPC::FaceMorphs*)Heap_Allocate(sizeof(TESNPC::FaceMorphs)); - - UInt32 i = 0; - for (auto value : presetData->presets) { - npc->faceMorph->presets[i] = value; - i++; - } - - i = 0; - for (auto value : presetData->morphs) { - npc->faceMorph->option[i] = value; - i++; - } - - for (auto & tint : presetData->tints) { - float alpha = (tint.color >> 24) / 255.0; - TintMask * tintMask = NULL; - if (player == actor && player->tintMasks.GetNthItem(tint.index, tintMask)) { - tintMask->color.red = (tint.color >> 16) & 0xFF; - tintMask->color.green = (tint.color >> 8) & 0xFF; - tintMask->color.blue = tint.color & 0xFF; - tintMask->alpha = alpha; - if (tintMask->alpha > 0) - tintMask->texture->str = tint.name; - } - - if (tint.index == 0 && setSkinColor) - { - 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); - } - } - - g_morphHandler.EraseSculptData(npc); - if (presetData->sculptData) { - if (presetData->sculptData->size() > 0) { - g_morphHandler.SetSculptTarget(npc, presetData->sculptData); - } - } - - g_morphHandler.EraseMorphData(npc); - for (auto & morph : presetData->customMorphs) - g_morphHandler.SetMorphValue(npc, morph.name, morph.value); - - g_overrideInterface.RemoveAllReferenceNodeOverrides(actor); - g_overlayInterface.RevertOverlays(actor, true); - - if ((applyType & kPresetApplyOverrides) == kPresetApplyOverrides) - { - for (auto & nodes : presetData->overrideData) { - for (auto & value : nodes.second) { - g_overrideInterface.AddNodeOverride(actor, gender == 1 ? true : false, nodes.first, value); - } - } - } - - if ((applyType & kPresetApplySkinOverrides) == kPresetApplySkinOverrides) - { - for (UInt32 i = 0; i <= 1; i++) { - for (auto & slot : presetData->skinData[i]) { - for (auto & value : slot.second) { - g_overrideInterface.AddSkinOverride(actor, gender == 1 ? true : false, i == 1 ? true : false, slot.first, value); - } - } - } - } - - g_transformInterface.RemoveAllReferenceTransforms(actor); - - if ((applyType & kPresetApplyTransforms) == kPresetApplyTransforms) - { - for (UInt32 i = 0; i <= 1; i++) { - for (auto & xForms : presetData->transformData[i]) { - for (auto & key : xForms.second) { - for (auto & value : key.second) { - g_transformInterface.AddNodeTransform(actor, i == 1 ? true : false, gender == 1 ? true : false, xForms.first, key.first, value); - } - } - } - } - } - g_transformInterface.UpdateNodeAllTransforms(actor); - - - g_bodyMorphInterface.ClearMorphs(actor); - - if ((applyType & kPresetApplyBodyMorphs) == kPresetApplyBodyMorphs) - { - for (auto & morph : presetData->bodyMorphData) { - for (auto & keys : morph.second) - g_bodyMorphInterface.SetMorph(actor, morph.first, keys.first, keys.second); - } - } - - g_bodyMorphInterface.UpdateModelWeight(actor); -} - -bool MorphMap::Visit(BSFixedString key, Visitor & visitor) -{ - MorphMap::iterator it = find(key); - if(it != end()) - { -#ifdef _DEBUG_MORPHAPPLICATOR - _DMESSAGE("%s - Applying %d additional morphs to %s", __FUNCTION__, it->second.size(), key.data); - gLog.Indent(); -#endif - for(auto iter = it->second.begin(); iter != it->second.end(); ++iter) - { -#ifdef _DEBUG_MORPHAPPLICATOR - _DMESSAGE("%s - Visting %s", __FUNCTION__, (*iter).data); -#endif - if(visitor.Accept(*iter)) - break; - } -#ifdef _DEBUG_MORPHAPPLICATOR - gLog.Outdent(); -#endif - return true; - } -#ifdef _DEBUG_MORPHAPPLICATOR - else { - _DMESSAGE("%s - No additional morphs for %s", __FUNCTION__, key.data); - } -#endif - - return false; -} - - - -bool MorphHandler::VisitMorphMap(BSFixedString key, MorphMap::Visitor & visitor) -{ - //key = toLower(key); - return m_morphMap.Visit(key, visitor); -} - -void MorphMap::AddMorph(BSFixedString key, BSFixedString value) -{ - //key = toLower(key); - MorphMap::iterator it = find(key); - if(it != end()) { - if (std::find(it->second.begin(), it->second.end(), value) == it->second.end()) - it->second.push_back(value); - } else { - MorphSet firstSet; - firstSet.push_back(value); - emplace(key, firstSet); - } -} - -void MorphHandler::ReadMorphs(std::string fixedPath, std::string modName, std::string fileName) -{ - std::string fullPath = fixedPath + modName + fileName; - BSResourceNiBinaryStream file(fullPath.c_str()); - if (!file.IsValid()) { - return; - } - - UInt32 lineCount = 0; - std::string str = ""; - while(BSReadLine(&file, &str)) - { - lineCount++; - str = std::trim(str); - if(str.length() == 0) - continue; - if(str.at(0) == '#') - continue; - - std::vector side = explode(str, '='); - if(side.size() < 2) { - _ERROR("ReadMorphs Error - Line (%d) loading a morph from %s has no left-hand side.", lineCount, fullPath.c_str()); - continue; - } - - std::string lSide = std::trim(side[0]); - std::string rSide = std::trim(side[1]); - - if(_strnicmp(lSide.c_str(), "extension", 9) != 0) { - _ERROR("ReadMorphs Error - Line (%d) loading a morph from %s invalid left-hand side.", lineCount, fullPath.c_str()); - continue; - } - - std::vector params = explode(rSide, ','); - if(params.size() < 2) { - _ERROR("ReadMorphs Error - Line (%d) slider %s from %s has less than 2 parameters.", lineCount, lSide.c_str(), fullPath.c_str()); - continue; - } - - // Trim all parameters - for(UInt32 i = 0; i < params.size(); i++) - params[i] = std::trim(params[i]); - - std::string key = params[0]; - for(UInt32 i = 1; i < params.size(); i++) { -#ifdef _DEBUG_DATAREADER - _DMESSAGE("ReadMorphs Info - Line (%d) added %s morph to %s from %s.", lineCount, params[i].c_str(), key.c_str(), fullPath.c_str()); -#endif - m_morphMap.AddMorph(BSFixedString(key.c_str()), BSFixedString(params[i].c_str())); - } - } -} - -void MorphHandler::ReadRaces(std::string fixedPath, std::string modPath, std::string fileName) -{ - std::string fullPath = fixedPath + modPath + fileName; - BSResourceNiBinaryStream file(fullPath.c_str()); - if (!file.IsValid()) { - return; - } - - std::map fileMap; - - UInt32 lineCount = 0; - std::string str = ""; - while(BSReadLine(&file, &str)) - { - lineCount++; - str = std::trim(str); - if(str.length() == 0) - continue; - if(str.at(0) == '#') - continue; - - std::vector side = explode(str, '='); - if(side.size() < 2) { - _ERROR("ReadRaces Error - Line (%d) loading a race from %s has insufficient parameters.", lineCount, fullPath.c_str()); - continue; - } - - std::string lSide = std::trim(side[0]); - std::string rSide = std::trim(side[1]); - - std::vector files = explode(rSide, ','); - for(UInt32 i = 0; i < files.size(); i++) - files[i] = std::trim(files[i]); - - for(UInt32 i = 0; i < files.size(); i++) - { - std::string pathOverride = modPath; - if(files[i].at(0) == ':') { - pathOverride = ""; - files[i].erase(0, 1); - } - - SliderMapPtr sliderMap = NULL; - std::map::iterator it = fileMap.find(files[i]); - if(it != fileMap.end()) { - sliderMap = it->second; - } else { - sliderMap = ReadSliders(fixedPath, pathOverride, files[i]); - if(sliderMap) { - fileMap.emplace(files[i], sliderMap); - } else { - _ERROR("ReadRaces Error - Line (%d) failed to load slider map for %s from %s.", lineCount, lSide.c_str(), fullPath.c_str()); - } - } - - if(sliderMap) { -#ifdef _DEBUG_DATAREADER - _DMESSAGE("ReadRaces Info - Line (%d) Loaded %s for Race %s from %s.", lineCount, files[i].c_str(), lSide.c_str(), fullPath.c_str()); -#endif - - TESRace * race = GetRaceByName(lSide); - if(race) - m_raceMap.AddSliderMap(race, sliderMap); - } - } - } -} - -void SliderMap::AddSlider(BSFixedString key, UInt8 gender, SliderInternal & sliderInternal) -{ - SliderMap::iterator it = find(key); - if(it != end()) { - it->second->slider[gender] = std::make_shared(); - it->second->slider[gender]->copy(&sliderInternal); - } else { - SliderGenderPtr sliderGender = std::make_shared(); - sliderGender->slider[gender] = std::make_shared(); - sliderGender->slider[gender]->copy(&sliderInternal); - emplace(key, sliderGender); - } -} - -SliderMapPtr MorphHandler::ReadSliders(std::string fixedPath, std::string modPath, std::string fileName) -{ - SliderMapPtr sliderMap = NULL; - std::string fullPath = fixedPath + modPath + fileName; - BSResourceNiBinaryStream file(fullPath.c_str()); - if (!file.IsValid()) { - return NULL; - } - - sliderMap = std::make_shared(); - - UInt8 gender = 0; - UInt32 lineCount = 0; - std::string str = ""; - while(BSReadLine(&file, &str)) - { - lineCount++; - str = std::trim(str); - if(str.length() == 0) - continue; - if(str.at(0) == '#') - continue; - - if(str.at(0) == '[') - { - str.erase(0, 1); - if(_strnicmp(str.c_str(), "Male", 4) == 0) - gender = 0; - if(_strnicmp(str.c_str(), "Female", 6) == 0) - gender = 1; - continue; - } - - std::vector side = explode(str, '='); - if(side.size() < 2) { - _ERROR("ReadSliders Error - Line (%d) slider from %s has no left-hand side.", lineCount, fullPath.c_str()); - continue; - } - - std::string lSide = std::trim(side[0]); - std::string rSide = std::trim(side[1]); - - std::vector params = explode(rSide, ','); - if(params.size() < 3) { - _ERROR("ReadSliders Error - Line (%d) slider %s from %s has less than 3 parameters.", lineCount, lSide.c_str(), fullPath.c_str()); - continue; - } - - // Trim all parameters - for(UInt32 i = 0; i < params.size(); i++) - params[i] = std::trim(params[i]); - - BSFixedString sliderName = BSFixedString(lSide.c_str()); - SliderInternal sliderInternal; - sliderInternal.name = sliderName; - sliderInternal.category = atoi(params.at(0).c_str()); - if(sliderInternal.category == -1) - sliderInternal.category = SliderInternal::kCategoryExtra; - switch(sliderInternal.category) - { - case SliderInternal::kCategoryExpressions: - case SliderInternal::kCategoryExtra: - case SliderInternal::kCategoryBody: - case SliderInternal::kCategoryHead: - case SliderInternal::kCategoryFace: - case SliderInternal::kCategoryEyes: - case SliderInternal::kCategoryBrow: - case SliderInternal::kCategoryMouth: - case SliderInternal::kCategoryHair: - break; - default: - _ERROR("ReadSliders Error - Line (%d) loading slider %s from %s has invalid category (%d).", lineCount, lSide.c_str(), fullPath.c_str(), sliderInternal.category); - continue; - break; - } - if(_strnicmp(params[1].c_str(), "Slider", 6) == 0) { - sliderInternal.type = SliderInternal::kTypeSlider; - } else if(_strnicmp(params[1].c_str(), "Preset", 6) == 0) { - sliderInternal.type = SliderInternal::kTypePreset; - } else if(_strnicmp(params[1].c_str(), "HeadPart", 8) == 0) { - sliderInternal.type = SliderInternal::kTypeHeadPart; - } else { - _ERROR("ReadSliders Error - Line (%d) loading slider %s from %s has invalid slider type (%s).", lineCount, lSide.c_str(), fullPath.c_str(), params[1].c_str()); - continue; - } - switch(sliderInternal.type) - { - case SliderInternal::kTypeSlider: - { - // Additional morphs are disabled - if (!g_extendedMorphs) - continue; - - if(params.size() < 4) { - _ERROR("ReadSliders Error - Line (%d) slider %s from %s has less than 4 parameters.", lineCount, lSide.c_str(), fullPath.c_str()); - continue; - } - - sliderInternal.lowerBound = BSFixedString(params[2].c_str()); - sliderInternal.upperBound = BSFixedString(params[3].c_str()); - - if(sliderInternal.lowerBound == BSFixedString("None")) - sliderInternal.lowerBound = BSFixedString(""); - if(sliderInternal.upperBound == BSFixedString("None")) - sliderInternal.upperBound = BSFixedString(""); - } - break; - case SliderInternal::kTypePreset: - { - // Additional morphs are disabled - if (!g_extendedMorphs) - continue; - - if (params.size() < 4) { - _ERROR("ReadSliders Error - Line (%d) slider %s from %s has less than 4 parameters.", lineCount, lSide.c_str(), fullPath.c_str()); - continue; - } - - sliderInternal.lowerBound = BSFixedString(params[2].c_str()); - UInt32 presetCount = atoi(params[3].c_str()); - if (presetCount > 255) { - presetCount = 255; - _WARNING("ReadSliders Warning - Line (%d) loading slider %s from %s has exceeded a preset count of %d.", lineCount, lSide.c_str(), fullPath.c_str(), presetCount); - } - sliderInternal.presetCount = presetCount; - - } - break; - case SliderInternal::kTypeHeadPart: - { - sliderInternal.presetCount = atoi(params[2].c_str()); - } - break; - } -#ifdef _DEBUG_DATAREADER - _DMESSAGE("ReadSliders Info - Line (%d) Added Slider (%s, %d, %d, %d, %s, %s) to Gender %d %s from %s.", lineCount, sliderInternal.name.data, sliderInternal.category, sliderInternal.type, sliderInternal.presetCount, sliderInternal.lowerBound.data, sliderInternal.upperBound.data, gender, lSide.c_str(), fullPath.c_str()); -#endif - sliderMap->AddSlider(sliderName, gender, sliderInternal); - } - - return sliderMap; -} - -#ifdef _DEBUG_DATADUMP -void SliderMap::DumpMap() -{ - for(SliderMap::iterator it = begin(); it != end(); ++it) - { - SliderGender * gender = it->second; - if(gender->slider[0]) - _DMESSAGE("Slider - Name: %s Gender: Male Type: %d Cat: %d LowerBound: %s UpperBound: %s PresetCount: %d", it->first.data, gender->slider[0]->type, gender->slider[0]->category, gender->slider[0]->lowerBound.data, gender->slider[0]->upperBound.data, gender->slider[0]->presetCount); - if(gender->slider[1]) - _DMESSAGE("Slider - Name: %s Gender: Female Type: %d Cat: %d LowerBound: %s UpperBound: %s PresetCount: %d", it->first.data, gender->slider[1]->type, gender->slider[1]->category, gender->slider[1]->lowerBound.data, gender->slider[1]->upperBound.data, gender->slider[1]->presetCount); - } -} - -void RaceMap::DumpMap() -{ - for(RaceMap::iterator it = begin(); it != end(); ++it) - { - _DMESSAGE("Race: %08X - %s", it->first->formID, it->first->editorId.data); - gLog.Indent(); - for(SliderSet::iterator sit = it->second.begin(); sit != it->second.end(); ++sit) - { - _DMESSAGE("Map: %08X", (*sit)); - (*sit)->DumpMap(); - } - gLog.Outdent(); - } -} - -void MorphMap::DumpMap() -{ - for(MorphMap::iterator it = begin(); it != end(); ++it) - { - _DMESSAGE("Morph: %s", it->first.data); - DumpVisitor visitor; - gLog.Indent(); - Visit(it->first, visitor); - gLog.Outdent(); - } -} - -void MorphHandler::DumpAll() -{ - m_raceMap.DumpMap(); - m_morphMap.DumpMap(); -} -#endif - -SliderInternalPtr MorphHandler::GetSlider(TESRace * race, UInt8 gender, BSFixedString name) -{ - SliderSetPtr sliderMaps = m_raceMap.GetSliderSet(race); - if(sliderMaps) - { - SliderInternalPtr sliderInternal; - sliderMaps->for_each_slider([&](SliderGenderPtr genders) { - sliderInternal = genders->slider[gender]; - if (sliderInternal && sliderInternal->name == name) - return true; - return false; - }); - if (sliderInternal) - return sliderInternal; - } - - return NULL; -} - - -bool sortFixedStrings(SliderInternalPtr s1, SliderInternalPtr s2) -{ - return s1->name.data < s2->name.data; -} - -SliderList * MorphHandler::CreateSliderList(TESRace * race, UInt8 gender) -{ - // Clear the old map before building the new - RaceSliders::iterator it = m_internalMap.find(race); - if(it != m_internalMap.end()) { - it->second.clear(); - } - - SliderSetPtr sliderMaps = m_raceMap.GetSliderSet(race); - if(sliderMaps) - { - sliderMaps->for_each_slider([&](SliderGenderPtr genders) { - SliderInternalPtr sliderInternal = genders->slider[gender]; - if (sliderInternal) - AddSlider(race, sliderInternal); - return false; - }); - } - - // Return the list - it = m_internalMap.find(race); - if(it != m_internalMap.end()) { - std::sort(it->second.begin(), it->second.end(), sortFixedStrings); - it->second.resize(it->second.size()); - return &it->second; - } - - return NULL; -} - -void MorphHandler::AddSlider(TESRace * race, SliderInternalPtr & slider) -{ - RaceSliders::iterator it = m_internalMap.find(race); - if(it != m_internalMap.end()) { - it->second.push_back(slider); - } else { - SliderList newList; - newList.push_back(slider); - m_internalMap.emplace(race, newList); - } -} - -void MorphHandler::ApplyMorph(TESNPC * npc, BGSHeadPart * headPart, BSFaceGenNiNode * faceNode) -{ - char buffer[MAX_PATH]; - - auto sculptTarget = GetSculptTarget(npc, false); - if (sculptTarget) { - if (headPart) { - - NiAVObject * object = faceNode->GetObjectByName(&headPart->partName.data); - if (object) { - BSGeometry * geometry = object->GetAsBSGeometry(); - if (geometry) { - auto sculptHost = sculptTarget->GetSculptHost(SculptData::GetHostByPart(headPart), false); - if (sculptHost) { - BSFaceGenBaseMorphExtraData * extraData = (BSFaceGenBaseMorphExtraData *)geometry->GetExtraData("FOD"); - if (extraData) { - for (auto data : *sculptHost) - extraData->vertexData[data.first] += data.second; - } - } - } - } - } - } - - if (!g_extendedMorphs) - return; - - ValueSet * valueSet = m_valueMap.GetValueSet(npc); - if(!valueSet) - return; - - UInt8 gender = CALL_MEMBER_FN(npc, GetSex)(); - - for(auto it = valueSet->begin(); it != valueSet->end(); ++it) - { - SliderInternalPtr slider = GetSlider(npc->race.race, gender, it->first); - if(slider) { - if(slider->type == SliderInternal::kTypePreset) { - if(it->second != 0) { // There should be no zero morph for presets - memset(buffer, 0, MAX_PATH); - sprintf_s(buffer, MAX_PATH, "%s%d", slider->lowerBound.data, (UInt32)it->second); - BSFixedString morphName(buffer); -#ifdef _DEBUG_MORPH - _DMESSAGE("Applying Single Preset %s value %f", morphName.data, it->value); -#endif - CALL_MEMBER_FN(FaceGen::GetSingleton(), ApplyMorph)(faceNode, headPart, &morphName, 1.0); - } - } else { - BSFixedString morphName = slider->lowerBound; - if(it->second < 0) - morphName = slider->lowerBound; - if(it->second > 0) - morphName = slider->upperBound; - - float relative = abs(it->second); - if(relative > 1.0) { - UInt32 count = (UInt32)relative; - float difference = relative - count; - for(UInt32 i = 0; i < count; i++) - CALL_MEMBER_FN(FaceGen::GetSingleton(), ApplyMorph)(faceNode, headPart, &morphName, 1.0); - relative = difference; - } -#ifdef _DEBUG_MORPH - _DMESSAGE("Applying Single Slider %s value %f", morphName.data, it->value); -#endif - CALL_MEMBER_FN(FaceGen::GetSingleton(), ApplyMorph)(faceNode, headPart, &morphName, relative); - } - } - } -} - -void MorphHandler::ApplyMorphs(TESNPC * npc, BSFaceGenNiNode * faceNode) -{ - char buffer[MAX_PATH]; - - - auto sculptTarget = GetSculptTarget(npc, false); - if (sculptTarget) { - VisitObjects(faceNode, [&](NiAVObject* object) - { - if (BSGeometry * geometry = object->GetAsBSGeometry()) { - std::string headPartName = object->m_name; - BGSHeadPart * headPart = GetHeadPartByName(headPartName); - if (headPart) { - auto sculptHost = sculptTarget->GetSculptHost(SculptData::GetHostByPart(headPart), false); - if (sculptHost) { - BSFaceGenBaseMorphExtraData * extraData = (BSFaceGenBaseMorphExtraData *)geometry->GetExtraData("FOD"); - if (extraData) { - for (auto data : *sculptHost) - extraData->vertexData[data.first] += data.second; - } - } - } - } - - return false; - }); - } - - if (!g_extendedMorphs) - return; - - ValueSet * valueSet = m_valueMap.GetValueSet(npc); - if(!valueSet) - return; - - UInt8 gender = CALL_MEMBER_FN(npc, GetSex)(); - - - for(auto it = valueSet->begin(); it != valueSet->end(); ++it) - { - SliderInternalPtr slider = GetSlider(npc->race.race, gender, it->first); - if(slider) { - if(slider->type == SliderInternal::kTypePreset) { - if(it->second != 0) { // There should be no zero morph for presets - memset(buffer, 0, MAX_PATH); - sprintf_s(buffer, MAX_PATH, "%s%d", slider->lowerBound.data, (UInt32)it->second); - BSFixedString morphName(buffer); -#ifdef _DEBUG_MORPH - _DMESSAGE("Applying Full Preset %s value %f", morphName.data, it->value); -#endif - SetMorph(npc, faceNode, morphName.data, 1.0); - } - } else { - BSFixedString morphName = slider->lowerBound; - if(it->second < 0.0) - morphName = slider->lowerBound; - if(it->second > 0.0) - morphName = slider->upperBound; - - float relative = abs(it->second); - if(relative > 1.0) { - UInt32 count = (UInt32)relative; - float difference = relative - count; - for(UInt32 i = 0; i < count; i++) - SetMorph(npc, faceNode, morphName.data, 1.0); - relative = difference; - } - -#ifdef _DEBUG_MORPH - _DMESSAGE("Applying Full Slider %s value %f", morphName.data, it->value); -#endif - SetMorph(npc, faceNode, morphName.data, relative); - } - } - } -} - -void MorphHandler::SetMorph(TESNPC * npc, BSFaceGenNiNode * faceNode, const char * name, float relative) -{ -#ifdef _DEBUG_MORPH - _DMESSAGE("Applying Morph %s", name); -#endif - BSFixedString morphName(name); - FaceGenApplyMorph(FaceGen::GetSingleton(), faceNode, npc, &morphName, relative); -} - -SInt32 MorphHandler::LoadSliders(tArray * sliderArray, RaceMenuSlider * slider) -{ - PlayerCharacter * player = (*g_thePlayer); - TESNPC * npc = DYNAMIC_CAST(player->baseForm, TESForm, TESNPC); - - UInt32 sliderId = sliderArray->count; - UInt32 morphIndex = SLIDER_OFFSET; - - currentList = CreateSliderList(player->race, CALL_MEMBER_FN(npc, GetSex)()); - if(!currentList) - return sliderId; - - ValueSet * valueSet = m_valueMap.GetValueSet(npc); - - // Clean up invalid morphs - if(valueSet) { - ValueSet::iterator it = valueSet->begin(); - while (it != valueSet->end()) { - bool foundMorph = false; - for(auto mit = currentList->begin(); mit != currentList->end(); ++mit) { - SliderInternalPtr slider = (*mit); - if(slider->name == it->first) { - foundMorph = true; - break; - } - } - - if (!foundMorph) { - _DMESSAGE("Erasing %s", it->first.data); - valueSet->erase(it++); - } - else - it++; - } - } - - UInt32 i = 0; - for(auto it = currentList->begin(); it != currentList->end(); ++it) - { - SliderInternalPtr slider = (*it); - std::string sliderName = "$"; - sliderName.append(slider->name.data); - - float value = valueSet ? valueSet->GetValue(slider->name) : 0.0; - - UInt32 sliderIndex = morphIndex + i; - float lowerBound = slider->lowerBound == BSFixedString("") ? 0.0 : -1.0; - float upperBound = slider->upperBound == BSFixedString("") ? 0.0 : 1.0; - float interval = g_sliderInterval; - float lowerMultiplier = g_sliderMultiplier; - float upperMultiplier = g_sliderMultiplier; - - if(slider->type == SliderInternal::kTypePreset) { - lowerBound = 0.0; - interval = 1; - lowerMultiplier = 1.0; - upperMultiplier = 1.0; - upperBound = (float)slider->presetCount; - } else if(slider->type == SliderInternal::kTypeHeadPart) { - lowerBound = 0.0; - interval = 1; - lowerMultiplier = 1.0; - upperMultiplier = 1.0; - HeadPartList * headPartList = g_partSet.GetPartList(slider->presetCount); - BGSHeadPart * headPart = npc->GetHeadPartByType(slider->presetCount); - SInt32 partIndex = -1; - if(headPart && headPartList) - partIndex = g_partSet.GetPartIndex(headPartList, headPart); - if(partIndex != -1) - value = (float)(partIndex + 1); - if(headPartList) - upperBound = (float)headPartList->size(); - else - upperBound = 0; - } - - BSFixedString morphName(sliderName.c_str()); - -#ifdef _DEBUG_SLIDER - _DMESSAGE("Adding slider: %s Morph: %s Value: %f SliderID: %d Index: %d", morphName.data, slider->name.data, value, sliderId, sliderIndex); -#endif - - RaceMenuSlider newSlider(slider->category, morphName.c_str(), "ChangeDoubleMorph", sliderId++, sliderIndex, 2, 1, lowerBound * lowerMultiplier, upperBound * upperMultiplier, value, interval, 0); - AddRaceMenuSlider(sliderArray, &newSlider); - i++; - } - - return sliderId; -} - -void MorphHandler::Save(SKSESerializationInterface * intfc, UInt32 kVersion) -{ - PlayerCharacter * player = (*g_thePlayer); - TESNPC * npc = DYNAMIC_CAST(player->baseForm, TESForm, TESNPC); - - auto sculptData = m_sculptStorage.GetSculptTarget(npc, false); - if (sculptData) { - if (sculptData->size() > 0) { - intfc->OpenRecord('SCDT', kVersion); - - UInt16 numValidParts = 0; - for (auto part : *sculptData) { - if (part.first.data[0] != 0 && part.second->size() > 0) { - numValidParts++; - } - } - - intfc->WriteRecordData(&numValidParts, sizeof(numValidParts)); - if (numValidParts > 0) { - for (auto part : *sculptData) { - UInt16 diffCount = part.second->size(); - if (diffCount > 0) { - UInt16 length = strlen(part.first.data); - intfc->OpenRecord('SCPT', kVersion); - intfc->WriteRecordData(&length, sizeof(length)); - intfc->WriteRecordData(part.first.data, length); - intfc->WriteRecordData(&diffCount, sizeof(diffCount)); - - for (auto diff : *part.second) { - intfc->WriteRecordData(&diff.first, sizeof(diff.first)); - intfc->WriteRecordData(&diff.second, sizeof(NiPoint3)); - } - } - } - } - } - } - - ValueSet * valueSet = m_valueMap.GetValueSet(npc); - if (valueSet) { - // Count only non-zero morphs - UInt32 numMorphs = 0; - for (auto it = valueSet->begin(); it != valueSet->end(); ++it) { - if (it->second != 0.0) - numMorphs++; - } - - if (numMorphs > 0) { - intfc->OpenRecord('MRST', kVersion); - intfc->WriteRecordData(&numMorphs, sizeof(numMorphs)); - for (auto it = valueSet->begin(); it != valueSet->end(); ++it) { - if (it->second != 0.0) { - UInt16 length = strlen(it->first.data); - intfc->OpenRecord('MRPH', kVersion); - intfc->WriteRecordData(&length, sizeof(length)); - intfc->WriteRecordData(it->first.data, length); - intfc->WriteRecordData(&it->second, sizeof(it->second)); - } - } - } - } -} - -bool MorphHandler::LoadMorphData(SKSESerializationInterface * intfc, UInt32 version) -{ - UInt32 type; - UInt32 length; - - bool error = false; - - PlayerCharacter * player = (*g_thePlayer); - TESNPC * playerBase = DYNAMIC_CAST(player->baseForm, TESForm, TESNPC); - - UInt32 numMorphs = 0; - if (!intfc->ReadRecordData(&numMorphs, sizeof(numMorphs))) - { - _MESSAGE("Error loading morph count"); - error = true; - return true; - } - - for (UInt32 i = 0; i < numMorphs; i++) - { - char * name = NULL; - UInt32 index = 0; - float value = 0.0; - - if (intfc->GetNextRecordInfo(&type, &version, &length)) - { - switch (type) - { - case 'MRPH': - { - UInt16 nameLength = 0; - if (!intfc->ReadRecordData(&nameLength, sizeof(nameLength))) { - _MESSAGE("Error loading morph name length"); - error = true; - return true; - } - - name = new char[nameLength + 1]; - if (!intfc->ReadRecordData(name, nameLength)) { - _MESSAGE("Error loading morph name"); - error = true; - return true; - } - name[nameLength] = 0; - - if (!intfc->ReadRecordData(&value, sizeof(value))) { - _MESSAGE("Error loading morph value"); - error = true; - return true; - } - } - break; - default: - _MESSAGE("unhandled type %08X", type); - error = true; - break; - } - } - - if (value != 0.0) { - _MESSAGE("Loaded Morph: %s - Value: %f", name, value); - m_valueMap.SetMorphValue(playerBase, BSFixedString(name), value); - } - } - - return error; -} - -bool MorphHandler::LoadSculptData(SKSESerializationInterface * intfc, UInt32 version) -{ - UInt32 type; - UInt32 length; - bool error = false; - - PlayerCharacter * player = (*g_thePlayer); - TESNPC * playerBase = DYNAMIC_CAST(player->baseForm, TESForm, TESNPC); - - UInt16 numParts = 0; - if (!intfc->ReadRecordData(&numParts, sizeof(numParts))) - { - _MESSAGE("Error loading sculpt part count"); - error = true; - return true; - } - - for (UInt32 i = 0; i < numParts; i++) - { - if (intfc->GetNextRecordInfo(&type, &version, &length)) - { - switch (type) - { - case 'SCPT': - { - UInt16 nameLength = 0; - if (!intfc->ReadRecordData(&nameLength, sizeof(nameLength))) { - _MESSAGE("Error loading sculpt part name length"); - error = true; - return true; - } - - char * name = new char[nameLength + 1]; - if (!intfc->ReadRecordData(name, nameLength)) { - _MESSAGE("Error loading sculpt part name"); - error = true; - return true; - } - name[nameLength] = 0; - - UInt16 totalDifferences = 0; - if (!intfc->ReadRecordData(&totalDifferences, sizeof(totalDifferences))) { - _MESSAGE("Error loading sculpt difference count"); - error = true; - return true; - } - - SculptDataPtr sculptTarget; - if (totalDifferences > 0) - sculptTarget = m_sculptStorage.GetSculptTarget(playerBase, true); - MappedSculptDataPtr sculptHost; - if (sculptTarget && totalDifferences > 0) - sculptHost = sculptTarget->GetSculptHost(BSFixedString(name), true); - - UInt16 index = 0; - NiPoint3 value; - for (UInt16 i = 0; i < totalDifferences; i++) - { - if (!intfc->ReadRecordData(&index, sizeof(index))) { - _MESSAGE("Error loading sculpt index"); - error = true; - return true; - } - - if (!intfc->ReadRecordData(&value, sizeof(value))) { - _MESSAGE("Error loading sculpt index"); - error = true; - return true; - } - - if (sculptTarget && sculptHost) - sculptHost->force_insert(std::make_pair(index, value)); - } - } - break; - default: - _MESSAGE("unhandled type %08X", type); - error = true; - break; - } - } - } - - return error; -} - -struct PresetHeader -{ - enum - { - kSignature = MACRO_SWAP32('SKSE'), // endian-swapping so the order matches - kVersion = 3, - - kVersion_Invalid = 0 - }; - - UInt32 signature; - UInt32 formatVersion; - UInt32 skseVersion; - UInt32 runtimeVersion; -}; - -#include - -bool MorphHandler::SaveJsonPreset(const char * filePath) -{ - Json::StyledWriter writer; - Json::Value root; - - IFileStream currentFile; - IFileStream::MakeAllDirs(filePath); - if (!currentFile.Create(filePath)) - { - _ERROR("%s: couldn't create preset file (%s) Error (%d)", __FUNCTION__, filePath, GetLastError()); - return true; - } - - Json::Value versionInfo; - versionInfo["signature"] = PresetHeader::kSignature; - versionInfo["formatVersion"] = PresetHeader::kVersion; - versionInfo["skseVersion"] = PACKED_SKSE_VERSION; - versionInfo["runtimeVersion"] = RUNTIME_VERSION_1_4_2; - - - PlayerCharacter * player = (*g_thePlayer); - TESNPC * npc = DYNAMIC_CAST(player->baseForm, TESForm, TESNPC); - DataHandler * dataHandler = DataHandler::GetSingleton(); - - bool isFemale = false; - if (npc) - isFemale = CALL_MEMBER_FN(npc, GetSex)() == 1; - - std::map modListLegacy; - std::set modList; - std::map partList; - - UInt32 numHeadParts = 0; - BGSHeadPart ** headParts = NULL; - if (CALL_MEMBER_FN(npc, HasOverlays)()) { - numHeadParts = GetNumActorBaseOverlays(npc); - headParts = GetActorBaseOverlays(npc); - } - else { - numHeadParts = npc->numHeadParts; - headParts = npc->headparts; - } - - // Acquire only vanilla dependencies - for (UInt32 i = 0; i < numHeadParts; i++) - { - BGSHeadPart * headPart = headParts[i]; - if (headPart && !headPart->IsExtraPart()) { - ModInfo * modInfo = GetModInfoByFormID(headPart->formID, false); - if (modInfo) { - modListLegacy.emplace(modInfo->modIndex, modInfo->name); - } - - partList.emplace(i, headPart); - } - } - - // Acquire all mod dependencies - for (UInt32 i = 0; i < numHeadParts; i++) - { - BGSHeadPart * headPart = headParts[i]; - if (headPart && !headPart->IsExtraPart()) { - ModInfo * modInfo = GetModInfoByFormID(headPart->formID, true); - if (modInfo) { - modList.emplace(modInfo->name); - } - } - } - - std::map> tintList; - for (UInt32 i = 0; i < player->tintMasks.count; i++) - { - TintMask * tintMask = NULL; - if (player->tintMasks.GetNthItem(i, tintMask)) - { - UInt32 tintColor = ((UInt32)(tintMask->alpha * 255.0) << 24) | tintMask->color.red << 16 | tintMask->color.green << 8 | tintMask->color.blue; - if (tintMask->texture) - tintList.emplace(i, std::make_pair(tintColor, tintMask->texture->str.data)); - } - } - - Json::Value modInfo; - for (auto mIt = modListLegacy.begin(); mIt != modListLegacy.end(); ++mIt) - { - Json::Value mod; - mod["index"] = mIt->first; - mod["name"] = mIt->second; - modInfo.append(mod); - } - - Json::Value modNames; - for (auto mIt = modList.begin(); mIt != modList.end(); ++mIt) - { - modNames.append(*mIt); - } - - Json::Value headPartInfo; - for (auto pIt = partList.begin(); pIt != partList.end(); ++pIt) - { - Json::Value partInfo; - partInfo["type"] = pIt->first; - partInfo["formId"] = (Json::UInt)pIt->second->formID; - partInfo["formIdentifier"] = GetFormIdentifier(pIt->second); - headPartInfo.append(partInfo); - } - - Json::Value tintInfo; - for (auto tmIt = tintList.begin(); tmIt != tintList.end(); ++tmIt) - { - Json::Value tint; - tint["index"] = tmIt->first; - tint["color"] = (Json::UInt)tmIt->second.first; - tint["texture"] = tmIt->second.second; - tintInfo.append(tint); - } - - Json::Value morphInfo; - if (npc->faceMorph) - { - for (UInt8 p = 0; p < TESNPC::FaceMorphs::kNumPresets; p++) { - Json::Value morphValue = (Json::UInt)npc->faceMorph->presets[p]; - morphInfo["presets"].append(morphValue); - } - - for (UInt8 o = 0; o < TESNPC::FaceMorphs::kNumOptions; o++) { - Json::Value morphValue = npc->faceMorph->option[o]; - morphInfo["morphs"].append(morphValue); - } - } - - Json::Value customMorphInfo; - ValueSet * valueSet = m_valueMap.GetValueSet(npc); - if (valueSet) - { - for (auto it = valueSet->begin(); it != valueSet->end(); ++it) - { - if (it->second != 0.0) { - Json::Value morphValue; - morphValue["name"] = it->first.data; - morphValue["value"] = it->second; - customMorphInfo.append(morphValue); - } - } - } - - - Json::Value sculptData; - auto sculptTarget = GetSculptTarget(npc, false); - if (sculptTarget) { - for (UInt32 i = 0; i < numHeadParts; i++) // Acquire all unique parts - { - BGSHeadPart * headPart = headParts[i]; - if (headPart) { - BSFixedString morphPath = SculptData::GetHostByPart(headPart); - auto sculptHost = sculptTarget->GetSculptHost(morphPath, false); - if (sculptHost) { - Json::Value hostData; - hostData["host"] = morphPath.data; - - TRIModelData data; - GetModelTri(morphPath, data); - - hostData["vertices"] = (Json::UInt)data.vertexCount; - - for (auto morph : *sculptHost) { - Json::Value value; - value.append(morph.first); - value.append((Json::Int)(morph.second.x * VERTEX_MULTIPLIER)); - value.append((Json::Int)(morph.second.y * VERTEX_MULTIPLIER)); - value.append((Json::Int)(morph.second.z * VERTEX_MULTIPLIER)); - hostData["data"].append(value); - } - - sculptData.append(hostData); - } - } - } - } - - Json::Value textureInfo; - BGSHeadPart * facePart = npc->GetCurrentHeadPartByType(BGSHeadPart::kTypeFace); - if (facePart) { - BGSTextureSet * textureSet = GetTextureSetForPart(npc, facePart); - if (textureSet) { - for (UInt8 i = 0; i < BSShaderTextureSet::kNumTextures; i++) { - const char * texturePath = textureSet->textureSet.GetTexturePath(i); - if (texturePath != NULL) { - Json::Value textureValue; - textureValue["index"] = i; - textureValue["texture"] = texturePath; - textureInfo.append(textureValue); - } - } - } - } - - // Collect override data - PresetData::OverrideData overrideData; - g_overrideInterface.VisitNodes(player, [&overrideData](BSFixedString node, OverrideVariant & value) - { - overrideData[node].push_back(value); - }); - - // Collect skin data - PresetData::SkinData skinData[2]; - for (UInt32 i = 0; i <= 1; i++) { - g_overrideInterface.VisitSkin(player, isFemale, i == 1, [&i, &skinData](UInt32 slotMask, OverrideVariant & value) - { - skinData[i][slotMask].push_back(value); - return false; - }); - } - - // Collect transform data - PresetData::TransformData transformData[2]; - for (UInt32 i = 0; i <= 1; i++) { - g_transformInterface.VisitNodes(player, i == 1, isFemale, [&i, &transformData](BSFixedString node, OverrideRegistration * keys) - { - keys->Visit([&i, &node, &transformData](const BSFixedString & key, OverrideSet * set) - { - if (key == BSFixedString("internal")) - return false; - - set->Visit([&i, &node, &transformData, &key](OverrideVariant * value) - { - transformData[i][node][key].push_back(*value); - return false; - }); - return false; - }); - - return false; - }); - } - - // Collect body morph data - PresetData::BodyMorphData bodyMorphData; - g_bodyMorphInterface.VisitMorphs(player, [&](BSFixedString name, std::unordered_map * map) - { - for (auto & it : *map) - { - bodyMorphData[name][it.first] = it.second; - } - }); - - for (UInt32 i = 0; i <= 1; i++) { - for (auto & data : transformData[i]) { - Json::Value transform; - transform["firstPerson"] = (bool)(i == 1); - transform["node"] = data.first.data; - - for (auto & key : data.second) { - Json::Value transformKey; - transformKey["name"] = key.first.data; - - for (auto & value : key.second) { - Json::Value jvalue; - jvalue["key"] = value.key; - jvalue["type"] = value.type; - jvalue["index"] = value.index; - switch (value.type) { - case OverrideVariant::kType_Bool: - jvalue["data"] = value.data.b; - break; - case OverrideVariant::kType_Int: - jvalue["data"] = value.data.i; - break; - case OverrideVariant::kType_Float: - jvalue["data"] = value.data.f; - break; - case OverrideVariant::kType_String: - jvalue["data"] = value.data.GetStr()->data; - break; - } - transformKey["values"].append(jvalue); - } - transform["keys"].append(transformKey); - } - root["transforms"].append(transform); - } - } - for (auto & data : overrideData) { - Json::Value ovr; - ovr["node"] = data.first.data; - - for (auto & value : data.second) { - Json::Value jvalue; - jvalue["key"] = value.key; - jvalue["type"] = value.type; - jvalue["index"] = value.index; - switch (value.type) { - case OverrideVariant::kType_Bool: - jvalue["data"] = value.data.b; - break; - case OverrideVariant::kType_Int: - jvalue["data"] = value.data.i; - break; - case OverrideVariant::kType_Float: - jvalue["data"] = value.data.f; - break; - case OverrideVariant::kType_String: - jvalue["data"] = value.data.GetStr()->data; - break; - } - ovr["values"].append(jvalue); - } - root["overrides"].append(ovr); - } - - for (UInt32 i = 0; i <= 1; i++) { - for (auto & data : skinData[i]) { - Json::Value slot; - slot["firstPerson"] = (bool)(i == 1); - slot["slotMask"] = (Json::UInt)data.first; - - for (auto & value : data.second) { - Json::Value jvalue; - jvalue["key"] = value.key; - jvalue["type"] = value.type; - jvalue["index"] = value.index; - switch (value.type) { - case OverrideVariant::kType_Bool: - jvalue["data"] = value.data.b; - break; - case OverrideVariant::kType_Int: - jvalue["data"] = value.data.i; - break; - case OverrideVariant::kType_Float: - jvalue["data"] = value.data.f; - break; - case OverrideVariant::kType_String: - jvalue["data"] = value.data.GetStr()->data; - break; - } - slot["values"].append(jvalue); - } - - root["skinOverrides"].append(slot); - } - } - - for (auto & data : bodyMorphData) { - Json::Value bm; - bm["name"] = data.first.data; - for (auto & keys : data.second) - { - Json::Value jvalue; - jvalue["key"] = keys.first.data; - jvalue["value"] = keys.second; - bm["keys"].append(jvalue); - } - root["bodyMorphs"].append(bm); - } - - root["version"] = versionInfo; - root["mods"] = modInfo; - root["modNames"] = modNames; - root["headParts"] = headPartInfo; - root["actor"]["weight"] = npc->weight; - - if (npc->headData) { - auto hairColor = npc->headData->hairColor; - if (hairColor) - root["actor"]["hairColor"] = (Json::UInt)(hairColor->color.red << 16 | hairColor->color.green << 8 | hairColor->color.blue); - } - - root["tintInfo"] = tintInfo; - root["faceTextures"] = textureInfo; - root["morphs"]["default"] = morphInfo; - root["morphs"]["custom"] = customMorphInfo; - root["morphs"]["sculptDivisor"] = VERTEX_MULTIPLIER; - root["morphs"]["sculpt"] = sculptData; - - std::string data = writer.write(root); - currentFile.WriteBuf(data.c_str(), data.length()); - currentFile.Close(); - return false; -} - -bool MorphHandler::SaveBinaryPreset(const char * filePath) -{ - IFileStream currentFile; - IFileStream::MakeAllDirs(filePath); - - _DMESSAGE("creating preset"); - if(!currentFile.Create(filePath)) - { - _ERROR("%s: couldn't create preset file (%s) Error (%d)", __FUNCTION__, filePath, GetLastError()); - return true; - } - - try - { - PresetHeader fileHeader; - fileHeader.signature = PresetHeader::kSignature; - fileHeader.formatVersion = PresetHeader::kVersion; - fileHeader.skseVersion = PACKED_SKSE_VERSION; - fileHeader.runtimeVersion = RUNTIME_VERSION_1_4_2; - - currentFile.Skip(sizeof(fileHeader)); - - PlayerCharacter * player = (*g_thePlayer); - TESNPC * npc = DYNAMIC_CAST(player->baseForm, TESForm, TESNPC); - DataHandler * dataHandler = DataHandler::GetSingleton(); - - typedef std::map ModMap; - typedef std::pair ModPair; - - typedef std::map PartMap; - typedef std::pair PartPair; - - typedef std::pair TintCouple; - typedef std::map TintMap; - typedef std::pair TintPair; - - ModMap modList; - PartMap partList; - - UInt32 numHeadParts = 0; - BGSHeadPart ** headParts = NULL; - if (CALL_MEMBER_FN(npc, HasOverlays)()) { - numHeadParts = GetNumActorBaseOverlays(npc); - headParts = GetActorBaseOverlays(npc); - } else { - numHeadParts = npc->numHeadParts; - headParts = npc->headparts; - } - for (UInt32 i = 0; i < numHeadParts; i++) // Acquire all unique parts - { - BGSHeadPart * headPart = headParts[i]; - if(headPart && !headPart->IsExtraPart()) { - ModInfo* modInfo = GetModInfoByFormID(headPart->formID); - if(modInfo) { - modList.emplace(modInfo->modIndex, modInfo->name); - partList.emplace(i, headPart); - } - } - } - - TintMap tintList; - for(UInt32 i = 0; i < player->tintMasks.count; i++) - { - TintMask * tintMask = NULL; - if(player->tintMasks.GetNthItem(i, tintMask)) - { - UInt32 tintColor = ((UInt32)(tintMask->alpha * 255.0) << 24) | tintMask->color.red << 16 | tintMask->color.green << 8 | tintMask->color.blue; - tintList.emplace(i, TintCouple(tintColor, tintMask->texture->str.data)); - } - } - - UInt8 modCount = modList.size(); - UInt8 partCount = partList.size(); - UInt8 tintCount = tintList.size(); - - currentFile.Write8(modCount); - for(auto mIt = modList.begin(); mIt != modList.end(); ++mIt) - { - currentFile.Write8(mIt->first); - - UInt16 strLen = strlen(mIt->second); - currentFile.Write16(strLen); - currentFile.WriteBuf(mIt->second, strLen); - } - - currentFile.Write8(partCount); - for(auto pIt = partList.begin(); pIt != partList.end(); ++pIt) - { - currentFile.Write8(pIt->first); - currentFile.Write32(pIt->second->formID); - } - - currentFile.WriteFloat(npc->weight); - - if (npc->faceMorph) - { - currentFile.Write8(TESNPC::FaceMorphs::kNumPresets); - for (UInt8 p = 0; p < TESNPC::FaceMorphs::kNumPresets; p++) - currentFile.Write8(npc->faceMorph->presets[p]); - - currentFile.Write8(TESNPC::FaceMorphs::kNumOptions); - for (UInt8 o = 0; o < TESNPC::FaceMorphs::kNumOptions; o++) - currentFile.WriteFloat(npc->faceMorph->option[o]); - } - else { - currentFile.Write8(0); - currentFile.Write8(0); - } - - UInt32 hairColor = 0; - if(npc->headData && npc->headData->hairColor) { - hairColor = npc->headData->hairColor->color.red << 16 | npc->headData->hairColor->color.green << 8 | npc->headData->hairColor->color.blue; - } - currentFile.Write32(hairColor); - - currentFile.Write8(tintCount); - for(auto tmIt = tintList.begin(); tmIt != tintList.end(); ++tmIt) - { - currentFile.Write8(tmIt->first); - currentFile.Write32(tmIt->second.first); - - UInt16 strLen = strlen(tmIt->second.second); - currentFile.Write16(strLen); - currentFile.WriteBuf(tmIt->second.second, strLen); - } - - SInt64 offset = currentFile.GetOffset(); - currentFile.Skip(sizeof(UInt8)); - UInt8 totalMorphs = 0; - - ValueSet * valueSet = m_valueMap.GetValueSet(npc); - if(valueSet) - { - for(auto it = valueSet->begin(); it != valueSet->end(); ++it) - { - if(it->second != 0.0) { - UInt16 strLen = strlen(it->first.data); - currentFile.Write16(strLen); - currentFile.WriteBuf(it->first.data, strLen); - - currentFile.WriteFloat(it->second); - totalMorphs++; - } - } - } - - SInt64 jumpBack = currentFile.GetOffset(); - currentFile.SetOffset(offset); - currentFile.Write8(totalMorphs); - - currentFile.SetOffset(jumpBack); - offset = currentFile.GetOffset(); - currentFile.Skip(sizeof(UInt8)); - UInt8 totalTextures = 0; - BGSHeadPart * facePart = npc->GetCurrentHeadPartByType(BGSHeadPart::kTypeFace); - if (facePart) { - BGSTextureSet * textureSet = GetTextureSetForPart(npc, facePart); - if (textureSet) { - for (UInt8 i = 0; i < BSShaderTextureSet::kNumTextures; i++) { - const char * texturePath = textureSet->textureSet.GetTexturePath(i); - if (texturePath != NULL) { - UInt16 strLen = strlen(texturePath); - currentFile.Write8(i); - currentFile.Write16(strLen); - currentFile.WriteBuf(texturePath, strLen); - totalTextures++; - } - } - } - } - currentFile.SetOffset(offset); - currentFile.Write8(totalTextures); - - // write header - currentFile.SetOffset(0); - currentFile.WriteBuf(&fileHeader, sizeof(fileHeader)); - - } - catch(...) - { - _ERROR("SavePreset: exception during save"); - } - - currentFile.Close(); - return false; -} - -PresetData::PresetData() -{ - weight = 0; - hairColor = 0; -} - -bool MorphHandler::LoadJsonPreset(const char * filePath, PresetDataPtr presetData) -{ - bool loadError = false; - BSResourceNiBinaryStream file(filePath); - if (!file.IsValid()) { - _ERROR("%s: File %s failed to open.", __FUNCTION__, filePath); - loadError = true; - return loadError; - } - - std::string in; - BSReadAll(&file, &in); - - Json::Features features; - features.all(); - - Json::Value root; - Json::Reader reader(features); - - bool parseSuccess = reader.parse(in, root); - if (!parseSuccess) { - _ERROR("%s: Error occured parsing json for %s.", __FUNCTION__, filePath); - loadError = true; - return loadError; - } - - Json::Value defaultValue; - Json::Value version = root["version"]; - if (version.empty()) { - _ERROR("%s: No version header.", __FUNCTION__); - loadError = true; - return loadError; - } - - UInt32 signature = version["signature"].asUInt(); - if (signature != PresetHeader::kSignature) - { - _ERROR("%s: invalid file signature (found %08X expected %08X)", __FUNCTION__, signature, PresetHeader::kSignature); - loadError = true; - return loadError; - } - - UInt32 formatVersion = version["formatVersion"].asUInt(); - if (formatVersion <= PresetHeader::kVersion_Invalid) - { - _ERROR("%s: version invalid (%08X)", __FUNCTION__, formatVersion); - loadError = true; - return loadError; - } - - Json::Value mods = root["mods"]; - Json::Value modNames = root["modNames"]; - if (mods.empty() && modNames.empty()) { - _ERROR("%s: No mods header.", __FUNCTION__); - loadError = true; - return loadError; - } - - DataHandler * dataHandler = DataHandler::GetSingleton(); - - std::map modList; - if (mods.type() == Json::arrayValue) { - for (auto & mod : mods) { - UInt32 modIndex = mod["index"].asUInt(); - std::string modName = mod["name"].asString(); - - modList.emplace(modIndex, modName); - presetData->modList.push_back(modName); - } - } - - if (root.isMember("modNames") && modNames.type() == Json::arrayValue) { - presetData->modList.clear(); - for (auto & mod : modNames) { - presetData->modList.push_back(mod.asString()); - } - } - - Json::Value headParts = root["headParts"]; - if (!headParts.empty() && headParts.type() == Json::arrayValue) { - for (auto & part : headParts) { - if (part.isMember("formIdentifier")) { - TESForm * headPartForm = GetFormFromIdentifier(part["formIdentifier"].asString()); - if (headPartForm) { - BGSHeadPart * headPart = DYNAMIC_CAST(headPartForm, TESForm, BGSHeadPart); - if (headPart) { - presetData->headParts.push_back(headPart); - } - } - } - else if (part.isMember("formId")) { - UInt8 partType = part["type"].asUInt(); - UInt32 formId = part["formId"].asUInt(); - - UInt32 modIndex = formId >> 24; - auto it = modList.find(modIndex); - if (it != modList.end()) { - UInt8 gameIndex = dataHandler->GetLoadedModIndex(it->second.c_str()); - if (gameIndex != 255) { - formId = (formId & 0x00FFFFFF) | (gameIndex << 24); - TESForm * headPartForm = LookupFormByID(formId); - if (headPartForm) { - BGSHeadPart * headPart = DYNAMIC_CAST(headPartForm, TESForm, BGSHeadPart); - if (headPart) { - presetData->headParts.push_back(headPart); - } - } - else { - _WARNING("Could not resolve part %08X", formId); - } - } - else { - _WARNING("Could not load part type %d from %s; mod not found.", partType, it->second.c_str()); - } - } - } - } - } - - Json::Value actor = root["actor"]; - if (!actor.empty() && actor.type() == Json::objectValue) { - presetData->weight = actor["weight"].asFloat(); - presetData->hairColor = actor["hairColor"].asUInt(); - } - - - Json::Value tintInfo = root["tintInfo"]; - if (!tintInfo.empty() && tintInfo.type() == Json::arrayValue) { - for (auto & tint : tintInfo) { - PresetData::Tint tintData; - tintData.color = tint["color"].asUInt(); - tintData.index = tint["index"].asUInt(); - tintData.name = tint["texture"].asString().c_str(); - presetData->tints.push_back(tintData); - } - } - - Json::Value faceTextures = root["faceTextures"]; - if (!faceTextures.empty() && faceTextures.type() == Json::arrayValue) { - for (auto & faceTexture : faceTextures) { - PresetData::Texture texture; - texture.index = faceTexture["index"].asUInt(); - texture.name = faceTexture["texture"].asString().c_str(); - presetData->faceTextures.push_back(texture); - } - } - - Json::Value morphs = root["morphs"]; - if (!morphs.empty()) { - Json::Value defaultMorphs = morphs["default"]; - if (!defaultMorphs.empty()) { - Json::Value presets = defaultMorphs["presets"]; - for (auto & preset : presets) { - UInt32 presetValue = preset.asUInt(); - if (presetValue == 255) - presetValue = -1; - - presetData->presets.push_back(presetValue); - } - - Json::Value morphs = defaultMorphs["morphs"]; - for (auto & morph : morphs) { - presetData->morphs.push_back(morph.asFloat()); - } - } - Json::Value customMorphs = morphs["custom"]; - if (!customMorphs.empty()) { - for (auto & customMorph : customMorphs) { - PresetData::Morph morph; - morph.name = customMorph["name"].asString().c_str(); - morph.value = customMorph["value"].asFloat(); - presetData->customMorphs.push_back(morph); - } - } - - SInt32 multiplier = -1; - - Json::Value sculptMult = morphs["sculptDivisor"]; - if (!sculptMult.empty()) - multiplier = sculptMult.asInt(); - - Json::Value sculptData = morphs["sculpt"]; - if (!sculptData.empty()) { - presetData->sculptData = std::make_shared(); - for (auto & hostFile : sculptData) { - BSFixedString host = hostFile["host"].asString().c_str(); - Json::Value data = hostFile["data"]; - - auto sculptedData = std::make_shared(); - for (auto & morphData : data) { - UInt16 index = morphData[0].asUInt(); - NiPoint3 pt; - - if (multiplier > 0) { - pt.x = (float)morphData[1].asInt() / (float)multiplier; - pt.y = (float)morphData[2].asInt() / (float)multiplier; - pt.z = (float)morphData[3].asInt() / (float)multiplier; - } else { - pt.x = morphData[1].asFloat(); - pt.y = morphData[2].asFloat(); - pt.z = morphData[3].asFloat(); - } - - sculptedData->force_insert(std::make_pair(index, pt)); - } - - presetData->sculptData->emplace(host, sculptedData); - } - } - } - - Json::Value transforms = root["transforms"]; - if (!transforms.empty()) { - for (auto & xForm : transforms) { - bool isFirstPerson = xForm["firstPerson"].asBool(); - BSFixedString nodeName = xForm["node"].asString().c_str(); - - Json::Value keys = xForm["keys"]; - for (auto & key : keys) { - BSFixedString keyName = key["name"].asString().c_str(); - - Json::Value values = key["values"]; - for (auto & jvalue : values) { - OverrideVariant value; - value.key = jvalue["key"].asUInt(); - value.type = jvalue["type"].asInt(); - value.index = jvalue["index"].asInt(); - switch (value.type) { - case OverrideVariant::kType_Bool: - value.data.b = jvalue["data"].asBool(); - break; - case OverrideVariant::kType_Int: - value.data.i = jvalue["data"].asInt(); - break; - case OverrideVariant::kType_Float: - value.data.f = jvalue["data"].asFloat(); - break; - case OverrideVariant::kType_String: - value.data.str = BSFixedString(jvalue["data"].asString().c_str()).data; - break; - } - - presetData->transformData[isFirstPerson ? 1 : 0][nodeName][keyName].push_back(value); - } - } - } - } - - Json::Value overrides = root["overrides"]; - if (!overrides.empty()) { - for (auto & ovr : overrides) { - BSFixedString node = ovr["node"].asString().c_str(); - Json::Value values = ovr["values"]; - for (auto & jvalue : values) { - OverrideVariant value; - value.key = jvalue["key"].asUInt(); - value.type = jvalue["type"].asInt(); - value.index = jvalue["index"].asInt(); - switch (value.type) { - case OverrideVariant::kType_Bool: - value.data.b = jvalue["data"].asBool(); - break; - case OverrideVariant::kType_Int: - value.data.i = jvalue["data"].asInt(); - break; - case OverrideVariant::kType_Float: - value.data.f = jvalue["data"].asFloat(); - break; - case OverrideVariant::kType_String: - value.data.str = BSFixedString(jvalue["data"].asString().c_str()).data; - break; - } - presetData->overrideData[node].push_back(value); - } - } - } - - Json::Value skinOverrides = root["skinOverrides"]; - if (!skinOverrides.empty()) { - for (auto & skinData : skinOverrides) { - bool isFirstPerson = skinData["firstPerson"].asBool(); - UInt32 slotMask = skinData["slotMask"].asUInt(); - - Json::Value values = skinData["values"]; - for (auto & jvalue : values) { - OverrideVariant value; - value.key = jvalue["key"].asUInt(); - value.type = jvalue["type"].asInt(); - value.index = jvalue["index"].asInt(); - switch (value.type) { - case OverrideVariant::kType_Bool: - value.data.b = jvalue["data"].asBool(); - break; - case OverrideVariant::kType_Int: - value.data.i = jvalue["data"].asInt(); - break; - case OverrideVariant::kType_Float: - value.data.f = jvalue["data"].asFloat(); - break; - case OverrideVariant::kType_String: - value.data.str = BSFixedString(jvalue["data"].asString().c_str()).data; - break; - } - - presetData->skinData[isFirstPerson ? 1 : 0][slotMask].push_back(value); - } - } - } - - Json::Value bodyMorphs = root["bodyMorphs"]; - if (!bodyMorphs.empty()) { - for (auto & bm : bodyMorphs) { - BSFixedString name = bm["name"].asString().c_str(); - - // Legacy version - Json::Value keyless = bm["value"]; - if (!keyless.empty()) - { - float value = bm["value"].asFloat(); - presetData->bodyMorphData[name]["RSMLegacy"] = value; - } - - // New version - Json::Value values = bm["keys"]; - if (!values.empty()) - { - for (auto & jvalue : values) { - BSFixedString key = jvalue["key"].asString().c_str(); - float value = jvalue["value"].asFloat(); - - // If the keys were mapped by mod name, skip them if they arent in load order - std::string strKey(key.data); - BSFixedString ext(strKey.substr(strKey.find_last_of(".") + 1).c_str()); - if (ext == BSFixedString("esp") || ext == BSFixedString("esm")) - { - if (!dataHandler->LookupLoadedModByName(key.data)) - continue; - } - - presetData->bodyMorphData[name][key] = value; - } - } - } - } - - return loadError; -} - -bool MorphHandler::LoadBinaryPreset(const char * filePath, PresetDataPtr presetData) -{ - bool loadError = false; - BSResourceNiBinaryStream file(filePath); - if (!file.IsValid()) { - _ERROR("%s: File %s failed to open.", __FUNCTION__, filePath); - loadError = true; - return loadError; - } - - try - { - PresetHeader header; - file.Read(&header, sizeof(header)); - - if(header.signature != PresetHeader::kSignature) - { - _ERROR("%s: invalid file signature (found %08X expected %08X)", __FUNCTION__, header.signature, PresetHeader::kSignature); - loadError = true; - goto done; - } - - if(header.formatVersion <= PresetHeader::kVersion_Invalid) - { - _ERROR("%s: version invalid (%08X)", __FUNCTION__, header.formatVersion); - loadError = true; - goto done; - } - - if(header.formatVersion < 2) - { - _ERROR("%s: version too old (found %08X current %08X)", __FUNCTION__, header.formatVersion, PresetHeader::kVersion); - goto done; - } - - DataHandler * dataHandler = DataHandler::GetSingleton(); - - typedef std::map ModMap; - typedef std::pair ModPair; - - ModMap modList; - UInt8 modCount = 0; - file.Read(&modCount, sizeof(modCount)); - - char textBuffer[MAX_PATH]; - for(UInt8 i = 0; i < modCount; i++) - { - UInt8 modIndex; - file.Read(&modIndex, sizeof(modIndex)); - - UInt16 strLen = 0; - file.Read(&strLen, sizeof(strLen)); - - memset(textBuffer, 0, MAX_PATH); - file.Read(textBuffer, strLen); - - std::string modName(textBuffer); - - modList.emplace(modIndex, modName); - presetData->modList.push_back(modName); - } - - UInt8 partCount = 0; - file.Read(&partCount, sizeof(partCount)); - - for(UInt8 i = 0; i < partCount; i++) - { - UInt8 partType = 0; - file.Read(&partType, sizeof(partType)); - - UInt32 formId = 0; - file.Read(&formId, sizeof(formId)); - - UInt8 modIndex = formId >> 24; - auto it = modList.find(modIndex); - if(it != modList.end()) { - UInt8 gameIndex = dataHandler->GetLoadedModIndex(it->second.c_str()); - if(gameIndex != 255) { - formId = (formId & 0x00FFFFFF) | (gameIndex << 24); - TESForm * headPartForm = LookupFormByID(formId); - if(headPartForm) { - BGSHeadPart * headPart = DYNAMIC_CAST(headPartForm, TESForm, BGSHeadPart); - if(headPart) { - presetData->headParts.push_back(headPart); - } - } else { - _WARNING("Could not resolve part %08X", formId); - } - } else { - _WARNING("Could not load part type %d from %s; mod not found.", partType, it->second.c_str()); - } - } - } - - float weight = 0.0; - file.Read(&weight, sizeof(weight)); - - presetData->weight = weight; - - UInt8 presetCount = 0; - file.Read(&presetCount, sizeof(presetCount)); - - for(UInt8 i = 0; i < presetCount; i++) - { - SInt32 preset = 0; - file.Read(&preset, sizeof(UInt8)); - - if(preset == 255) - preset = -1; - - presetData->presets.push_back(preset); - } - - UInt8 optionCount = 0; - file.Read(&optionCount, sizeof(optionCount)); - - for(UInt8 i = 0; i < optionCount; i++) - { - float option = 0.0; - file.Read(&option, sizeof(option)); - - presetData->morphs.push_back(option); - } - - UInt32 hairColor = 0; - file.Read(&hairColor, sizeof(hairColor)); - - presetData->hairColor = hairColor; - - UInt8 tintCount = 0; - file.Read(&tintCount, sizeof(tintCount)); - - for(UInt8 i = 0; i < tintCount; i++) - { - UInt8 tintIndex = 0; - file.Read(&tintIndex, sizeof(tintIndex)); - - UInt32 tintColor = 0; - file.Read(&tintColor, sizeof(tintColor)); - - UInt16 strLen = 0; - file.Read(&strLen, sizeof(strLen)); - - memset(textBuffer, 0, MAX_PATH); - file.Read(textBuffer, strLen); - - BSFixedString tintPath = textBuffer; - - PresetData::Tint tint; - tint.color = tintColor; - tint.index = tintIndex; - tint.name = tintPath; - presetData->tints.push_back(tint); - } - - UInt8 morphCount = 0; - file.Read(&morphCount, sizeof(morphCount)); - - for(UInt8 i = 0; i < morphCount; i++) - { - UInt16 strLen = 0; - file.Read(&strLen, sizeof(strLen)); - - memset(textBuffer, 0, MAX_PATH); - file.Read(textBuffer, strLen); - - float morphValue = 0.0; - file.Read(&morphValue, sizeof(morphValue)); - - PresetData::Morph morph; - morph.name = textBuffer; - morph.value = morphValue; - - presetData->customMorphs.push_back(morph); - } - - if(header.formatVersion >= 3) - { - UInt8 textureCount = 0; - file.Read(&textureCount, sizeof(textureCount)); - - for(UInt8 i = 0; i < textureCount; i++) - { - UInt8 textureIndex = 0; - file.Read(&textureIndex, sizeof(textureIndex)); - - UInt16 strLen = 0; - file.Read(&strLen, sizeof(strLen)); - - memset(textBuffer, 0, MAX_PATH); - file.Read(textBuffer, strLen); - - BSFixedString texturePath(textBuffer); - - PresetData::Texture texture; - texture.index = textureIndex; - texture.name = texturePath; - - presetData->faceTextures.push_back(texture); - } - } - } - catch(...) - { - _ERROR("%s: exception during load", __FUNCTION__); - loadError = true; - } - -done: - return loadError; -} - -BSFixedString SculptData::GetHostByPart(BGSHeadPart * headPart) -{ - const char * morphPath = headPart->chargenMorph.GetModelName(); - if (morphPath != NULL && morphPath[0] != NULL) - return morphPath; - - morphPath = headPart->morph.GetModelName(); - if (morphPath != NULL && morphPath[0] != NULL) - return morphPath; - - morphPath = headPart->raceMorph.GetModelName(); - if (morphPath != NULL && morphPath[0] != NULL) - return morphPath; - - return BSFixedString(""); -} - -MappedSculptDataPtr SculptData::GetSculptHost(BSFixedString host, bool create) -{ - auto it = find(host); - if (it != end()) - return it->second; - else if (create) { - auto data = std::make_shared(); - emplace(host, data); - return data; - } - - return nullptr; -} - -SculptDataPtr SculptStorage::GetSculptTarget(TESNPC * target, bool create) -{ - auto it = find(target); - if (it != end()) - return it->second; - else if (create) { - auto data = std::make_shared(); - emplace(target, data); - return data; - } - - return nullptr; -} - -void SculptStorage::SetSculptTarget(TESNPC * target, SculptDataPtr sculptData) -{ - auto it = find(target); - if (it != end()) - it->second = sculptData; - else { - emplace(target, sculptData); - } -} - -void SculptStorage::EraseNPC(TESNPC * npc) -{ - auto sculptTarget = find(npc); - if (sculptTarget != end()) { - erase(sculptTarget); - } -} - -SKSETaskApplyMorphs::SKSETaskApplyMorphs(Actor * actor) -{ - m_formId = actor->formID; -} - -void SKSETaskApplyMorphs::Run() -{ - if (!m_formId) - return; - - TESForm * form = LookupFormByID(m_formId); - Actor * actor = DYNAMIC_CAST(form, TESForm, Actor); - if (!actor) - return; - - TESNPC * actorBase = DYNAMIC_CAST(actor->baseForm, TESForm, TESNPC); - if (!actorBase) - return; - - BSFaceGenNiNode * faceNode = actor->GetFaceGenNiNode(); - if (faceNode) { - g_morphHandler.ApplyMorphs(actorBase, faceNode); - UpdateModelFace(faceNode); - } -} - -SKSETaskImportHead::SKSETaskImportHead(Actor * actor, BSFixedString nifPath) : m_nifPath(nifPath) -{ - m_formId = actor->formID; -} -/* -class TESNPC_Extn : public TESNPC -{ -public: - MEMBER_FN_PREFIX(TESNPC_Extn); - DEFINE_MEMBER_FN(UpdateHead, void, 0x560E00, NiGeometry * geometry); -}; - -class BSFaceGenNiNode_Extn : public BSFaceGenNiNode -{ -public: - MEMBER_FN_PREFIX(BSFaceGenNiNode_Extn); - DEFINE_MEMBER_FN(UpdateSkin, void, 0x5A83C0, NiAVObject * root, NiAVObject * geometry, UInt32 unk1); -}; - -class UnknownClass1 -{ -public: - static UnknownClass1 * GetSingleton(void) - { - return *((UnknownClass1 **)0x1BA7680); - } - - MEMBER_FN_PREFIX(UnknownClass1); - DEFINE_MEMBER_FN(Invalidate, void, 0xC78D80, NiAVObject * object); - DEFINE_MEMBER_FN(Invalidate2, void, 0xC77EB0, NiAVObject * object, char unk1, char unk2); -}; - -typedef UInt32(*_UpdateModelGeometryData)(NiAVObject*, UInt8 * update); -const _UpdateModelGeometryData UpdateModelGeometryData = (_UpdateModelGeometryData)0x005A9B30; - -typedef void (*_InvalidateGeometryData)(NiAVObject* object, NiAVObject* root); -const _InvalidateGeometryData InvalidateGeometryData = (_InvalidateGeometryData)0x00C6F3B0; -*/ - -void SKSETaskImportHead::Run() -{ - if (!m_formId) - return; - - TESForm * form = LookupFormByID(m_formId); - Actor * actor = DYNAMIC_CAST(form, TESForm, Actor); - if (!actor) - return; - - NiNode * root = actor->GetNiRootNode(0); - BSFaceGenNiNode * faceNode = actor->GetFaceGenNiNode(); - TESNPC * actorBase = DYNAMIC_CAST(actor->baseForm, TESForm, TESNPC); - if (!actorBase || !faceNode || !root) - 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); - } - - UInt32 numParts = actorBase->numHeadParts; - BGSHeadPart ** headParts = actorBase->headparts; - if (CALL_MEMBER_FN(actorBase, HasOverlays)()) { - numParts = GetNumActorBaseOverlays(actorBase); - headParts = GetActorBaseOverlays(actorBase); - } - - std::unordered_map> typeMap; - for (UInt32 i = 0; i < numParts; i++) - { - BGSHeadPart * headPart = headParts[i]; - for (UInt32 p = 0; p < faceNode->m_children.m_size; p++) - { - NiAVObject * object = faceNode->m_children.m_data[p]; - if (object && BSFixedString(object->m_name) == headPart->partName) { - BSGeometry * geometry = object->GetAsBSGeometry(); - if (geometry) { - BSGeometry * otherGeometry = NULL; - geometry->IncRef(); - typeMap.emplace(SculptData::GetHostByPart(headPart), std::make_tuple(headPart, geometry, otherGeometry)); - break; - } - } - } - } - - UInt8 niStreamMemory[0x5B4]; - memset(niStreamMemory, 0, 0x5B4); - NiStream * niStream = (NiStream *)niStreamMemory; - CALL_MEMBER_FN(niStream, ctor)(); - - - BSResourceNiBinaryStream binaryStream(m_nifPath.data); - if (binaryStream.IsValid()) { - - NiNode * rootNode = NULL; - niStream->LoadStream(&binaryStream); - if (niStream->m_rootObjects.m_data) - { - if (niStream->m_rootObjects.m_data[0]) // Get the root node - rootNode = niStream->m_rootObjects.m_data[0]->GetAsNiNode(); - if (rootNode) - { - VisitObjects(rootNode, [&](NiAVObject* trishape) - { - NiNode * parent = trishape->m_parent; - if (parent && BSFixedString(parent->m_name) == BSFixedString("BSFaceGenNiNodeSkinned")) { - BSGeometry * geometry = trishape->GetAsBSGeometry(); - if (geometry) { - std::string name(trishape->m_name); - BGSHeadPart * part = GetHeadPartByName(name); - if (part) { - auto it = typeMap.find(SculptData::GetHostByPart(part)); - if (it != typeMap.end()) { - geometry->IncRef(); - std::get<2>(it->second) = geometry; - } - } - } - } - return false; - }); - - } - } - - CALL_MEMBER_FN(niStream, dtor)(); - } - - for (auto obj : typeMap) { - BGSHeadPart * part = std::get<0>(obj.second); - BSGeometry * source = std::get<1>(obj.second); - BSGeometry * target = std::get<2>(obj.second); - if (!part || !source || !target) - continue; - -#ifdef FIXME_GEOMETRY - NiGeometryData * sourceData = niptr_cast(source->m_spModelData); - NiGeometryData * targetData = niptr_cast(target->m_spModelData); - if (!sourceData || !targetData) - continue; - - if (sourceData->m_usVertices == targetData->m_usVertices) { - auto sculptHost = g_morphHandler.GetSculptTarget(actorBase); - if (sculptHost) { - auto sculptData = sculptHost->GetSculptHost(obj.first); - if (sculptData) { - BSFaceGenBaseMorphExtraData * extraData = (BSFaceGenBaseMorphExtraData *)source->GetExtraData("FOD"); - if (extraData) { - for (UInt32 i = 0; i < sourceData->m_usVertices; i++) { - NiPoint3 diff = targetData->m_pkVertex[i] - sourceData->m_pkVertex[i]; - - if (abs(diff.x) > 0.001 || abs(diff.y) > 0.001 || abs(diff.z) > 0.001) { - extraData->vertexData[i] += diff; - sculptData->force_insert(std::make_pair(i, diff)); - } - } - } - } - } - } -#endif - - if (source) - source->DecRef(); - if (target) - target->DecRef(); - } - - UpdateModelFace(faceNode); - - if (animationData) { - animationData->overrideFlag = 0; - CALL_MEMBER_FN(animationData, Reset)(1.0, 1, 1, 0, 0); - FaceGen::GetSingleton()->isReset = 1; - UpdateModelFace(faceNode); - } -} \ No newline at end of file diff --git a/skee/MorphHandler.h b/skee/MorphHandler.h deleted file mode 100644 index 00fca15..0000000 --- a/skee/MorphHandler.h +++ /dev/null @@ -1,450 +0,0 @@ -#pragma once - -#include "skse64/GameTypes.h" - -#ifdef _DEBUG -//#define _DEBUG_HOOK -//#define _DEBUG_MORPHAPPLICATOR -//#define _DEBUG_DATADUMP -//#define _DEBUG_DATAREADER -//#define _DEBUG_MORPH -#endif - -class BSFaceGenNiNode; -class TESNPC; -class SliderArray; -class RaceMenuSlider; -struct SKSESerializationInterface; -class TESRace; -class BGSHeadPart; -class TESForm; -class TESModelTri; - -#define SLIDER_OFFSET 200 -#define SLIDER_CATEGORY_EXTRA 512 -#define SLIDER_CATEGORY_EXPRESSIONS 1024 - -#define SLIDER_MOD_DIRECTORY "actors\\character\\FaceGenMorphs\\" -#define SLIDER_DIRECTORY "actors\\character\\FaceGenMorphs\\morphs\\" - -#define MORPH_CACHE_TEMPLATE "%08X.tri" -#define MORPH_CACHE_DIR "cache\\" -#define MORPH_CACHE_PATH "actors\\character\\FaceGenMorphs\\morphs\\cache\\" - -#include -#include -#include -#include -#include - -#include "IHashType.h" -#include "OverrideVariant.h" - -#include "skse64/GameResources.h" -#include "skse64/GameThreads.h" - -class SliderInternal -{ -public: - SliderInternal::SliderInternal() - { - category = -1; - name = ""; - lowerBound = ""; - upperBound = ""; - type = 0; - presetCount = 0; - } - - void SliderInternal::copy(SliderInternal * slider) - { - category = slider->category; - name = slider->name; - lowerBound = slider->lowerBound; - upperBound = slider->upperBound; - type = slider->type; - presetCount = slider->presetCount; - } - - enum - { - kCategoryExpressions = SLIDER_CATEGORY_EXPRESSIONS, - kCategoryExtra = SLIDER_CATEGORY_EXTRA, - kCategoryBody = 4, - kCategoryHead = 8, - kCategoryFace = 16, - kCategoryEyes = 32, - kCategoryBrow = 64, - kCategoryMouth = 128, - kCategoryHair = 256 - }; - - enum - { - kTypeSlider = 0, - kTypePreset = 1, - kTypeHeadPart = 2 - }; - - SInt32 category; - BSFixedString name; - BSFixedString lowerBound; - BSFixedString upperBound; - UInt8 type; - UInt8 presetCount; -}; - -typedef std::shared_ptr SliderInternalPtr; - -class SliderGender -{ -public: - SliderGender::SliderGender() - { - slider[0] = NULL; - slider[1] = NULL; - } - - SliderInternalPtr slider[2]; -}; -typedef std::shared_ptr SliderGenderPtr; -typedef std::vector SliderList; -typedef std::map RaceSliders; -typedef std::vector MorphSet; - -class MorphMap : public std::map -{ -public: - class Visitor - { - public: - virtual bool Accept(BSFixedString morphName) { return false; }; - }; - - void AddMorph(BSFixedString key, BSFixedString value); - bool Visit(BSFixedString key, Visitor & visitor); - void Revert(); - -#ifdef _DEBUG_DATADUMP - void DumpMap(); - class DumpVisitor : public Visitor - { - public: - virtual bool Accept(BSFixedString morphName) - { - _MESSAGE("Extra Morph: %s", morphName.data); - return false; - }; - }; -#endif -}; - -class SliderMap : public std::map -{ -public: - SliderMap::SliderMap() : std::map(){ } - - void AddSlider(BSFixedString key, UInt8 gender, SliderInternal & slider); - -#ifdef _DEBUG_DATADUMP - void DumpMap(); -#endif -}; - -typedef std::shared_ptr SliderMapPtr; - - -class SliderSet : public std::set -{ -public: - bool for_each_slider(std::function func); -}; - -typedef std::shared_ptr SliderSetPtr; - -class RaceMap : public std::map -{ -public: - SliderSetPtr GetSliderSet(TESRace * race); - bool AddSliderMap(TESRace * race, SliderMapPtr sliderMap); - bool CreateDefaultMap(TESRace * race); - - void Revert(); - -#ifdef _DEBUG_DATADUMP - void DumpMap(); -#endif -}; - -class ValueSet : public std::unordered_map -{ -public: - void SetValue(BSFixedString name, float value); - void ClearValue(BSFixedString name); - float GetValue(BSFixedString name); -}; - -class ValueMap : public std::unordered_map -{ -public: - ValueSet * GetValueSet(TESNPC* npc); - void EraseNPC(TESNPC * npc); - - float GetMorphValueByName(TESNPC* npc, BSFixedString name); - void SetMorphValue(TESNPC* npc, BSFixedString name, float value); -}; - -#define VERTEX_THRESHOLD 0.00001 -#define VERTEX_MULTIPLIER 10000 - -class MappedSculptData : public std::unordered_map -{ -public: - void force_insert(value_type const & v) - { - if (abs(v.second.x) < VERTEX_THRESHOLD && abs(v.second.y) < VERTEX_THRESHOLD && abs(v.second.z) < VERTEX_THRESHOLD) - return; - - auto res = insert(v); - if (!res.second) - (*res.first).second = v.second; - } - - void add(value_type const & v) - { - auto res = insert(v); - if (!res.second) - (*res.first).second += v.second; - - if (abs((*res.first).second.x) < VERTEX_THRESHOLD && abs((*res.first).second.y) < VERTEX_THRESHOLD && abs((*res.first).second.z) < VERTEX_THRESHOLD) - erase(res.first); - } -}; -typedef std::shared_ptr MappedSculptDataPtr; - -class SculptData : public std::unordered_map < BSFixedString, MappedSculptDataPtr > -{ -public: - MappedSculptDataPtr GetSculptHost(BSFixedString, bool create = true); - - static BSFixedString GetHostByPart(BGSHeadPart * headPart); -}; -typedef std::shared_ptr SculptDataPtr; - -class SculptStorage : public std::unordered_map < TESNPC*, SculptDataPtr > -{ -public: - void SetSculptTarget(TESNPC * npc, SculptDataPtr sculptData); - SculptDataPtr GetSculptTarget(TESNPC* npc, bool create = true); - void EraseNPC(TESNPC * npc); -}; - - -class PresetData -{ -public: - PresetData(); - - struct Tint - { - UInt32 index; - UInt32 color; - BSFixedString name; - }; - - struct Morph - { - float value; - BSFixedString name; - }; - - struct Texture - { - UInt8 index; - BSFixedString name; - }; - - float weight; - UInt32 hairColor; - std::vector modList; - std::vector headParts; - std::vector presets; - std::vector morphs; - std::vector tints; - std::vector customMorphs; - std::vector faceTextures; - BSFixedString tintTexture; - typedef std::map> OverrideData; - OverrideData overrideData; - typedef std::map> SkinData; - SkinData skinData[2]; - typedef std::map>> TransformData; - TransformData transformData[2]; - SculptDataPtr sculptData; - typedef std::unordered_map> BodyMorphData; - BodyMorphData bodyMorphData; -}; -typedef std::shared_ptr PresetDataPtr; - -class TRIFile -{ -public: - TRIFile() - { - vertexCount = -1; - } - - bool Load(const char * triPath); - bool Apply(BSGeometry * geometry, BSFixedString morph, float relative); - - struct Morph - { - BSFixedString name; - float multiplier; - - struct Vertex - { - SInt16 x, y, z; - }; - - std::vector vertices; - }; - - SInt32 vertexCount; - std::unordered_map morphs; -}; - -class TRIModelData -{ -public: - TRIModelData() - { - vertexCount = -1; - morphModel = NULL; - } - SInt32 vertexCount; - std::shared_ptr triFile; - TESModelTri * morphModel; -}; - -typedef std::unordered_map ModelMap; -typedef std::unordered_map PresetMap; - -class MorphHandler -{ -public: - void Save(SKSESerializationInterface * intfc, UInt32 kVersion); - void Revert(); - void RevertInternals(); - - bool LoadMorphData(SKSESerializationInterface * intfc, UInt32 version); - bool LoadSculptData(SKSESerializationInterface * intfc, UInt32 version); - - void LoadMods(); - - float GetMorphValueByName(TESNPC* npc, BSFixedString name); - void SetMorphValue(TESNPC* npc, BSFixedString name, float value); - - void SetMorph(TESNPC * npc, BSFaceGenNiNode * faceNode, const char * name, float relative); - - void ApplyMorph(TESNPC * npc, BGSHeadPart * headPart, BSFaceGenNiNode * faceNode); - void ApplyMorphs(TESNPC * npc, BSFaceGenNiNode * faceNode); - - SInt32 LoadSliders(tArray * sliderArray, RaceMenuSlider * slider); - - void ReadMorphs(std::string fixedPath, std::string modName, std::string fileName); - void ReadRaces(std::string fixedPath, std::string modName, std::string fileName); - SliderMapPtr ReadSliders(std::string fixedPath, std::string modName, std::string fileName); - - SliderInternalPtr GetSlider(TESRace * race, UInt8 gender, BSFixedString name); - SliderInternalPtr GetSliderByIndex(TESRace * race, UInt32 index); - - SliderList * CreateSliderList(TESRace * race, UInt8 gender); - void AddSlider(TESRace * race, SliderInternalPtr & slider); - - bool VisitMorphMap(BSFixedString key, MorphMap::Visitor & visitor); - - bool CacheHeadPartModel(BGSHeadPart * headPart, bool cacheTRI = false); - bool GetModelTri(BSFixedString filePath, TRIModelData & modelData); - TRIModelData & GetExtendedModelTri(BSFixedString morphName, bool cacheTRI = false); - - SliderList * currentList; - RaceSliders m_internalMap; - RaceMap m_raceMap; - MorphMap m_morphMap; - ValueMap m_valueMap; - ModelMap m_modelMap; - PresetMap m_mappedPreset; - - SculptStorage m_sculptStorage; - inline SculptDataPtr GetSculptTarget(TESNPC * npc, bool create = true) - { - return m_sculptStorage.GetSculptTarget(npc, create); - } - inline void SetSculptTarget(TESNPC * npc, const SculptDataPtr & data) - { - return m_sculptStorage.SetSculptTarget(npc, data); - } - inline void EraseSculptData(TESNPC * npc) - { - m_sculptStorage.EraseNPC(npc); - } - inline void EraseMorphData(TESNPC * npc) - { - m_valueMap.EraseNPC(npc); - } - - PresetDataPtr GetPreset(TESNPC* npc); - void AssignPreset(TESNPC * npc, PresetDataPtr presetData); - void ApplyPreset(TESNPC * npc, BSFaceGenNiNode * faceNode, BGSHeadPart * headPart); - bool ErasePreset(TESNPC * npc); - void ClearPresets(); - - bool SaveBinaryPreset(const char * filePath); - //bool LoadPreset(const char * filePath, GFxMovieView * movieView, GFxValue * rootObject); - bool LoadBinaryPreset(const char * filePath, PresetDataPtr presetData); - - enum ApplyTypes - { - kPresetApplyFace = (0 << 0), - kPresetApplyOverrides = (1 << 0), - kPresetApplyBodyMorphs = (1 << 1), - kPresetApplyTransforms = (1 << 2), - kPresetApplySkinOverrides = (1 << 3), - kPresetApplyAll = kPresetApplyFace | kPresetApplyOverrides | kPresetApplyBodyMorphs | kPresetApplyTransforms | kPresetApplySkinOverrides - }; - - void ApplyPresetData(Actor * actor, PresetDataPtr presetData, bool setSkinColor = false, ApplyTypes applyType = kPresetApplyAll); - - bool SaveJsonPreset(const char * filePath); - bool LoadJsonPreset(const char * filePath, PresetDataPtr presetData); - -#ifdef _DEBUG_DATADUMP - void DumpAll(); -#endif -}; - -class SKSETaskImportHead : public TaskDelegate -{ -public: - virtual void Run(); - virtual void Dispose() { delete this; } - - SKSETaskImportHead(Actor * actor, BSFixedString nifPath); - -private: - UInt32 m_formId; - BSFixedString m_nifPath; -}; - -class SKSETaskApplyMorphs : public TaskDelegate -{ -public: - virtual void Run(); - virtual void Dispose() { delete this; } - - SKSETaskApplyMorphs(Actor * actor); - -private: - UInt32 m_formId; -}; \ No newline at end of file diff --git a/skee/NifUtils.cpp b/skee/NifUtils.cpp index e4bb6fa..b37e175 100644 --- a/skee/NifUtils.cpp +++ b/skee/NifUtils.cpp @@ -1,4 +1,5 @@ #include "NifUtils.h" +#include "Utilities.h" #include @@ -20,8 +21,7 @@ #include "skse64/NiExtraData.h" #include - -#include "DirectXTex/DirectXTex.h" +#include #ifdef FIXME #include @@ -147,20 +147,19 @@ BSGeometry * GetHeadGeometry(Actor * actor, UInt32 partType) return NULL; } -BSGeometry * GetGeometryByHeadPart(BSFaceGenNiNode * faceNode, BGSHeadPart * headPart) +NiAVObject * GetObjectByHeadPart(BSFaceGenNiNode * faceNode, BGSHeadPart * headPart) { for (UInt32 p = 0; p < faceNode->m_children.m_size; p++) { NiAVObject * object = faceNode->m_children.m_data[p]; if (object && BSFixedString(object->m_name) == headPart->partName) { - BSGeometry * geometry = object->GetAsBSGeometry(); - if (geometry) { - return geometry; + if (object) { + return object; } } } - return NULL; + return nullptr; } SKSETaskRefreshTintMask::SKSETaskRefreshTintMask(Actor * actor, BSFixedString ddsPath) : m_ddsPath(ddsPath) @@ -288,9 +287,8 @@ void SKSETaskExportHead::Run() IFileStream::MakeAllDirs(m_nifPath.data); - BSFadeNode * rootNode = BSFadeNode::Create(); - rootNode->IncRef(); - NiNode * skinnedNode = NiNode::Create(0); + NiPointer rootNode = BSFadeNode::Create(); + NiPointer skinnedNode = NiNode::Create(0); skinnedNode->m_name = BSFixedString("BSFaceGenNiNodeSkinned").data; std::map boneMap; @@ -308,24 +306,24 @@ void SKSETaskExportHead::Run() CALL_MEMBER_FN(geometryData, DeepCopy)((NiObject **)&newGeometryData); NiProperty * trishapeEffect = niptr_cast(geometry->m_spEffectState); - NiProperty * newTrishapeEffect = NULL; + NiPointer newTrishapeEffect; if (trishapeEffect) CALL_MEMBER_FN(trishapeEffect, DeepCopy)((NiObject **)&newTrishapeEffect); NiProperty * trishapeProperty = niptr_cast(geometry->m_spPropertyState); - NiProperty * newTrishapeProperty = NULL; + NiPointer newTrishapeProperty; if (trishapeProperty) CALL_MEMBER_FN(trishapeProperty, DeepCopy)((NiObject **)&newTrishapeProperty); NiSkinInstance * skinInstance = niptr_cast(geometry->m_spSkinInstance); - NiSkinInstance * newSkinInstance = NULL; + NiPointer newSkinInstance; if (skinInstance) { newSkinInstance = skinInstance->Clone(); newSkinInstance->m_pkRootParent = skinnedNode; UInt32 numBones = 0; NiSkinData * skinData = niptr_cast(skinInstance->m_spSkinData); - NiSkinData * newSkinData = NULL; + NiPointer newSkinData; if (skinData) { numBones = skinData->m_uiBones; CALL_MEMBER_FN(skinData, DeepCopy)((NiObject **)&newSkinData); @@ -337,10 +335,7 @@ void SKSETaskExportHead::Run() 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) @@ -354,6 +349,7 @@ void SKSETaskExportHead::Run() auto it = boneMap.find(bone); if (it == boneMap.end()) { NiNode * newBone = NiNode::Create(); + newBone->IncRef(); newBone->m_name = bone->m_name; newBone->m_flags = bone->m_flags; boneMap.insert(std::make_pair(bone, newBone)); @@ -370,7 +366,7 @@ void SKSETaskExportHead::Run() } } - NiGeometry * newGeometry = NULL; + NiPointer newGeometry; if (NiTriShape * trishape = geometry->GetAsNiTriShape()) { NiTriShape * newTrishape = NiTriShape::Create(static_cast(newGeometryData)); @@ -445,39 +441,36 @@ void SKSETaskExportHead::Run() else if (BSGeometry * geometry = object->GetAsBSGeometry()) { NiProperty * trishapeEffect = niptr_cast(geometry->m_spEffectState); - NiProperty * newTrishapeEffect = NULL; + NiPointer newTrishapeEffect; if (trishapeEffect) CALL_MEMBER_FN(trishapeEffect, DeepCopy)((NiObject **)&newTrishapeEffect); NiProperty * trishapeProperty = niptr_cast(geometry->m_spPropertyState); - NiProperty * newTrishapeProperty = NULL; + NiPointer newTrishapeProperty; if (trishapeProperty) CALL_MEMBER_FN(trishapeProperty, DeepCopy)((NiObject **)&newTrishapeProperty); NiSkinInstance * skinInstance = niptr_cast(geometry->m_spSkinInstance); - NiSkinInstance * newSkinInstance = NULL; + NiPointer newSkinInstance; if (skinInstance) { - newSkinInstance = skinInstance->Clone(); + newSkinInstance = skinInstance->Clone(); // Clonned instance starts at 0 newSkinInstance->m_pkRootParent = skinnedNode; UInt32 numBones = 0; NiSkinData * skinData = niptr_cast(skinInstance->m_spSkinData); - NiSkinData * newSkinData = NULL; + NiPointer newSkinData; if (skinData) { numBones = skinData->m_uiBones; CALL_MEMBER_FN(skinData, DeepCopy)((NiObject **)&newSkinData); } NiSkinPartition * skinPartition = niptr_cast(skinInstance->m_spSkinPartition); - NiSkinPartition * newSkinPartition = NULL; + NiPointer newSkinPartition; 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) @@ -491,6 +484,7 @@ void SKSETaskExportHead::Run() auto it = boneMap.find(bone); if (it == boneMap.end()) { NiNode * newBone = NiNode::Create(); + newBone->IncRef(); newBone->m_name = bone->m_name; newBone->m_flags = bone->m_flags; boneMap.insert(std::make_pair(bone, newBone)); @@ -507,7 +501,7 @@ void SKSETaskExportHead::Run() } } - BSGeometry * newGeometry = NULL; + NiPointer newGeometry; BSTriShape * trishape = geometry->GetAsBSTriShape(); if (trishape) @@ -541,13 +535,7 @@ void SKSETaskExportHead::Run() newTrishape->m_localTransform = geometry->m_localTransform; newTrishape->m_name = geometry->m_name; newTrishape->m_spEffectState = newTrishapeEffect; - if (newTrishapeEffect) - newTrishapeEffect->DecRef(); - newTrishape->m_spPropertyState = newTrishapeProperty; - if (newTrishapeProperty) - newTrishapeProperty->DecRef(); - newTrishape->m_spSkinInstance = newSkinInstance; newTrishape->geometryData = trishape->geometryData; @@ -570,7 +558,7 @@ void SKSETaskExportHead::Run() newTrishape->unk110 = trishape->unk110; newTrishape->unk118 = trishape->unk118; newTrishape->unk140 = trishape->unk140; - newTrishape->unk148 = trishape->unk148; + newTrishape->vertexDesc = trishape->vertexDesc; newTrishape->unk150 = trishape->unk150; newTrishape->unk151 = trishape->unk151; newTrishape->unk152 = trishape->unk152; @@ -625,8 +613,10 @@ void SKSETaskExportHead::Run() } } - for (auto & bones : boneMap) + for (auto & bones : boneMap) { rootNode->AttachChild(bones.second, true); + bones.second->DecRef(); + } rootNode->AttachChild(skinnedNode, true); @@ -675,6 +665,30 @@ NiTransform GetGeometryTransform(BSGeometry * geometry) NiTransform transform = geometry->m_localTransform; NiSkinInstance * dstSkin = niptr_cast(geometry->m_spSkinInstance); if (dstSkin) { + ScopedCriticalSection cs(&dstSkin->lock); + NiSkinData * skinData = dstSkin->m_spSkinData; + if (skinData) { + transform = transform * skinData->m_kRootParentToSkin; + + for (UInt32 i = 0; i < skinData->m_uiBones; i++) { + NiAVObject * bone = dstSkin->m_ppkBones[i]; + if (bone->m_name == BSFixedString("NPC Head [Head]").data) { + transform = transform * skinData->m_pkBoneData[i].m_kSkinToBone; + break; + } + } + } + } + + return transform; +} + +NiTransform GetLegacyGeometryTransform(NiGeometry * geometry) +{ + NiTransform transform = geometry->m_localTransform; + NiSkinInstance * dstSkin = niptr_cast(geometry->m_spSkinInstance); + if (dstSkin) { + ScopedCriticalSection cs(&dstSkin->lock); NiSkinData * skinData = dstSkin->m_spSkinData; if (skinData) { transform = transform * skinData->m_kRootParentToSkin; diff --git a/skee/NifUtils.h b/skee/NifUtils.h index 5c4762b..edd8f81 100644 --- a/skee/NifUtils.h +++ b/skee/NifUtils.h @@ -14,6 +14,7 @@ class TESNPC; class BGSHeadPart; class BSFaceGenNiNode; class BSGeometry; +class NiGeometry; class NiTriStripsData; class SKSETaskExportHead : public TaskDelegate @@ -45,7 +46,7 @@ BGSTextureSet * GetTextureSetForPart(TESNPC * npc, BGSHeadPart * headPart); std::pair GetTextureSetForPartByName(TESNPC * npc, BSFixedString partName); BSGeometry * GetHeadGeometry(Actor * actor, UInt32 partType); void ExportTintMaskDDS(Actor * actor, BSFixedString filePath); -BSGeometry * GetGeometryByHeadPart(BSFaceGenNiNode * faceNode, BGSHeadPart * headPart); +NiAVObject * GetObjectByHeadPart(BSFaceGenNiNode * faceNode, BGSHeadPart * headPart); void SaveSourceDDS(NiSourceTexture * pkSrcTexture, const char * pcFileName); void SaveRenderedDDS(NiRenderedTexture * pkTexture, const char * pcFileName); @@ -53,6 +54,7 @@ void SaveRenderedDDS(NiRenderedTexture * pkTexture, const char * pcFileName); bool VisitObjects(NiAVObject * parent, std::function functor); NiTransform GetGeometryTransform(BSGeometry * geometry); +NiTransform GetLegacyGeometryTransform(NiGeometry * geometry); UInt16 GetStripLengthSum(NiTriStripsData * strips); void GetTriangleIndices(NiTriStripsData * strips, UInt16 i, UInt16 v0, UInt16 v1, UInt16 v2); diff --git a/skee/OverlayInterface.cpp b/skee/OverlayInterface.cpp index d46bb48..8f2dc97 100644 --- a/skee/OverlayInterface.cpp +++ b/skee/OverlayInterface.cpp @@ -127,7 +127,7 @@ void OverlayInterface::InstallOverlay(const char * nodeName, const char * path, BSGeometry * targetShape = newShape->GetAsBSGeometry(); if(targetShape) { - targetShape->unk148 = source->unk148; + targetShape->vertexDesc = source->vertexDesc; if (shaderProperty) targetShape->m_spEffectState = shaderProperty; @@ -293,9 +293,8 @@ void OverlayInterface::RelinkOverlay(const char * nodeName, TESObjectREFR * refr if (source && foundGeometry) { - foundGeometry->unk148 = source->unk148; + foundGeometry->vertexDesc = source->vertexDesc; NiSkinInstance * sourceSkin = niptr_cast(source->m_spSkinInstance); - if (sourceSkin) { foundGeometry->m_spSkinInstance = sourceSkin->Clone(); } diff --git a/skee/PartHandler.cpp b/skee/PartHandler.cpp index ca52eda..83a7fc9 100644 --- a/skee/PartHandler.cpp +++ b/skee/PartHandler.cpp @@ -109,7 +109,7 @@ void ReadPartReplacements(std::string fixedPath, std::string modPath, std::strin UInt32 lineCount = 0; UInt8 gender = 0; std::string str = ""; - while (BSReadLine(&file, &str)) + while (BSFileUtil::ReadLine(&file, &str)) { lineCount++; str = std::trim(str); diff --git a/skee/SKEEHooks.cpp b/skee/SKEEHooks.cpp index 1840457..177567f 100644 --- a/skee/SKEEHooks.cpp +++ b/skee/SKEEHooks.cpp @@ -38,7 +38,6 @@ #include extern SKSETaskInterface * g_task; -extern SKEETaskInterface g_taskOverride; extern ItemDataInterface g_itemDataInterface; extern TintMaskInterface g_tintMaskInterface; @@ -91,43 +90,8 @@ RelocAddr<_DoubleMorphCallback> DoubleMorphCallback(0x008B4A10); RelocAddr<_UpdateNPCMorphs> UpdateNPCMorphs(0x00360A30); RelocAddr<_UpdateNPCMorph> UpdateNPCMorph(0x00360C20); - -// REMOVE THIS AFTER SKSE64 UPDATE -ICriticalSection s_taskQueueLock; -std::queue s_tasks; - -typedef UInt32 (*_ProcessTaskInterface)(void * unk1); -RelocAddr <_ProcessTaskInterface> ProcessTaskInterface_Hook_Original(0x00C03E60); - -static bool IsTaskQueueEmpty() -{ - IScopedCriticalSection scoped(&s_taskQueueLock); - return s_tasks.empty(); -} - -UInt32 ProcessTaskInterface_Hook(void * unk1) -{ - while (!IsTaskQueueEmpty()) - { - s_taskQueueLock.Enter(); - TaskDelegate * cmd = s_tasks.front(); - s_tasks.pop(); - s_taskQueueLock.Leave(); - - cmd->Run(); - cmd->Dispose(); - } - - return ProcessTaskInterface_Hook_Original(unk1); -} - -void ProcessTaskInterface_AddTask(TaskDelegate * cmd) -{ - s_taskQueueLock.Enter(); - s_tasks.push(cmd); - s_taskQueueLock.Leave(); -} -// --------------------------------------- +typedef void(*_RaceSexMenu_Render)(RaceSexMenu * menu); +RelocAddr<_RaceSexMenu_Render> RaceSexMenu_Render(0x0051E9E0); typedef NiAVObject * (*_CreateWeaponNode)(UInt32 * unk1, UInt32 unk2, Actor * actor, UInt32 ** unk4, UInt32 * unk5); extern const _CreateWeaponNode CreateWeaponNode = (_CreateWeaponNode)0x0046F530; @@ -267,9 +231,9 @@ NiAVObject * CreateArmorNode_Hooked(ArmorAddonTree * addonInfo, NiNode * objectR { NiAVObject * retVal = CreateArmorNode(addonInfo, objectRoot, stackInfo->unk10, unk4, unk5, unk6); - TESObjectREFR * reference = nullptr; + NiPointer reference; UInt32 handle = addonInfo->handle; - LookupREFRByHandle(&handle, &reference); + LookupREFRByHandle(handle, reference); if (reference) InstallArmorAddonHook(reference, stackInfo->params, addonInfo->boneTree, retVal); @@ -583,46 +547,31 @@ void SkyrimVM_Hooked::RegisterEventSinks_Hooked() } #endif -#ifdef FIXME +#include +#include "CDXD3DDevice.h" #include "CDXNifScene.h" #include "CDXNifMesh.h" - #include "CDXCamera.h" +#include "Utilities.h" #include "skse64/NiRenderer.h" #include "skse64/NiTextures.h" -#include -#pragma comment(lib, "d3dx9.lib") +extern CDXD3DDevice * g_Device; +extern CDXNifScene g_World; +extern CDXModelViewerCamera g_Camera; -CDXNifScene g_World; -extern CDXModelViewerCamera g_Camera; // A model viewing camera - -void RaceSexMenu_Hooked::RenderMenu_Hooked(void) +void RaceSexMenu_Render_Hooked(RaceSexMenu * rsm) { - CALL_MEMBER_FN(this, RenderMenu)(); - - ID3D11Device * pDevice = NiDX9Renderer::GetSingleton()->m_pkD3DDevice9; - if (!pDevice) // This shouldnt happen - return; - - if (g_World.IsVisible() && g_World.GetTextureGroup()) { - NiRenderedTexture * renderedTexture = g_World.GetTextureGroup()->renderedTexture[0]; - if (renderedTexture) { - g_World.Begin(pDevice); - LPDIRECT3DSURFACE9 oldTarget; - pDevice->GetRenderTarget(0, &oldTarget); - LPDIRECT3DSURFACE9 pRenderSurface = NULL; - LPDIRECT3DTEXTURE9 pRenderTexture = (LPDIRECT3DTEXTURE9)((NiTexture::NiDX9TextureData*)renderedTexture->rendererData)->texture; - pRenderTexture->GetSurfaceLevel(0, &pRenderSurface); - pDevice->SetRenderTarget(0, pRenderSurface); - g_World.Render(pDevice); - pDevice->SetRenderTarget(0, oldTarget); - g_World.End(pDevice); - } + if (g_Device && g_World.IsVisible() && g_World.GetRenderTargetView()) { + ScopedCriticalSection cs(&g_renderManager->lock); + g_World.Begin(&g_Camera, g_Device); + g_World.Render(&g_Camera, g_Device); + g_World.End(&g_Camera, g_Device); } + + RaceSexMenu_Render(rsm); } -#endif void RegenerateHead_Hooked(FaceGen * faceGen, BSFaceGenNiNode * headNode, BGSHeadPart * headPart, TESNPC * npc) { @@ -773,7 +722,7 @@ UInt8 BGSHeadPart_Hooked::IsPlayablePart_Hooked() class MorphVisitor : public MorphMap::Visitor { public: - MorphVisitor::MorphVisitor(BSFaceGenModel * model, BSFixedString * morphName, NiAVObject ** headNode, float relative, UInt8 unk1) + MorphVisitor::MorphVisitor(BSFaceGenModel * model, SKEEFixedString morphName, NiAVObject ** headNode, float relative, UInt8 unk1) { m_model = model; m_morphName = morphName; @@ -781,7 +730,7 @@ class MorphVisitor : public MorphMap::Visitor m_relative = relative; m_unk1 = unk1; } - bool Accept(BSFixedString morphName) + bool Accept(const SKEEFixedString & morphName) override { TRIModelData & morphData = g_morphInterface.GetExtendedModelTri(morphName, true); if (morphData.morphModel && morphData.triFile) { @@ -790,14 +739,14 @@ class MorphVisitor : public MorphMap::Visitor geometry = (*m_headNode)->GetAsBSGeometry(); if (geometry) - morphData.triFile->Apply(geometry, *m_morphName, m_relative); + morphData.triFile->Apply(geometry, m_morphName, m_relative); } return false; } private: BSFaceGenModel * m_model; - BSFixedString * m_morphName; + SKEEFixedString m_morphName; NiAVObject ** m_headNode; float m_relative; UInt8 m_unk1; @@ -813,7 +762,7 @@ UInt8 ApplyRaceMorph_Hooked(BSFaceGenModel * model, BSFixedString * morphName, T try { - MorphVisitor morphVisitor(model, morphName, headNode, relative, unk1); + MorphVisitor morphVisitor(model, *morphName, headNode, relative, unk1); g_morphInterface.VisitMorphMap(modelMorph->GetModelName(), morphVisitor); } catch (...) @@ -834,8 +783,8 @@ UInt8 ApplyChargenMorph_Hooked(BSFaceGenModel * model, BSFixedString * morphName try { - MorphVisitor morphVisitor(model, morphName, headNode, relative, unk1); - g_morphInterface.VisitMorphMap(BSFixedString(modelMorph->GetModelName()), morphVisitor); + MorphVisitor morphVisitor(model, *morphName, headNode, relative, unk1); + g_morphInterface.VisitMorphMap(modelMorph->GetModelName(), morphVisitor); } catch (...) { @@ -1106,13 +1055,6 @@ bool InstallSKEEHooks() _ERROR("couldn't create codegen buffer. this is fatal. skipping remainder of init process."); return false; } - - if (g_task->interfaceVersion < 3) - { - RelocAddr ProcessTaskInterface_Target(0x005B31E0 + 0x739); - g_branchTrampoline.Write5Call(ProcessTaskInterface_Target.GetUIntPtr(), (uintptr_t)ProcessTaskInterface_Hook); - g_taskOverride.AddTask = ProcessTaskInterface_AddTask; - } RelocAddr InvokeCategoriesList_Target(0x008B5420 + 0x9FB); g_branchTrampoline.Write5Call(InvokeCategoriesList_Target.GetUIntPtr(), (uintptr_t)InvokeCategoryList_Hook); @@ -1247,6 +1189,9 @@ bool InstallSKEEHooks() RelocAddr UpdateMorph_Target(0x003DC3B0 + 0x79); g_branchTrampoline.Write5Call(UpdateMorph_Target.GetUIntPtr(), (uintptr_t)UpdateMorph_Hooked); + RelocAddr RaceSexMenu_Render_Target(0x016D4CC8 + 0x30); // ??_7RaceSexMenu@@6B@ + SafeWrite64(RaceSexMenu_Render_Target.GetUIntPtr(), (uintptr_t)RaceSexMenu_Render_Hooked); + if (g_disableFaceGenCache) { RelocAddr Cache_Target(0x008B2DD0); diff --git a/skee/SKEEHooks.h b/skee/SKEEHooks.h index 2859cb0..b2eb0f1 100644 --- a/skee/SKEEHooks.h +++ b/skee/SKEEHooks.h @@ -14,11 +14,6 @@ class NiNode; #include "skse64/GameExtraData.h" #include "skse64/GameMenus.h" -struct SKEETaskInterface : public SKSETaskInterface -{ - void(*AddSKSETask)(TaskDelegate * task); -}; - extern RelocAddr TESModelTri_vtbl; typedef SInt32 (*_AddRaceMenuSlider)(tArray * sliders, RaceMenuSlider * slider); extern RelocAddr<_AddRaceMenuSlider> AddRaceMenuSlider; diff --git a/skee/ScaleformCharGenFunctions.cpp b/skee/ScaleformCharGenFunctions.cpp index e324394..f337580 100644 --- a/skee/ScaleformCharGenFunctions.cpp +++ b/skee/ScaleformCharGenFunctions.cpp @@ -46,10 +46,16 @@ extern SKSETaskInterface * g_task; #include "skse64/NiRenderer.h" #include "skse64/NiExtraData.h" +#include +#include + +#include "CDXShader.h" +#include "CDXD3DDevice.h" #include "CDXCamera.h" #include "CDXNifScene.h" #include "CDXNifMesh.h" #include "CDXBrush.h" +#include "CDXBrushMesh.h" #include "CDXUndo.h" #include "CDXNifCommands.h" @@ -64,12 +70,14 @@ UInt32 colors[] = { 0x33240d, 0x20330d, 0x0d1633, 0x1a332f }; -#ifdef FIXME +extern CDXD3DDevice* g_Device; extern CDXModelViewerCamera g_Camera; extern CDXNifScene g_World; extern float g_panSpeed; extern float g_cameraFOV; -#endif +extern SInt32 g_viewWidth; +extern SInt32 g_viewHeight; +extern bool g_enableHeadExport; void SKSEScaleform_SavePreset::Invoke(Args * args) { @@ -160,10 +168,15 @@ void SKSEScaleform_ReadPreset::Invoke(Args * args) GFxValue modArray; args->movie->CreateArray(&modArray); for(std::vector::iterator it = presetData->modList.begin(); it != presetData->modList.end(); ++it) { + + const ModInfo * modInfo = dataHandler->LookupModByName((*it).c_str()); + if (!modInfo || !modInfo->IsActive()) + continue; + GFxValue modObject; args->movie->CreateObject(&modObject); RegisterString(&modObject, args->movie, "name", (*it).c_str()); - RegisterNumber(&modObject, "loadedIndex", dataHandler->GetModIndex((*it).c_str())); + RegisterNumber(&modObject, "loadedIndex", modInfo->GetPartialIndex()); modArray.PushBack(&modObject); } object->SetMember("mods", &modArray); @@ -426,7 +439,8 @@ void SKSEScaleform_ExportHead::Invoke(Args * args) std::string ddsPath = strData; ddsPath.append(".dds"); - g_task->AddTask(new SKSETaskExportHead(actor, nifPath.c_str(), ddsPath.c_str())); + if(g_enableHeadExport) + g_task->AddTask(new SKSETaskExportHead(actor, nifPath.c_str(), ddsPath.c_str())); } void SKSEScaleform_ImportHead::Invoke(Args * args) @@ -436,7 +450,6 @@ void SKSEScaleform_ImportHead::Invoke(Args * args) const char * strData = args->args[0].GetString(); -#ifdef FIXME // Release the previous import just in case g_World.ReleaseImport(); @@ -467,66 +480,36 @@ void SKSEScaleform_ImportHead::Invoke(Args * args) if (rootNode) { args->movie->CreateArray(args->result); - /*args->movie->CreateObject(args->result); - - GFxValue source; - args->movie->CreateArray(&source); - - - GFxValue destination; - args->movie->CreateArray(&destination); - - UInt32 numParts = actorBase->numHeadParts; - BGSHeadPart ** headParts = actorBase->headparts; - if (CALL_MEMBER_FN(actorBase, HasOverlays)()) { - numParts = GetNumActorBaseOverlays(actorBase); - headParts = GetActorBaseOverlays(actorBase); - } - - for (UInt32 i = 0; i < numParts; i++) - { - BGSHeadPart * headPart = headParts[i]; - if (!headPart) - continue; - - NiTriBasedGeom * geometry = GetTriBasedGeomByHeadPart(faceNode, headPart); - if (!geometry) - continue; - - NiGeometryData * geometryData = niptr_cast(geometry->m_spModelData); - if (!geometryData) - continue; - - bool morphable = geometry->GetExtraData("FOD") != NULL; - - GFxValue gfxPart; - args->movie->CreateObject(&gfxPart); - RegisterString(&gfxPart, args->movie, "name", geometry->m_name); - RegisterNumber(&gfxPart, "vertices", geometryData->m_usVertices); - RegisterBool(&gfxPart, "morphable", morphable); - destination.PushBack(&gfxPart); - } - - */ - SInt32 gIndex = 0; VisitObjects(rootNode, [&gIndex, &args](NiAVObject* trishape) { NiNode * parent = trishape->m_parent; if (parent && BSFixedString(parent->m_name) == BSFixedString("BSFaceGenNiNodeSkinned")) { - NiTriBasedGeom * geometry = trishape->GetAsNiTriBasedGeom(); - if (!geometry) - return false; - NiGeometryData * geometryData = niptr_cast(geometry->m_spModelData); - if (!geometryData) - return false; + UInt32 numVertices = 0; + + NiGeometry * legacyGeometry = trishape->GetAsNiGeometry(); + BSTriShape * geometry = trishape->GetAsBSTriShape(); + if (geometry) { + numVertices = geometry->numVertices; + } + else if (legacyGeometry) { + NiGeometryData * geometryData = niptr_cast(legacyGeometry->m_spModelData); + if (geometryData) { + numVertices = geometryData->m_usVertices; + } + } + else { + gIndex++; + return false; + } + GFxValue gfxGeom; args->movie->CreateObject(&gfxGeom); - RegisterString(&gfxGeom, args->movie, "name", geometry->m_name); - RegisterNumber(&gfxGeom, "vertices", geometryData->m_usVertices); + RegisterString(&gfxGeom, args->movie, "name", trishape->m_name); + RegisterNumber(&gfxGeom, "vertices", numVertices); RegisterNumber(&gfxGeom, "gIndex", gIndex); args->result->PushBack(&gfxGeom); gIndex++; @@ -534,9 +517,6 @@ void SKSEScaleform_ImportHead::Invoke(Args * args) return false; }); - - //args->result->SetMember("source", &source); - //args->result->SetMember("destination", &destination); } } } @@ -549,14 +529,11 @@ void SKSEScaleform_ImportHead::Invoke(Args * args) // Release the created NiStream CALL_MEMBER_FN(niStream, dtor)(); -#endif } void SKSEScaleform_ReleaseImportedHead::Invoke(Args * args) { -#ifdef FIXME g_World.ReleaseImport(); -#endif } void SKSEScaleform_LoadImportedHead::Invoke(Args * args) @@ -564,13 +541,13 @@ void SKSEScaleform_LoadImportedHead::Invoke(Args * args) ASSERT(args->numArgs >= 1); ASSERT(args->args[0].GetType() == GFxValue::kType_Array); -#ifdef FIXME - UInt32 meshLength = min(g_World.GetNumMeshes(), args->args[0].GetArraySize()); + UInt32 meshLength = g_World.GetNumMeshes(); + UInt32 reqLength = args->args[0].GetArraySize(); - for (UInt32 i = 0; i < meshLength; i++) + for (UInt32 i = 0, m = 0; i < meshLength && m < reqLength; i++) { - CDXNifMesh * mesh = static_cast(g_World.GetNthMesh(i)); + CDXNifMesh * mesh = dynamic_cast(g_World.GetNthMesh(i)); if (mesh) { NiNode * importRoot = g_World.GetImportRoot(); if (importRoot) { @@ -578,28 +555,32 @@ void SKSEScaleform_LoadImportedHead::Invoke(Args * args) SInt32 searchIndex = -1; GFxValue gfxIndex; - args->args[0].GetElement(i, &gfxIndex); + args->args[0].GetElement(m, &gfxIndex); searchIndex = gfxIndex.GetNumber(); - NiGeometry * sourceGeometry = NULL; + NiAVObject * sourceGeometry = NULL; SInt32 gIndex = 0; VisitObjects(importRoot, [&gIndex, &args, &searchIndex, &sourceGeometry](NiAVObject* trishape) { NiNode * parent = trishape->m_parent; if (parent && BSFixedString(parent->m_name) == BSFixedString("BSFaceGenNiNodeSkinned")) { - NiTriBasedGeom * geometry = trishape->GetAsNiTriBasedGeom(); - if (!geometry) - return false; - - NiGeometryData * geometryData = niptr_cast(geometry->m_spModelData); - if (!geometryData) - return false; + NiTriBasedGeom * legacyGeometry = trishape->GetAsNiTriBasedGeom(); + BSTriShape * geometry = trishape->GetAsBSTriShape(); + + if (legacyGeometry) { + NiGeometryData * geometryData = niptr_cast(legacyGeometry->m_spModelData); + if (!geometryData) { + gIndex++; + return false; + } + } if (searchIndex == gIndex) { - sourceGeometry = geometry; + if (geometry) sourceGeometry = geometry; + else if (legacyGeometry) sourceGeometry = legacyGeometry; + else return false; return true; } - gIndex++; } @@ -612,9 +593,10 @@ void SKSEScaleform_LoadImportedHead::Invoke(Args * args) importGeometry->Apply(g_undoStack.Push(importGeometry)); } } + + m++; } } -#endif } @@ -623,8 +605,6 @@ void SKSEScaleform_ClearSculptData::Invoke(Args * args) ASSERT(args->numArgs >= 1); ASSERT(args->args[0].GetType() == GFxValue::kType_Array); -#ifdef FIXME - UInt32 meshLength = args->args[0].GetArraySize(); for (UInt32 i = 0; i < meshLength; i++) @@ -633,14 +613,13 @@ void SKSEScaleform_ClearSculptData::Invoke(Args * args) args->args[0].GetElement(i, &gfxIndex); SInt32 meshIndex = gfxIndex.GetNumber(); - CDXNifMesh * mesh = static_cast(g_World.GetNthMesh(meshIndex)); + CDXNifMesh * mesh = dynamic_cast(g_World.GetNthMesh(meshIndex)); if (mesh) { std::shared_ptr resetGeometry = std::make_shared(mesh); if (resetGeometry->Length() > 0) resetGeometry->Apply(g_undoStack.Push(resetGeometry)); } } -#endif } @@ -814,37 +793,87 @@ void SKSEScaleform_SetRaceSexCameraPos::Invoke(Args * args) void SKSEScaleform_CreateMorphEditor::Invoke(Args * args) { -#ifdef FIXME - ID3D11Device * pDevice = NiDX9Renderer::GetSingleton()->m_pkD3DDevice9; - if (!pDevice) { - _ERROR("%s - Failed to acquire DirectX device.", __FUNCTION__); + auto pDeviceContext = g_renderManager->context; + + Microsoft::WRL::ComPtr pDevice; + pDeviceContext->GetDevice(&pDevice); + if (!pDevice) // This shouldnt happen + return; + + Microsoft::WRL::ComPtr device3; + pDevice->QueryInterface(__uuidof(ID3D11Device3), (void**)&device3); + if (!device3) { + _ERROR("%s - Failed to acquire device3.", __FUNCTION__); return; } - PlayerCharacter * player = (*g_thePlayer); - g_Camera.SetProjParams(g_cameraFOV * (D3DX_PI / 180.0f), 1.0f, 1.0f, 1000.0f); + g_Device = new CDXD3DDevice(device3, pDeviceContext); + + CDXInitParams initParams; + initParams.camera = &g_Camera; + initParams.device = g_Device; + initParams.viewportWidth = g_viewWidth; + initParams.viewportHeight = g_viewHeight; + + CDXVec vecEye = DirectX::XMVectorSet(32.0f, 0.0f, 0.0f, 1.0f); + CDXVec vecAt = DirectX::XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f); + g_Camera.SetWindow(initParams.viewportWidth, initParams.viewportHeight); + g_Camera.SetViewParams(&vecEye, &vecAt); + g_Camera.SetProjParams(g_cameraFOV * (DirectX::XM_PI / 180.0f), 1.0f, 1.0f, 1000.0f); g_Camera.SetPanSpeed(g_panSpeed); - g_World.SetWorkingActor(player); - g_World.Setup(pDevice); + g_Camera.Update(); - Actor * actor = g_World.GetWorkingActor(); - if (!actor) { + const char * shaderPaths[] = { + "SKSE/Plugins/CharGen/shader.vs", + "SKSE/Plugins/CharGen/shader.ps" + }; + + std::vector vsb, psb; + BSResourceNiBinaryStream vs(shaderPaths[0]), ps(shaderPaths[1]); + if (!vs.IsValid()) { + _ERROR("%s - Failed to read %s", __FUNCTION__, shaderPaths[0]); + return; + } + if (!ps.IsValid()) { + _ERROR("%s - Failed to read %s", __FUNCTION__, shaderPaths[1]); + return; + } + BSFileUtil::ReadAll(&vs, vsb); + BSFileUtil::ReadAll(&ps, psb); + + initParams.vertexShader.pSrcData = &vsb.at(0); + initParams.vertexShader.SrcDataSize = vsb.size(); + initParams.vertexShader.pSourceName = "shader.vs"; + initParams.pixelShader.pSrcData = &psb.at(0); + initParams.pixelShader.SrcDataSize = psb.size(); + initParams.pixelShader.pSourceName = "shader.ps"; + + if (!g_World.Setup(initParams)) { + _ERROR("%s - Failed to setup world.", __FUNCTION__); + return; + } + + PlayerCharacter * player = (*g_thePlayer); + if (!player) { _ERROR("%s - Invalid working actor.", __FUNCTION__); return; } - TESNPC * actorBase = DYNAMIC_CAST(actor->baseForm, TESForm, TESNPC); + TESNPC * actorBase = DYNAMIC_CAST(player->baseForm, TESForm, TESNPC); if (!actorBase) { _ERROR("%s - No actor base.", __FUNCTION__); return; } - NiNode * rootFaceGen = actor->GetFaceGenNiNode(); + NiNode * rootFaceGen = player->GetFaceGenNiNode(); if (!rootFaceGen) { _ERROR("%s - No FaceGen node.", __FUNCTION__); return; } + g_World.SetWorkingActor(player); + +#if 0 BSFaceGenAnimationData * animationData = actor->GetFaceGenAnimationData(); if (animationData) { FaceGen::GetSingleton()->isReset = 0; @@ -857,6 +886,7 @@ void SKSEScaleform_CreateMorphEditor::Invoke(Args * args) } UpdateModelFace(rootFaceGen); } +#endif UInt32 numHeadParts = actorBase->numHeadParts; BGSHeadPart ** headParts = actorBase->headparts; @@ -893,7 +923,17 @@ void SKSEScaleform_CreateMorphEditor::Invoke(Args * args) continue; if(headPart->partName == BSFixedString(object->m_name)) { - CDXNifMesh * mesh = CDXNifMesh::Create(pDevice, object->GetAsNiGeometry()); + NiGeometry* legacyGeometry = object->GetAsNiGeometry(); + BSTriShape* geometry = object->GetAsBSTriShape(); + + CDXNifMesh * mesh = nullptr; + if (legacyGeometry) { + mesh = CDXLegacyNifMesh::Create(g_Device, legacyGeometry); + } + if (geometry) { + mesh = CDXBSTriShapeMesh::Create(g_Device, geometry); + } + if (!mesh) continue; @@ -902,7 +942,7 @@ void SKSEScaleform_CreateMorphEditor::Invoke(Args * args) CDXMaterial * material = mesh->GetMaterial(); if (material) - material->SetWireframeColor(CDXVec3(((colors[i] >> 16) & 0xFF) / 255.0, ((colors[i] >> 8) & 0xFF) / 255.0, (colors[i] & 0xFF) / 255.0)); + material->SetWireframeColor(DirectX::XMFLOAT4(((colors[i] >> 16) & 0xFF) / 255.0, ((colors[i] >> 8) & 0xFF) / 255.0, (colors[i] & 0xFF) / 255.0, 1.0f)); if (headPart->type != BGSHeadPart::kTypeFace) mesh->SetLocked(true); @@ -913,24 +953,25 @@ void SKSEScaleform_CreateMorphEditor::Invoke(Args * args) } } +#if 0 if (animationData) { animationData->overrideFlag = 0; CALL_MEMBER_FN(animationData, Reset)(1.0, 1, 1, 0, 0); FaceGen::GetSingleton()->isReset = 1; UpdateModelFace(rootFaceGen); } +#endif args->movie->CreateObject(args->result); - RegisterNumber(args->result, "width", g_World.GetWidth()); - RegisterNumber(args->result, "height", g_World.GetHeight()); -#endif + RegisterNumber(args->result, "width", initParams.viewportWidth); + RegisterNumber(args->result, "height", initParams.viewportHeight); } void SKSEScaleform_ReleaseMorphEditor::Invoke(Args * args) { -#ifdef FIXME g_World.Release(); -#endif + delete g_Device; + g_Device = nullptr; } void SKSEScaleform_BeginRotateMesh::Invoke(Args * args) @@ -939,9 +980,7 @@ void SKSEScaleform_BeginRotateMesh::Invoke(Args * args) ASSERT(args->args[0].GetType() == GFxValue::kType_Number); ASSERT(args->args[1].GetType() == GFxValue::kType_Number); -#ifdef FIXME g_Camera.OnRotateBegin(args->args[0].GetNumber(), args->args[1].GetNumber()); -#endif }; void SKSEScaleform_DoRotateMesh::Invoke(Args * args) @@ -950,16 +989,12 @@ void SKSEScaleform_DoRotateMesh::Invoke(Args * args) ASSERT(args->args[0].GetType() == GFxValue::kType_Number); ASSERT(args->args[1].GetType() == GFxValue::kType_Number); -#ifdef FIXME g_Camera.OnRotate(args->args[0].GetNumber(), args->args[1].GetNumber()); -#endif }; void SKSEScaleform_EndRotateMesh::Invoke(Args * args) { -#ifdef FIXME g_Camera.OnRotateEnd(); -#endif }; void SKSEScaleform_BeginPanMesh::Invoke(Args * args) @@ -968,9 +1003,7 @@ void SKSEScaleform_BeginPanMesh::Invoke(Args * args) ASSERT(args->args[0].GetType() == GFxValue::kType_Number); ASSERT(args->args[1].GetType() == GFxValue::kType_Number); -#ifdef FIXME g_Camera.OnMoveBegin(args->args[0].GetNumber(), args->args[1].GetNumber()); -#endif }; void SKSEScaleform_DoPanMesh::Invoke(Args * args) @@ -979,16 +1012,12 @@ void SKSEScaleform_DoPanMesh::Invoke(Args * args) ASSERT(args->args[0].GetType() == GFxValue::kType_Number); ASSERT(args->args[1].GetType() == GFxValue::kType_Number); -#ifdef FIXME g_Camera.OnMove(args->args[0].GetNumber(), args->args[1].GetNumber()); -#endif }; void SKSEScaleform_EndPanMesh::Invoke(Args * args) { -#ifdef FIXME g_Camera.OnMoveEnd(); -#endif }; void SKSEScaleform_BeginPaintMesh::Invoke(Args * args) @@ -1001,15 +1030,14 @@ void SKSEScaleform_BeginPaintMesh::Invoke(Args * args) SInt32 y = args->args[1].GetNumber(); bool hitMesh = false; -#ifdef FIXME + CDXBrush * brush = g_World.GetCurrentBrush(); if (brush) { CDXBrushPickerBegin brushStroke(brush); brushStroke.SetMirror(brush->IsMirror()); - if (g_World.Pick(x, y, brushStroke)) + if (g_World.Pick(&g_Camera, x, y, brushStroke)) hitMesh = true; } -#endif args->result->SetBool(hitMesh); }; @@ -1023,36 +1051,44 @@ void SKSEScaleform_DoPaintMesh::Invoke(Args * args) SInt32 x = args->args[0].GetNumber(); SInt32 y = args->args[1].GetNumber(); -#ifdef FIXME - CDXBrush * brush = g_World.GetCurrentBrush(); if (brush) { CDXBrushPickerUpdate brushStroke(brush); brushStroke.SetMirror(brush->IsMirror()); - g_World.Pick(x, y, brushStroke); + g_World.Pick(&g_Camera, x, y, brushStroke); } -#endif }; void SKSEScaleform_EndPaintMesh::Invoke(Args * args) { -#ifdef FIXME CDXBrush * brush = g_World.GetCurrentBrush(); if(brush) brush->EndStroke(); -#endif }; +void SKSEScaleform_DoHoverMesh::Invoke(Args * args) +{ + ASSERT(args->numArgs >= 2); + ASSERT(args->args[0].GetType() == GFxValue::kType_Number); + ASSERT(args->args[1].GetType() == GFxValue::kType_Number); + + SInt32 x = args->args[0].GetNumber(); + SInt32 y = args->args[1].GetNumber(); + + CDXBrush * brush = g_World.GetCurrentBrush(); + if (brush) { + CDXBrushTranslator translator(brush, static_cast(g_World.GetNthMesh(0)), static_cast(g_World.GetNthMesh(1))); + g_World.Pick(&g_Camera, x, y, translator); + } +}; void SKSEScaleform_GetCurrentBrush::Invoke(Args * args) { -#ifdef FIXME CDXBrush * brush = g_World.GetCurrentBrush(); if (brush) args->result->SetNumber(brush->GetType()); else args->result->SetNull(); -#endif } void SKSEScaleform_SetCurrentBrush::Invoke(Args * args) @@ -1060,21 +1096,18 @@ void SKSEScaleform_SetCurrentBrush::Invoke(Args * args) ASSERT(args->numArgs >= 1); ASSERT(args->args[0].GetType() == GFxValue::kType_Number); -#ifdef FIXME CDXBrush::BrushType brushType = (CDXBrush::BrushType)(UInt32)args->args[0].GetNumber(); CDXBrush * brush = g_World.GetBrush(brushType); if (brush) g_World.SetCurrentBrush(brushType); args->result->SetBool(brush != NULL); -#endif } void SKSEScaleform_GetBrushes::Invoke(Args * args) { args->movie->CreateArray(args->result); -#ifdef FIXME for (auto brush : g_World.GetBrushes()) { GFxValue object; args->movie->CreateObject(&object); @@ -1094,7 +1127,6 @@ void SKSEScaleform_GetBrushes::Invoke(Args * args) RegisterNumber(&object, "mirror", brush->IsMirror() ? 1.0 : 0.0); args->result->PushBack(&object); } -#endif } void SKSEScaleform_SetBrushData::Invoke(Args * args) @@ -1103,7 +1135,6 @@ void SKSEScaleform_SetBrushData::Invoke(Args * args) ASSERT(args->args[0].GetType() == GFxValue::kType_Number); ASSERT(args->args[1].GetType() == GFxValue::kType_Object); -#ifdef FIXME CDXBrush::BrushType brushType = (CDXBrush::BrushType)(UInt32)args->args[0].GetNumber(); CDXBrush * brush = g_World.GetBrush(brushType); if (brush) { @@ -1126,41 +1157,35 @@ void SKSEScaleform_SetBrushData::Invoke(Args * args) else { args->result->SetBool(false); } -#endif } void SKSEScaleform_GetMeshes::Invoke(Args * args) { args->movie->CreateArray(args->result); -#ifdef FIXME for (UInt32 i = 0; i < g_World.GetNumMeshes(); i++) { - CDXNifMesh * mesh = static_cast(g_World.GetNthMesh(i)); - if (mesh) { - NiGeometry * geometry = mesh->GetNifGeometry(); - if (geometry) { - GFxValue object; - args->movie->CreateObject(&object); - RegisterString(&object, args->movie, "name", geometry->m_name); - RegisterNumber(&object, "meshIndex", i); - RegisterBool(&object, "wireframe", mesh->ShowWireframe()); - RegisterBool(&object, "locked", mesh->IsLocked()); - RegisterBool(&object, "visible", mesh->IsVisible()); - RegisterBool(&object, "morphable", mesh->IsMorphable()); - RegisterNumber(&object, "vertices", mesh->GetVertexCount()); - - CDXMaterial * material = mesh->GetMaterial(); - if (material) { - CDXVec3 fColor = material->GetWireframeColor(); - UInt32 color = 0xFF000000 | (UInt32)(fColor.x * 255) << 16 | (UInt32)(fColor.y * 255) << 8 | (UInt32)(fColor.z * 255); - RegisterNumber(&object, "wfColor", color); - } - - args->result->PushBack(&object); + CDXMesh * mesh = g_World.GetNthMesh(i); + if (mesh && mesh->IsEditable()) { + GFxValue object; + args->movie->CreateObject(&object); + RegisterString(&object, args->movie, "name", mesh->GetName()); + RegisterNumber(&object, "meshIndex", i); + RegisterBool(&object, "wireframe", mesh->ShowWireframe()); + RegisterBool(&object, "locked", mesh->IsLocked()); + RegisterBool(&object, "visible", mesh->IsVisible()); + RegisterBool(&object, "morphable", mesh->IsMorphable()); + RegisterNumber(&object, "vertices", mesh->GetVertexCount()); + + CDXMaterial * material = mesh->GetMaterial(); + if (material) { + DirectX::XMFLOAT4 fColor = material->GetWireframeColor(); + UInt32 color = 0xFF000000 | (UInt32)(fColor.x * 255) << 16 | (UInt32)(fColor.y * 255) << 8 | (UInt32)(fColor.z * 255); + RegisterNumber(&object, "wfColor", color); } + + args->result->PushBack(&object); } } -#endif } void SKSEScaleform_SetMeshData::Invoke(Args * args) @@ -1171,8 +1196,7 @@ void SKSEScaleform_SetMeshData::Invoke(Args * args) UInt32 i = (UInt32)args->args[0].GetNumber(); -#ifdef FIXME - CDXNifMesh * mesh = static_cast(g_World.GetNthMesh(i)); + CDXEditableMesh * mesh = dynamic_cast(g_World.GetNthMesh(i)); if (mesh) { GFxValue wireframe; args->args[1].GetMember("wireframe", &wireframe); @@ -1189,7 +1213,7 @@ void SKSEScaleform_SetMeshData::Invoke(Args * args) CDXMaterial * material = mesh->GetMaterial(); if (material) { UInt32 color = wfColor.GetNumber(); - material->SetWireframeColor(CDXVec3(((color >> 16) & 0xFF) / 255.0, ((color >> 8) & 0xFF) / 255.0, (color & 0xFF) / 255.0)); + material->SetWireframeColor(DirectX::XMFLOAT4(((color >> 16) & 0xFF) / 255.0, ((color >> 8) & 0xFF) / 255.0, (color & 0xFF) / 255.0, 1.0f)); } args->result->SetBool(true); @@ -1197,28 +1221,21 @@ void SKSEScaleform_SetMeshData::Invoke(Args * args) else { args->result->SetBool(false); } -#endif } void SKSEScaleform_GetActionLimit::Invoke(Args * args) { -#ifdef FIXME args->result->SetNumber(g_undoStack.GetLimit()); -#endif } void SKSEScaleform_UndoAction::Invoke(Args * args) { -#ifdef FIXME args->result->SetNumber(g_undoStack.Undo(true)); -#endif } void SKSEScaleform_RedoAction::Invoke(Args * args) { -#ifdef FIXME args->result->SetNumber(g_undoStack.Redo(true)); -#endif } void SKSEScaleform_GoToAction::Invoke(Args * args) @@ -1226,7 +1243,6 @@ void SKSEScaleform_GoToAction::Invoke(Args * args) ASSERT(args->numArgs >= 1); ASSERT(args->args[0].GetType() == GFxValue::kType_Number); -#ifdef FIXME SInt32 previous = g_undoStack.GetIndex(); SInt32 result = g_undoStack.GoTo(args->args[0].GetNumber(), true); @@ -1239,14 +1255,11 @@ void SKSEScaleform_GoToAction::Invoke(Args * args) } args->result->SetNumber(result); -#endif } void SKSEScaleform_GetMeshCameraRadius::Invoke(Args * args) { -#ifdef FIXME args->result->SetNumber(g_Camera.GetRadius()); -#endif } void SKSEScaleform_SetMeshCameraRadius::Invoke(Args * args) @@ -1254,10 +1267,8 @@ void SKSEScaleform_SetMeshCameraRadius::Invoke(Args * args) ASSERT(args->numArgs >= 1); ASSERT(args->args[0].GetType() == GFxValue::kType_Number); -#ifdef FIXME g_Camera.SetRadius(args->args[0].GetNumber()); g_Camera.Update(); -#endif } #include diff --git a/skee/ScaleformCharGenFunctions.h b/skee/ScaleformCharGenFunctions.h index 3c9d831..9b4d770 100644 --- a/skee/ScaleformCharGenFunctions.h +++ b/skee/ScaleformCharGenFunctions.h @@ -184,6 +184,13 @@ class SKSEScaleform_EndPaintMesh : public GFxFunctionHandler virtual void Invoke(Args * args); }; + +class SKSEScaleform_DoHoverMesh : public GFxFunctionHandler +{ +public: + virtual void Invoke(Args * args); +}; + class SKSEScaleform_GetCurrentBrush : public GFxFunctionHandler { public: diff --git a/skee/ScaleformFunctions_chargen.cpp b/skee/ScaleformFunctions_chargen.cpp deleted file mode 100644 index 1ccbdcf..0000000 --- a/skee/ScaleformFunctions_chargen.cpp +++ /dev/null @@ -1,1317 +0,0 @@ -#include "common/IFileStream.h" - -#include "skse/PluginAPI.h" -#include "skse/skse_version.h" - -#include "ScaleformFunctions.h" -#include "MorphHandler.h" -#include "PartHandler.h" - -#include "skse/GameAPI.h" -#include "skse/GameData.h" -#include "skse/GameObjects.h" -#include "skse/GameRTTI.h" -#include "skse/GameStreams.h" -#include "skse/GameMenus.h" - -#include "NifUtils.h" - -#include "skse/NiRTTI.h" -#include "skse/NiObjects.h" -#include "skse/NiNodes.h" -#include "skse/NiGeometry.h" -#include "skse/NiSerialization.h" - -#include "skse/ScaleformMovie.h" -#include "skse/ScaleformLoader.h" - -#include "interfaces/OverrideVariant.h" -#include "interfaces/OverrideInterface.h" -#include "interfaces/OverlayInterface.h" -#include "interfaces/NiTransformInterface.h" -#include "interfaces/BodyMorphInterface.h" - -extern OverrideInterface * g_overrideInterface; -extern NiTransformInterface * g_transformInterface; -extern OverlayInterface * g_overlayInterface; -extern BodyMorphInterface * g_bodyMorphInterface; - -extern MorphHandler g_morphHandler; -extern PartSet g_partSet; - -extern SKSETaskInterface * g_task; - -#include "CDXCamera.h" -#include "skse/NiRenderer.h" - -#include "CDXNifScene.h" -#include "CDXNifMesh.h" -#include "CDXBrush.h" -#include "CDXUndo.h" -#include "CDXNifCommands.h" - -#include "skse/NiExtraData.h" - -UInt32 colors[] = { - 0xffffff, 0xff0000, 0x0000ff, 0x00ff00, - 0xff00ff, 0xffff00, 0x00ffff, 0x79f2f2, - 0xe58473, 0xe673da, 0x57d936, 0xcc3d00, - 0x5233cc, 0xcc9466, 0xbf001d, 0xb8bf30, - 0x8c007e, 0x466d8c, 0x287300, 0x397359, - 0x453973, 0x662e00, 0x050066, 0x665e1a, - 0x663342, 0x59332d, 0x4c000b, 0x40103b, - 0x33240d, 0x20330d, 0x0d1633, 0x1a332f -}; - -extern CDXModelViewerCamera g_Camera; -extern CDXNifScene g_World; -extern float g_panSpeed; -extern float g_cameraFOV; - -void RegisterNumber(GFxValue * dst, const char * name, double value) -{ - GFxValue fxValue; - fxValue.SetNumber(value); - dst->SetMember(name, &fxValue); -} - -void RegisterBool(GFxValue * dst, const char * name, bool value) -{ - GFxValue fxValue; - fxValue.SetBool(value); - dst->SetMember(name, &fxValue); -} - -void RegisterUnmanagedString(GFxValue * dst, const char * name, const char * str) -{ - GFxValue fxValue; - fxValue.SetString(str); - dst->SetMember(name, &fxValue); -} - -void RegisterString(GFxValue * dst, GFxMovieView * view, const char * name, const char * str) -{ - GFxValue fxValue; - view->CreateString(&fxValue, str); - dst->SetMember(name, &fxValue); -} - -void SKSEScaleform_SavePreset::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 1); - ASSERT(args->args[0].GetType() == GFxValue::kType_String); - ASSERT(args->args[1].GetType() == GFxValue::kType_Bool); - - bool saveJson = args->args[1].GetBool(); - const char * strData = args->args[0].GetString(); - - if (saveJson) - args->result->SetBool(g_morphHandler.SaveJsonPreset(strData)); - else - args->result->SetBool(g_morphHandler.SaveBinaryPreset(strData)); -} - -void SKSEScaleform_LoadPreset::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 1); - ASSERT(args->args[0].GetType() == GFxValue::kType_String); - ASSERT(args->args[1].GetType() == GFxValue::kType_Object); - ASSERT(args->args[2].GetType() == GFxValue::kType_Bool); - - bool loadJson = args->args[2].GetBool(); - - const char * strData = args->args[0].GetString(); - - GFxValue * object = NULL; - if (args->numArgs >= 2) - object = &args->args[1]; - - auto presetData = std::make_shared(); - bool loadError = loadJson ? g_morphHandler.LoadJsonPreset(strData, presetData) : g_morphHandler.LoadBinaryPreset(strData, presetData);//g_morphHandler.LoadPreset(strData, args->movie, object); - if (!loadError) { - g_morphHandler.ApplyPresetData(*g_thePlayer, presetData); - - RegisterNumber(object, "hairColor", presetData->hairColor); - - GFxValue tintArray; - args->movie->CreateArray(&tintArray); - - for(auto & tint : presetData->tints) { - GFxValue tintObject; - args->movie->CreateObject(&tintObject); - RegisterNumber(&tintObject, "color", tint.color); - RegisterNumber(&tintObject, "index", tint.index); - RegisterString(&tintObject, args->movie, "texture", tint.name.data); - tintArray.PushBack(&tintObject); - } - - object->SetMember("tints", &tintArray); - } - - args->result->SetBool(loadError); -} - -const char * GetGameSettingString(const char * key) -{ - Setting * setting = (*g_gameSettingCollection)->Get(key); - if(setting && setting->GetType() == Setting::kType_String) - return setting->data.s; - - return NULL; -} - -void SKSEScaleform_ReadPreset::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 1); - ASSERT(args->args[0].GetType() == GFxValue::kType_String); - ASSERT(args->args[1].GetType() == GFxValue::kType_Object); - ASSERT(args->args[2].GetType() == GFxValue::kType_Bool); - - bool loadJson = args->args[2].GetBool(); - const char * strData = args->args[0].GetString(); - - - GFxValue * object = NULL; - if (args->numArgs >= 2) - object = &args->args[1]; - - DataHandler * dataHandler = DataHandler::GetSingleton(); - auto presetData = std::make_shared(); - bool loadError = loadJson ? g_morphHandler.LoadJsonPreset(strData, presetData) : g_morphHandler.LoadBinaryPreset(strData, presetData);//g_morphHandler.LoadPreset(strData, args->movie, object); - if(!loadError) { - PlayerCharacter * player = (*g_thePlayer); - TESNPC * npc = DYNAMIC_CAST(player->baseForm, TESForm, TESNPC); - - GFxValue modArray; - args->movie->CreateArray(&modArray); - for(std::vector::iterator it = presetData->modList.begin(); it != presetData->modList.end(); ++it) { - GFxValue modObject; - args->movie->CreateObject(&modObject); - RegisterString(&modObject, args->movie, "name", (*it).c_str()); - RegisterNumber(&modObject, "loadedIndex", dataHandler->GetModIndex((*it).c_str())); - modArray.PushBack(&modObject); - } - object->SetMember("mods", &modArray); - - GFxValue partArray; - args->movie->CreateArray(&partArray); - for(std::vector::iterator it = presetData->headParts.begin(); it != presetData->headParts.end(); ++it) { - GFxValue partObject; - args->movie->CreateString(&partObject, (*it)->partName.data); - partArray.PushBack(&partObject); - } - object->SetMember("headParts", &partArray); - - GFxValue weightObject; - args->movie->CreateObject(&weightObject); - RegisterUnmanagedString(&weightObject, "name", GetGameSettingString("sRSMWeight")); - RegisterNumber(&weightObject, "value", presetData->weight); - object->SetMember("weight", &weightObject); - - GFxValue hairObject; - args->movie->CreateObject(&hairObject); - RegisterUnmanagedString(&hairObject, "name", GetGameSettingString("sRSMHairColorPresets")); - RegisterNumber(&hairObject, "value", presetData->hairColor); - object->SetMember("hair", &hairObject); - - GFxValue tintArray; - args->movie->CreateArray(&tintArray); - for(std::vector::iterator it = presetData->tints.begin(); it != presetData->tints.end(); ++it) { - PresetData::Tint & tint = (*it); - GFxValue tintObject; - args->movie->CreateObject(&tintObject); - RegisterNumber(&tintObject, "color", tint.color); - RegisterNumber(&tintObject, "index", tint.index); - RegisterString(&tintObject, args->movie, "texture", tint.name.data); - tintArray.PushBack(&tintObject); - } - object->SetMember("tints", &tintArray); - - GFxValue morphArray; - args->movie->CreateArray(&morphArray); - - const char * presetNames[FacePresetList::kNumPresets]; - presetNames[FacePresetList::kPreset_NoseType] = GetGameSettingString("sRSMNoseTypes"); - presetNames[FacePresetList::kPreset_BrowType] = GetGameSettingString("sRSMBrowTypes"); - presetNames[FacePresetList::kPreset_EyesType] = GetGameSettingString("sRSMEyeTypes"); - presetNames[FacePresetList::kPreset_LipType] = GetGameSettingString("sRSMMouthTypes"); - - const char * morphNames[FaceMorphList::kNumMorphs]; - morphNames[FaceMorphList::kMorph_NoseShortLong] = GetGameSettingString("sRSMNoseLength"); - morphNames[FaceMorphList::kMorph_NoseDownUp] = GetGameSettingString("sRSMNoseHeight"); - morphNames[FaceMorphList::kMorph_JawUpDown] = GetGameSettingString("sRSMJawHeight"); - morphNames[FaceMorphList::kMorph_JawNarrowWide] = GetGameSettingString("sRSMJawWidth"); - morphNames[FaceMorphList::kMorph_JawBackForward] = GetGameSettingString("sRSMJawForward"); - morphNames[FaceMorphList::kMorph_CheeksDownUp] = GetGameSettingString("sRSMCheekboneHeight"); - morphNames[FaceMorphList::kMorph_CheeksInOut] = GetGameSettingString("sRSMCheekboneWidth"); - morphNames[FaceMorphList::kMorph_EyesMoveDownUp] = GetGameSettingString("sRSMEyeHeight"); - morphNames[FaceMorphList::kMorph_EyesMoveInOut] = GetGameSettingString("sRSMEyeDepth"); - morphNames[FaceMorphList::kMorph_BrowDownUp] = GetGameSettingString("sRSMBrowHeight"); - morphNames[FaceMorphList::kMorph_BrowInOut] = GetGameSettingString("sRSMBrowWidth"); - morphNames[FaceMorphList::kMorph_BrowBackForward] = GetGameSettingString("sRSMBrowForward"); - morphNames[FaceMorphList::kMorph_LipMoveDownUp] = GetGameSettingString("sRSMMouthHeight"); - morphNames[FaceMorphList::kMorph_LipMoveInOut] = GetGameSettingString("sRSMMouthForward"); - morphNames[FaceMorphList::kMorph_ChinThinWide] = GetGameSettingString("sRSMChinWidth"); - morphNames[FaceMorphList::kMorph_ChinMoveUpDown] = GetGameSettingString("sRSMChinLength"); - morphNames[FaceMorphList::kMorph_OverbiteUnderbite] = GetGameSettingString("sRSMChinForward"); - morphNames[FaceMorphList::kMorph_EyesBackForward] = GetGameSettingString("sRSMEyeDepth"); - morphNames[FaceMorphList::kMorph_Vampire] = NULL; - - UInt32 i = 0; - for(std::vector::iterator it = presetData->presets.begin(); it != presetData->presets.end(); ++it) { - GFxValue presetObject; - args->movie->CreateObject(&presetObject); - if(presetNames[i]) - RegisterUnmanagedString(&presetObject, "name", presetNames[i]); - RegisterNumber(&presetObject, "value", *it); - RegisterNumber(&presetObject, "type", 0); - RegisterNumber(&presetObject, "index", i); - morphArray.PushBack(&presetObject); - i++; - } - - i = 0; - for(auto & it : presetData->morphs) { - GFxValue presetObject; - args->movie->CreateObject(&presetObject); - if (i < FaceMorphList::kNumMorphs && morphNames[i]) - RegisterUnmanagedString(&presetObject, "name", morphNames[i]); - RegisterNumber(&presetObject, "value", it); - RegisterNumber(&presetObject, "type", 1); - RegisterNumber(&presetObject, "index", i); - morphArray.PushBack(&presetObject); - i++; - } - - i = 0; - for(auto & it : presetData->customMorphs) { - std::string morphName = "$"; - morphName.append(it.name.data); - GFxValue customObject; - args->movie->CreateObject(&customObject); - RegisterString(&customObject, args->movie, "name", morphName.c_str()); - RegisterNumber(&customObject, "value", it.value); - RegisterNumber(&customObject, "type", 2); - RegisterNumber(&customObject, "index", i); - morphArray.PushBack(&customObject); - i++; - } - i = 0; - for (auto & it : presetData->bodyMorphData) { - GFxValue customObject; - args->movie->CreateObject(&customObject); - RegisterString(&customObject, args->movie, "name", it.first.data); - - float morphSum = 0; - for (auto & keys : it.second) - morphSum += keys.second; - - RegisterNumber(&customObject, "value", morphSum); - RegisterNumber(&customObject, "type", 3); - RegisterNumber(&customObject, "index", i); - morphArray.PushBack(&customObject); - i++; - } - object->SetMember("morphs", &morphArray); - } - - args->result->SetBool(loadError); -} - -void SKSEScaleform_ReloadSliders::Invoke(Args * args) -{ - MenuManager * mm = MenuManager::GetSingleton(); - if (mm) { - BSFixedString t("RaceSex Menu"); - RaceSexMenu* raceMenu = (RaceSexMenu*)mm->GetMenu(&t); - if(raceMenu) { - PlayerCharacter * player = (*g_thePlayer); - CALL_MEMBER_FN(raceMenu, LoadSliders)((UInt32)player->baseForm, 0); - //CALL_MEMBER_FN(raceMenu, UpdatePlayer)(); - CALL_MEMBER_FN((*g_thePlayer), QueueNiNodeUpdate)(true); - } - } -} - -void SKSEScaleform_GetSliderData::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 1); - ASSERT(args->args[0].GetType() == GFxValue::kType_Number); - ASSERT(args->args[1].GetType() == GFxValue::kType_Number); - - UInt32 sliderId = (UInt32)args->args[0].GetNumber(); - double value = args->args[1].GetNumber(); - - MenuManager * mm = MenuManager::GetSingleton(); - if(mm) - { - BSFixedString t("RaceSex Menu"); - RaceSexMenu * raceMenu = (RaceSexMenu *)mm->GetMenu(&t); - if(raceMenu) - { - RaceMenuSlider * slider = NULL; - RaceSexMenu::RaceComponent * raceData = NULL; - - UInt8 gender = 0; - PlayerCharacter * player = (*g_thePlayer); - TESNPC * actorBase = DYNAMIC_CAST(player->baseForm, TESForm, TESNPC); - if(actorBase) - gender = CALL_MEMBER_FN(actorBase, GetSex)(); - - if(raceMenu->raceIndex < raceMenu->sliderData[gender].count) - raceData = &raceMenu->sliderData[gender][raceMenu->raceIndex]; - if(raceData && sliderId < raceData->sliders.count) - slider = &raceData->sliders[sliderId]; - - if(raceData && slider) - { - args->movie->CreateObject(args->result); - RegisterNumber(args->result, "type", slider->type); - RegisterNumber(args->result, "index", slider->index); - - switch(slider->type) - { - case RaceMenuSlider::kTypeHeadPart: - { - if(slider->index < RaceSexMenu::kNumHeadPartLists) - { - BGSHeadPart * headPart = NULL; - raceMenu->headParts[slider->index].GetNthItem((UInt32)value, headPart); - if(headPart) { - RegisterNumber(args->result, "formId", headPart->formID); - RegisterString(args->result, args->movie, "partName", headPart->partName.data); - } - } - } - break; - case RaceMenuSlider::kTypeDoubleMorph: - { - // Provide case for custom parts - if(slider->index >= SLIDER_OFFSET) { - UInt32 sliderIndex = slider->index - SLIDER_OFFSET; - SliderInternalPtr sliderInternal = g_morphHandler.GetSliderByIndex(player->race, sliderIndex); - if(sliderInternal) { - RegisterNumber(args->result, "subType", sliderInternal->type); - switch (sliderInternal->type) - { - // Only acquire part information for actual part sliders - case SliderInternal::kTypeHeadPart: - { - UInt8 partType = sliderInternal->presetCount; - HeadPartList * partList = g_partSet.GetPartList(partType); - if (partList) - { - BGSHeadPart * targetPart = g_partSet.GetPartByIndex(partList, (UInt32)value - 1); - if (targetPart) { - RegisterNumber(args->result, "formId", targetPart->formID); - RegisterString(args->result, args->movie, "partName", targetPart->partName.data); - } - } - } - break; - } - } - } - } - break; - } - } - } - } -} - - -void SKSEScaleform_GetModName::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 1); - ASSERT(args->args[0].GetType() == GFxValue::kType_Number); - - UInt32 modIndex = (UInt32)args->args[0].GetNumber(); - - DataHandler* pDataHandler = DataHandler::GetSingleton(); - ModInfo* modInfo = pDataHandler->modList.modInfoList.GetNthItem(modIndex); - if(modInfo) { - args->movie->CreateString(args->result, modInfo->name); - } -} - -void SKSEScaleform_ExportHead::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 1); - ASSERT(args->args[0].GetType() == GFxValue::kType_String); - - const char * strData = args->args[0].GetString(); - - // Get the Editor's working actor - Actor * actor = g_World.GetWorkingActor(); - if (!actor) - return; - - std::string nifPath = strData; - nifPath.append(".nif"); - std::string ddsPath = strData; - ddsPath.append(".dds"); - - g_task->AddTask(new SKSETaskExportHead(actor, nifPath.c_str(), ddsPath.c_str())); -} - -void SKSEScaleform_ImportHead::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 1); - ASSERT(args->args[0].GetType() == GFxValue::kType_String); - - const char * strData = args->args[0].GetString(); - - // Release the previous import just in case - g_World.ReleaseImport(); - - // Get the Editor's working actor - Actor * actor = g_World.GetWorkingActor(); - if (!actor) - return; - - BSFaceGenNiNode * faceNode = actor->GetFaceGenNiNode(); - TESNPC * actorBase = DYNAMIC_CAST(actor->baseForm, TESForm, TESNPC); - if (!actorBase || !faceNode) - return; - - UInt8 niStreamMemory[0x5B4]; - memset(niStreamMemory, 0, 0x5B4); - NiStream * niStream = (NiStream *)niStreamMemory; - CALL_MEMBER_FN(niStream, ctor)(); - - NiNode * rootNode = NULL; - BSResourceNiBinaryStream binaryStream(strData); - if (binaryStream.IsValid()) - { - niStream->LoadStream(&binaryStream); - if (niStream->m_rootObjects.m_data) - { - if (niStream->m_rootObjects.m_data[0]) // Get the root node - rootNode = niStream->m_rootObjects.m_data[0]->GetAsNiNode(); - if (rootNode) - { - args->movie->CreateArray(args->result); - /*args->movie->CreateObject(args->result); - - GFxValue source; - args->movie->CreateArray(&source); - - - - GFxValue destination; - args->movie->CreateArray(&destination); - - UInt32 numParts = actorBase->numHeadParts; - BGSHeadPart ** headParts = actorBase->headparts; - if (CALL_MEMBER_FN(actorBase, HasOverlays)()) { - numParts = GetNumActorBaseOverlays(actorBase); - headParts = GetActorBaseOverlays(actorBase); - } - - for (UInt32 i = 0; i < numParts; i++) - { - BGSHeadPart * headPart = headParts[i]; - if (!headPart) - continue; - - NiTriBasedGeom * geometry = GetTriBasedGeomByHeadPart(faceNode, headPart); - if (!geometry) - continue; - - NiGeometryData * geometryData = niptr_cast(geometry->m_spModelData); - if (!geometryData) - continue; - - bool morphable = geometry->GetExtraData("FOD") != NULL; - - GFxValue gfxPart; - args->movie->CreateObject(&gfxPart); - RegisterString(&gfxPart, args->movie, "name", geometry->m_name); - RegisterNumber(&gfxPart, "vertices", geometryData->m_usVertices); - RegisterBool(&gfxPart, "morphable", morphable); - destination.PushBack(&gfxPart); - } - - */ - - SInt32 gIndex = 0; - VisitObjects(rootNode, [&gIndex, &args](NiAVObject* trishape) - { - NiNode * parent = trishape->m_parent; - if (parent && BSFixedString(parent->m_name) == BSFixedString("BSFaceGenNiNodeSkinned")) { - NiTriBasedGeom * geometry = trishape->GetAsNiTriBasedGeom(); - if (!geometry) - return false; - - NiGeometryData * geometryData = niptr_cast(geometry->m_spModelData); - if (!geometryData) - return false; - - GFxValue gfxGeom; - args->movie->CreateObject(&gfxGeom); - RegisterString(&gfxGeom, args->movie, "name", geometry->m_name); - RegisterNumber(&gfxGeom, "vertices", geometryData->m_usVertices); - RegisterNumber(&gfxGeom, "gIndex", gIndex); - args->result->PushBack(&gfxGeom); - gIndex++; - } - - return false; - }); - - //args->result->SetMember("source", &source); - //args->result->SetMember("destination", &destination); - } - } - } - - // Add the Root node to the Editor - if (rootNode) { - rootNode->IncRef(); - g_World.SetImportRoot(rootNode); - } - - // Release the created NiStream - CALL_MEMBER_FN(niStream, dtor)(); -} - -void SKSEScaleform_ReleaseImportedHead::Invoke(Args * args) -{ - g_World.ReleaseImport(); -} - -void SKSEScaleform_LoadImportedHead::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 1); - ASSERT(args->args[0].GetType() == GFxValue::kType_Array); - - UInt32 meshLength = min(g_World.GetNumMeshes(), args->args[0].GetArraySize()); - - for (UInt32 i = 0; i < meshLength; i++) - { - CDXNifMesh * mesh = static_cast(g_World.GetNthMesh(i)); - if (mesh) { - NiNode * importRoot = g_World.GetImportRoot(); - if (importRoot) { - - SInt32 searchIndex = -1; - - GFxValue gfxIndex; - args->args[0].GetElement(i, &gfxIndex); - searchIndex = gfxIndex.GetNumber(); - - NiGeometry * sourceGeometry = NULL; - SInt32 gIndex = 0; - VisitObjects(importRoot, [&gIndex, &args, &searchIndex, &sourceGeometry](NiAVObject* trishape) - { - NiNode * parent = trishape->m_parent; - if (parent && BSFixedString(parent->m_name) == BSFixedString("BSFaceGenNiNodeSkinned")) { - NiTriBasedGeom * geometry = trishape->GetAsNiTriBasedGeom(); - if (!geometry) - return false; - - NiGeometryData * geometryData = niptr_cast(geometry->m_spModelData); - if (!geometryData) - return false; - - if (searchIndex == gIndex) { - sourceGeometry = geometry; - return true; - } - - gIndex++; - } - - return false; - }); - - if (sourceGeometry) { - std::shared_ptr importGeometry = std::make_shared(mesh, sourceGeometry); - if (importGeometry->Length() > 0) - importGeometry->Apply(g_undoStack.Push(importGeometry)); - } - } - } - } -} - - -void SKSEScaleform_ClearSculptData::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 1); - ASSERT(args->args[0].GetType() == GFxValue::kType_Array); - - UInt32 meshLength = args->args[0].GetArraySize(); - - for (UInt32 i = 0; i < meshLength; i++) - { - GFxValue gfxIndex; - args->args[0].GetElement(i, &gfxIndex); - SInt32 meshIndex = gfxIndex.GetNumber(); - - CDXNifMesh * mesh = static_cast(g_World.GetNthMesh(meshIndex)); - if (mesh) { - std::shared_ptr resetGeometry = std::make_shared(mesh); - if (resetGeometry->Length() > 0) - resetGeometry->Apply(g_undoStack.Push(resetGeometry)); - } - } -} - - -void SKSEScaleform_GetHeadParts::Invoke(Args * args) -{ - args->movie->CreateObject(args->result); - - GFxValue partList; - args->movie->CreateArray(&partList); - - PlayerCharacter * player = (*g_thePlayer); - TESNPC * actorBase = DYNAMIC_CAST(player->baseForm, TESForm, TESNPC); - for(UInt32 i = 0; i < actorBase->numHeadParts; i++) - { - GFxValue partData; - args->movie->CreateObject(&partData); - - BGSHeadPart * headPart = actorBase->headparts[i]; - - GFxValue headPartData; - args->movie->CreateObject(&headPartData); - RegisterString(&headPartData, args->movie, "partName", headPart->partName.data); - RegisterNumber(&headPartData, "partFlags", headPart->partFlags); - RegisterNumber(&headPartData, "partType", headPart->type); - RegisterString(&headPartData, args->movie, "modelPath", headPart->model.GetModelName()); - RegisterString(&headPartData, args->movie, "chargenMorphPath", headPart->chargenMorph.GetModelName()); - RegisterString(&headPartData, args->movie, "raceMorphPath", headPart->raceMorph.GetModelName()); - partData.SetMember("base", &headPartData); - - // Get the overlay, if there is one - if(CALL_MEMBER_FN(actorBase, HasOverlays)()) { - BGSHeadPart * overlayPart = actorBase->GetHeadPartOverlayByType(headPart->type); - if(overlayPart) { - GFxValue overlayPartData; - args->movie->CreateObject(&overlayPartData); - RegisterString(&overlayPartData, args->movie, "partName", overlayPart->partName.data); - RegisterNumber(&overlayPartData, "partFlags", overlayPart->partFlags); - RegisterNumber(&overlayPartData, "partType", overlayPart->type); - RegisterString(&overlayPartData, args->movie, "modelPath", overlayPart->model.GetModelName()); - RegisterString(&overlayPartData, args->movie, "chargenMorphPath", overlayPart->chargenMorph.GetModelName()); - RegisterString(&overlayPartData, args->movie, "raceMorphPath", overlayPart->raceMorph.GetModelName()); - partData.SetMember("overlay", &overlayPartData); - } - } - - partList.PushBack(&partData); - } - - args->result->SetMember("parts", &partList); -} - -void SKSEScaleform_GetPlayerPosition::Invoke(Args * args) -{ - PlayerCharacter * player = (*g_thePlayer); - NiNode * root = player->GetNiRootNode(0); - if(root) { - args->movie->CreateObject(args->result); - GFxValue x; - x.SetNumber(root->m_localTransform.pos.x); - args->result->SetMember("x", &x); - GFxValue y; - y.SetNumber(root->m_localTransform.pos.y); - args->result->SetMember("y", &y); - GFxValue z; - z.SetNumber(root->m_localTransform.pos.z); - args->result->SetMember("z", &z); - } -} - -void SKSEScaleform_GetPlayerRotation::Invoke(Args * args) -{ - PlayerCharacter * player = (*g_thePlayer); - NiNode * root = player->GetNiRootNode(0); - - args->movie->CreateArray(args->result); - for(UInt32 i = 0; i < 3 * 3; i++) - { - GFxValue index; - index.SetNumber(((float*)(root->m_localTransform.rot.data))[i]); - args->result->PushBack(&index); - } -} - -void SKSEScaleform_SetPlayerRotation::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 1); - ASSERT(args->args[0].GetType() == GFxValue::kType_Array); - ASSERT(args->args[0].GetArraySize() == 9); - - PlayerCharacter * player = (*g_thePlayer); - NiNode * root = player->GetNiRootNode(0); - - for(UInt32 i = 0; i < 3 * 3; i++) - { - GFxValue val; - args->args[0].GetElement(i, &val); - if(val.GetType() != GFxValue::kType_Number) - break; - - ((float*)root->m_localTransform.rot.data)[i] = val.GetNumber(); - } - - NiAVObject::ControllerUpdateContext ctx; - root->UpdateWorldData(&ctx); -} - -void SKSEScaleform_GetRaceSexCameraRot::Invoke(Args * args) -{ - RaceSexMenu * raceMenu = DYNAMIC_CAST(MenuManager::GetSingleton()->GetMenu(&UIStringHolder::GetSingleton()->raceSexMenu), IMenu, RaceSexMenu); - if(raceMenu) { - NiNode * raceCamera = raceMenu->camera.cameraNode; - args->movie->CreateArray(args->result); - for(UInt32 i = 0; i < 3 * 3; i++) - { - GFxValue index; - index.SetNumber(((float*)raceCamera->m_localTransform.rot.data)[i]); - args->result->PushBack(&index); - } - } -} - -void SKSEScaleform_GetRaceSexCameraPos::Invoke(Args * args) -{ - RaceSexMenu * raceMenu = DYNAMIC_CAST(MenuManager::GetSingleton()->GetMenu(&UIStringHolder::GetSingleton()->raceSexMenu), IMenu, RaceSexMenu); - if(raceMenu) { - NiNode * raceCamera = raceMenu->camera.cameraNode; - args->movie->CreateObject(args->result); - GFxValue x; - x.SetNumber(raceCamera->m_localTransform.pos.x); - args->result->SetMember("x", &x); - GFxValue y; - y.SetNumber(raceCamera->m_localTransform.pos.y); - args->result->SetMember("y", &y); - GFxValue z; - z.SetNumber(raceCamera->m_localTransform.pos.z); - args->result->SetMember("z", &z); - } -} - -void SKSEScaleform_SetRaceSexCameraPos::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 1); - ASSERT(args->args[0].GetType() == GFxValue::kType_Object); - - RaceSexMenu * raceMenu = DYNAMIC_CAST(MenuManager::GetSingleton()->GetMenu(&UIStringHolder::GetSingleton()->raceSexMenu), IMenu, RaceSexMenu); - if(raceMenu) { - NiNode * raceCamera = raceMenu->camera.cameraNode; - - GFxValue val; - args->args[0].GetMember("x", &val); - if(val.GetType() == GFxValue::kType_Number) - raceCamera->m_localTransform.pos.x = val.GetNumber(); - - args->args[0].GetMember("y", &val); - if(val.GetType() == GFxValue::kType_Number) - raceCamera->m_localTransform.pos.y = val.GetNumber(); - - args->args[0].GetMember("z", &val); - if(val.GetType() == GFxValue::kType_Number) - raceCamera->m_localTransform.pos.z = val.GetNumber(); - - NiAVObject::ControllerUpdateContext ctx; - raceCamera->UpdateWorldData(&ctx); - } -} - -void SKSEScaleform_CreateMorphEditor::Invoke(Args * args) -{ - LPDIRECT3DDEVICE9 pDevice = NiDX9Renderer::GetSingleton()->m_pkD3DDevice9; - if (!pDevice) { - _ERROR("%s - Failed to acquire DirectX device.", __FUNCTION__); - return; - } - - PlayerCharacter * player = (*g_thePlayer); - g_Camera.SetProjParams(g_cameraFOV * (D3DX_PI / 180.0f), 1.0f, 1.0f, 1000.0f); - g_Camera.SetPanSpeed(g_panSpeed); - g_World.SetWorkingActor(player); - g_World.Setup(pDevice); - - Actor * actor = g_World.GetWorkingActor(); - if (!actor) { - _ERROR("%s - Invalid working actor.", __FUNCTION__); - return; - } - - TESNPC * actorBase = DYNAMIC_CAST(actor->baseForm, TESForm, TESNPC); - if (!actorBase) { - _ERROR("%s - No actor base.", __FUNCTION__); - return; - } - - NiNode * rootFaceGen = actor->GetFaceGenNiNode(); - if (!rootFaceGen) { - _ERROR("%s - No FaceGen node.", __FUNCTION__); - 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(rootFaceGen); - } - - UInt32 numHeadParts = actorBase->numHeadParts; - BGSHeadPart ** headParts = actorBase->headparts; - if (CALL_MEMBER_FN(actorBase, HasOverlays)()) { - numHeadParts = GetNumActorBaseOverlays(actorBase); - headParts = GetActorBaseOverlays(actorBase); - } - - // What?? - if (!headParts) { - _ERROR("%s - No head parts found.", __FUNCTION__); - return; - } - - for(UInt32 i = 0; i < rootFaceGen->m_children.m_emptyRunStart; i++) - { - std::set extraParts; // Collect extra hair parts - BGSHeadPart * hairPart = actorBase->GetCurrentHeadPartByType(BGSHeadPart::kTypeHair); - if(hairPart) { - BGSHeadPart * extraPart = NULL; - for(UInt32 p = 0; p < hairPart->extraParts.count; p++) { - if(hairPart->extraParts.GetNthItem(p, extraPart)) - extraParts.insert(extraPart); - } - } - - for(UInt32 h = 0; h < actorBase->numHeadParts; h++) { - BGSHeadPart * headPart = headParts[h]; - if (!headPart) - continue; - - NiAVObject * object = rootFaceGen->m_children.m_data[i]; - if (!object) - continue; - - if(headPart->partName == BSFixedString(object->m_name)) { - CDXNifMesh * mesh = CDXNifMesh::Create(pDevice, object->GetAsNiGeometry()); - if (!mesh) - continue; - - if (extraParts.find(headPart) != extraParts.end()) // Is one of the hair parts toggle visibility - mesh->SetVisible(false); - - CDXMaterial * material = mesh->GetMaterial(); - if (material) - material->SetWireframeColor(CDXVec3(((colors[i] >> 16) & 0xFF) / 255.0, ((colors[i] >> 8) & 0xFF) / 255.0, (colors[i] & 0xFF) / 255.0)); - - if (headPart->type != BGSHeadPart::kTypeFace) - mesh->SetLocked(true); - - g_World.AddMesh(mesh); - break; - } - } - } - - if (animationData) { - animationData->overrideFlag = 0; - CALL_MEMBER_FN(animationData, Reset)(1.0, 1, 1, 0, 0); - FaceGen::GetSingleton()->isReset = 1; - UpdateModelFace(rootFaceGen); - } - - args->movie->CreateObject(args->result); - RegisterNumber(args->result, "width", g_World.GetWidth()); - RegisterNumber(args->result, "height", g_World.GetHeight()); -} - -void SKSEScaleform_ReleaseMorphEditor::Invoke(Args * args) -{ - g_World.Release(); -} - -void SKSEScaleform_BeginRotateMesh::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 2); - ASSERT(args->args[0].GetType() == GFxValue::kType_Number); - ASSERT(args->args[1].GetType() == GFxValue::kType_Number); - - g_Camera.OnRotateBegin(args->args[0].GetNumber(), args->args[1].GetNumber()); -}; - -void SKSEScaleform_DoRotateMesh::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 2); - ASSERT(args->args[0].GetType() == GFxValue::kType_Number); - ASSERT(args->args[1].GetType() == GFxValue::kType_Number); - - g_Camera.OnRotate(args->args[0].GetNumber(), args->args[1].GetNumber()); -}; - -void SKSEScaleform_EndRotateMesh::Invoke(Args * args) -{ - g_Camera.OnRotateEnd(); -}; - -void SKSEScaleform_BeginPanMesh::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 2); - ASSERT(args->args[0].GetType() == GFxValue::kType_Number); - ASSERT(args->args[1].GetType() == GFxValue::kType_Number); - - g_Camera.OnMoveBegin(args->args[0].GetNumber(), args->args[1].GetNumber()); -}; - -void SKSEScaleform_DoPanMesh::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 2); - ASSERT(args->args[0].GetType() == GFxValue::kType_Number); - ASSERT(args->args[1].GetType() == GFxValue::kType_Number); - - g_Camera.OnMove(args->args[0].GetNumber(), args->args[1].GetNumber()); -}; - -void SKSEScaleform_EndPanMesh::Invoke(Args * args) -{ - g_Camera.OnMoveEnd(); -}; - -void SKSEScaleform_BeginPaintMesh::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 2); - ASSERT(args->args[0].GetType() == GFxValue::kType_Number); - ASSERT(args->args[1].GetType() == GFxValue::kType_Number); - - SInt32 x = args->args[0].GetNumber(); - SInt32 y = args->args[1].GetNumber(); - - bool hitMesh = false; - CDXBrush * brush = g_World.GetCurrentBrush(); - if (brush) { - CDXBrushPickerBegin brushStroke(brush); - brushStroke.SetMirror(brush->IsMirror()); - if (g_World.Pick(x, y, brushStroke)) - hitMesh = true; - } - - args->result->SetBool(hitMesh); -}; - -void SKSEScaleform_DoPaintMesh::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 2); - ASSERT(args->args[0].GetType() == GFxValue::kType_Number); - ASSERT(args->args[1].GetType() == GFxValue::kType_Number); - - SInt32 x = args->args[0].GetNumber(); - SInt32 y = args->args[1].GetNumber(); - - CDXBrush * brush = g_World.GetCurrentBrush(); - if (brush) { - CDXBrushPickerUpdate brushStroke(brush); - brushStroke.SetMirror(brush->IsMirror()); - g_World.Pick(x, y, brushStroke); - } -}; - -void SKSEScaleform_EndPaintMesh::Invoke(Args * args) -{ - CDXBrush * brush = g_World.GetCurrentBrush(); - if(brush) - brush->EndStroke(); -}; - - -void SKSEScaleform_GetCurrentBrush::Invoke(Args * args) -{ - CDXBrush * brush = g_World.GetCurrentBrush(); - if (brush) - args->result->SetNumber(brush->GetType()); - else - args->result->SetNull(); -} - -void SKSEScaleform_SetCurrentBrush::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 1); - ASSERT(args->args[0].GetType() == GFxValue::kType_Number); - - CDXBrush::BrushType brushType = (CDXBrush::BrushType)(UInt32)args->args[0].GetNumber(); - CDXBrush * brush = g_World.GetBrush(brushType); - if (brush) - g_World.SetCurrentBrush(brushType); - - args->result->SetBool(brush != NULL); -} - -void SKSEScaleform_GetBrushes::Invoke(Args * args) -{ - args->movie->CreateArray(args->result); - for (auto brush : g_World.GetBrushes()) { - GFxValue object; - args->movie->CreateObject(&object); - RegisterNumber(&object, "type", brush->GetType()); - RegisterNumber(&object, "radius", brush->GetProperty(CDXBrush::kBrushProperty_Radius, CDXBrush::kBrushPropertyValue_Value)); - RegisterNumber(&object, "radiusMin", brush->GetProperty(CDXBrush::kBrushProperty_Radius, CDXBrush::kBrushPropertyValue_Min)); - RegisterNumber(&object, "radiusMax", brush->GetProperty(CDXBrush::kBrushProperty_Radius, CDXBrush::kBrushPropertyValue_Max)); - RegisterNumber(&object, "radiusInterval", brush->GetProperty(CDXBrush::kBrushProperty_Radius, CDXBrush::kBrushPropertyValue_Interval)); - RegisterNumber(&object, "strength", brush->GetProperty(CDXBrush::kBrushProperty_Strength, CDXBrush::kBrushPropertyValue_Value)); - RegisterNumber(&object, "strengthMin", brush->GetProperty(CDXBrush::kBrushProperty_Strength, CDXBrush::kBrushPropertyValue_Min)); - RegisterNumber(&object, "strengthMax", brush->GetProperty(CDXBrush::kBrushProperty_Strength, CDXBrush::kBrushPropertyValue_Max)); - RegisterNumber(&object, "strengthInterval", brush->GetProperty(CDXBrush::kBrushProperty_Strength, CDXBrush::kBrushPropertyValue_Interval)); - RegisterNumber(&object, "falloff", brush->GetProperty(CDXBrush::kBrushProperty_Falloff, CDXBrush::kBrushPropertyValue_Value)); - RegisterNumber(&object, "falloffMin", brush->GetProperty(CDXBrush::kBrushProperty_Falloff, CDXBrush::kBrushPropertyValue_Min)); - RegisterNumber(&object, "falloffMax", brush->GetProperty(CDXBrush::kBrushProperty_Falloff, CDXBrush::kBrushPropertyValue_Max)); - RegisterNumber(&object, "falloffInterval", brush->GetProperty(CDXBrush::kBrushProperty_Falloff, CDXBrush::kBrushPropertyValue_Interval)); - RegisterNumber(&object, "mirror", brush->IsMirror() ? 1.0 : 0.0); - args->result->PushBack(&object); - } -} - -void SKSEScaleform_SetBrushData::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 2); - ASSERT(args->args[0].GetType() == GFxValue::kType_Number); - ASSERT(args->args[1].GetType() == GFxValue::kType_Object); - - CDXBrush::BrushType brushType = (CDXBrush::BrushType)(UInt32)args->args[0].GetNumber(); - CDXBrush * brush = g_World.GetBrush(brushType); - if (brush) { - GFxValue radius; - args->args[1].GetMember("radius", &radius); - GFxValue strength; - args->args[1].GetMember("strength", &strength); - GFxValue falloff; - args->args[1].GetMember("falloff", &falloff); - GFxValue mirror; - args->args[1].GetMember("mirror", &mirror); - - brush->SetProperty(CDXBrush::kBrushProperty_Radius, CDXBrush::kBrushPropertyValue_Value, radius.GetNumber()); - brush->SetProperty(CDXBrush::kBrushProperty_Strength, CDXBrush::kBrushPropertyValue_Value, strength.GetNumber()); - brush->SetProperty(CDXBrush::kBrushProperty_Falloff, CDXBrush::kBrushPropertyValue_Value, falloff.GetNumber()); - brush->SetMirror(mirror.GetNumber() > 0.0 ? true : false); - - args->result->SetBool(true); - } - else { - args->result->SetBool(false); - } -} - -void SKSEScaleform_GetMeshes::Invoke(Args * args) -{ - args->movie->CreateArray(args->result); - for (UInt32 i = 0; i < g_World.GetNumMeshes(); i++) { - CDXNifMesh * mesh = static_cast(g_World.GetNthMesh(i)); - if (mesh) { - NiGeometry * geometry = mesh->GetNifGeometry(); - if (geometry) { - GFxValue object; - args->movie->CreateObject(&object); - RegisterString(&object, args->movie, "name", geometry->m_name); - RegisterNumber(&object, "meshIndex", i); - RegisterBool(&object, "wireframe", mesh->ShowWireframe()); - RegisterBool(&object, "locked", mesh->IsLocked()); - RegisterBool(&object, "visible", mesh->IsVisible()); - RegisterBool(&object, "morphable", mesh->IsMorphable()); - RegisterNumber(&object, "vertices", mesh->GetVertexCount()); - - CDXMaterial * material = mesh->GetMaterial(); - if (material) { - CDXVec3 fColor = material->GetWireframeColor(); - UInt32 color = 0xFF000000 | (UInt32)(fColor.x * 255) << 16 | (UInt32)(fColor.y * 255) << 8 | (UInt32)(fColor.z * 255); - RegisterNumber(&object, "wfColor", color); - } - - args->result->PushBack(&object); - } - } - } -} - -void SKSEScaleform_SetMeshData::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 2); - ASSERT(args->args[0].GetType() == GFxValue::kType_Number); - ASSERT(args->args[1].GetType() == GFxValue::kType_Object); - - UInt32 i = (UInt32)args->args[0].GetNumber(); - CDXNifMesh * mesh = static_cast(g_World.GetNthMesh(i)); - if (mesh) { - GFxValue wireframe; - args->args[1].GetMember("wireframe", &wireframe); - GFxValue locked; - args->args[1].GetMember("locked", &locked); - GFxValue visible; - args->args[1].GetMember("visible", &visible); - GFxValue wfColor; - args->args[1].GetMember("wfColor", &wfColor); - - mesh->SetLocked(locked.GetBool()); - mesh->SetShowWireframe(wireframe.GetBool()); - mesh->SetVisible(visible.GetBool()); - CDXMaterial * material = mesh->GetMaterial(); - if (material) { - UInt32 color = wfColor.GetNumber(); - material->SetWireframeColor(CDXVec3(((color >> 16) & 0xFF) / 255.0, ((color >> 8) & 0xFF) / 255.0, (color & 0xFF) / 255.0)); - } - - args->result->SetBool(true); - } - else { - args->result->SetBool(false); - } -} - -void SKSEScaleform_GetActionLimit::Invoke(Args * args) -{ - args->result->SetNumber(g_undoStack.GetLimit()); -} - -void SKSEScaleform_UndoAction::Invoke(Args * args) -{ - args->result->SetNumber(g_undoStack.Undo(true)); -} - -void SKSEScaleform_RedoAction::Invoke(Args * args) -{ - args->result->SetNumber(g_undoStack.Redo(true)); -} - -void SKSEScaleform_GoToAction::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 1); - ASSERT(args->args[0].GetType() == GFxValue::kType_Number); - - SInt32 previous = g_undoStack.GetIndex(); - SInt32 result = g_undoStack.GoTo(args->args[0].GetNumber(), true); - - if (result != previous) { - Actor * actor = g_World.GetWorkingActor(); - if (actor) { - NiNode * rootFaceGen = actor->GetFaceGenNiNode(); - UpdateModelFace(rootFaceGen); - } - } - - args->result->SetNumber(result); -} - -void SKSEScaleform_GetMeshCameraRadius::Invoke(Args * args) -{ - args->result->SetNumber(g_Camera.GetRadius()); -} - -void SKSEScaleform_SetMeshCameraRadius::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 1); - ASSERT(args->args[0].GetType() == GFxValue::kType_Number); - - g_Camera.SetRadius(args->args[0].GetNumber()); - g_Camera.Update(); -} - -#include - -void ReadFileDirectory(const char * lpFolder, const char ** lpFilePattern, UInt32 numPatterns, std::function file) -{ - char szFullPattern[MAX_PATH]; - WIN32_FIND_DATA FindFileData; - HANDLE hFindFile; - // first we are going to process any subdirectories - PathCombine(szFullPattern, lpFolder, "*"); - hFindFile = FindFirstFile(szFullPattern, &FindFileData); - if (hFindFile != INVALID_HANDLE_VALUE) - { - do - { - if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - // found a subdirectory; recurse into it - PathCombine(szFullPattern, lpFolder, FindFileData.cFileName); - if (FindFileData.cFileName[0] == '.') - continue; - - file(szFullPattern, FindFileData, true); - } - } while (FindNextFile(hFindFile, &FindFileData)); - FindClose(hFindFile); - } - // now we are going to look for the matching files - for (UInt32 i = 0; i < numPatterns; i++) - { - PathCombine(szFullPattern, lpFolder, lpFilePattern[i]); - hFindFile = FindFirstFile(szFullPattern, &FindFileData); - if (hFindFile != INVALID_HANDLE_VALUE) - { - do - { - if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) - { - // found a file; do something with it - PathCombine(szFullPattern, lpFolder, FindFileData.cFileName); - file(szFullPattern, FindFileData, false); - } - } while (FindNextFile(hFindFile, &FindFileData)); - FindClose(hFindFile); - } - } -} - -void SKSEScaleform_GetExternalFiles::Invoke(Args * args) -{ - ASSERT(args->numArgs >= 1); - ASSERT(args->args[0].GetType() == GFxValue::kType_String); - ASSERT(args->args[1].GetType() == GFxValue::kType_Array); - - const char * path = args->args[0].GetString(); - - UInt32 numPatterns = args->args[1].GetArraySize(); - - const char ** patterns = (const char **)ScaleformHeap_Allocate(numPatterns * sizeof(const char*)); - for (UInt32 i = 0; i < numPatterns; i++) { - GFxValue str; - args->args[1].GetElement(i, &str); - patterns[i] = str.GetString(); - } - - args->movie->CreateArray(args->result); - - ReadFileDirectory(path, patterns, numPatterns, [args](char* dirPath, WIN32_FIND_DATA & fileData, bool dir) - { - GFxValue fileInfo; - args->movie->CreateObject(&fileInfo); - RegisterString(&fileInfo, args->movie, "path", dirPath); - RegisterString(&fileInfo, args->movie, "name", fileData.cFileName); - UInt64 fileSize = (UInt64)fileData.nFileSizeHigh << 32 | fileData.nFileSizeLow; - RegisterNumber(&fileInfo, "size", fileSize); - SYSTEMTIME sysTime; - FileTimeToSystemTime(&fileData.ftLastWriteTime, &sysTime); - GFxValue date; - GFxValue params[7]; - params[0].SetNumber(sysTime.wYear); - params[1].SetNumber(sysTime.wMonth - 1); // Flash Month is 0-11, System time is 1-12 - params[2].SetNumber(sysTime.wDay); - params[3].SetNumber(sysTime.wHour); - params[4].SetNumber(sysTime.wMinute); - params[5].SetNumber(sysTime.wSecond); - params[6].SetNumber(sysTime.wMilliseconds); - args->movie->CreateObject(&date, "Date", params, 7); - fileInfo.SetMember("lastModified", &date); - RegisterBool(&fileInfo, "directory", dir); - args->result->PushBack(&fileInfo); - }); - - ScaleformHeap_Free(patterns); -} - diff --git a/skee/ScaleformFunctions_chargen.h b/skee/ScaleformFunctions_chargen.h deleted file mode 100644 index 1343457..0000000 --- a/skee/ScaleformFunctions_chargen.h +++ /dev/null @@ -1,263 +0,0 @@ -#pragma once - -#include "skse/ScaleformCallbacks.h" -#include "skse/GameThreads.h" -#include "skse/GameTypes.h" - -class GFxValue; -class GFxMovieView; - -void RegisterNumber(GFxValue * dst, const char * name, double value); -void RegisterString(GFxValue * dst, GFxMovieView * view, const char * name, const char * str); - -class SKSEScaleform_GetHeadParts : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_GetModName : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_GetSliderData : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_ReloadSliders : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_LoadPreset : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_SavePreset : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_ReadPreset : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_ImportHead : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_LoadImportedHead : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_ClearSculptData : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_ReleaseImportedHead : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_ExportHead : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_GetPlayerPosition : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_GetPlayerRotation : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_SetPlayerRotation : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_GetRaceSexCameraRot : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_GetRaceSexCameraPos : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_SetRaceSexCameraPos : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_CreateMorphEditor : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_ReleaseMorphEditor : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_BeginRotateMesh : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_DoRotateMesh : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_EndRotateMesh : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_BeginPanMesh : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_DoPanMesh : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_EndPanMesh : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_BeginPaintMesh : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_DoPaintMesh : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_EndPaintMesh : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_GetCurrentBrush : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_SetCurrentBrush : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_GetBrushes : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_SetBrushData : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_GetMeshes : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_SetMeshData : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_GetActionLimit : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_UndoAction : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_RedoAction : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_GoToAction : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_GetMeshCameraRadius : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_SetMeshCameraRadius : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; - -class SKSEScaleform_GetExternalFiles : public GFxFunctionHandler -{ -public: - virtual void Invoke(Args * args); -}; diff --git a/skee/ScaleformLoader.cpp b/skee/ScaleformLoader.cpp deleted file mode 100644 index 513a7dc..0000000 --- a/skee/ScaleformLoader.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "ScaleformLoader.h" - -#include "skse64_common/Relocation.h" - -GFxLoader * GFxLoader::GetSingleton() -{ - // 4E9F39D1066653EF254B38406212E476F80A6C9B+AE - RelocPtr g_GFxLoader(0x02EC72B0); - return *g_GFxLoader; -} diff --git a/skee/ScaleformLoader.h b/skee/ScaleformLoader.h deleted file mode 100644 index 6f0f526..0000000 --- a/skee/ScaleformLoader.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include "skse64/ScaleformState.h" - -class NiTexture; -class IMenu; -class GImageInfoBase; - -extern bool g_logScaleform; - -class GFxImageLoader : public GFxState -{ -public: - virtual GImageInfoBase* LoadImage(const char * url) = 0; -}; - -class BSScaleformImageLoader : public GFxImageLoader -{ -public: - virtual ~BSScaleformImageLoader(); - virtual GImageInfoBase* LoadImage(const char * url); - - MEMBER_FN_PREFIX(BSScaleformImageLoader); - DEFINE_MEMBER_FN(AddVirtualImage, UInt8, 0, NiTexture ** texture); - DEFINE_MEMBER_FN(ReleaseVirtualImage, UInt8, 0, NiTexture ** texture); -}; - -class GFxLoader -{ -public: - UInt32 unk00; // 00 - GFxStateBag * stateBag; // 04 - UInt32 unk08; // 08 - UInt32 unk0C; // 0C - BSScaleformImageLoader * imageLoader; // 10 - - static GFxLoader * GetSingleton(); - - - - MEMBER_FN_PREFIX(GFxLoader); - DEFINE_MEMBER_FN(ctor, GFxLoader *, 0x00EA7830); - - // Note: Probably in subclass - DEFINE_MEMBER_FN(LoadMovie, bool, 0x00EA7EF0, IMenu* menu, GFxMovieView** viewOut, const char* name, int arg4, float arg5); -}; diff --git a/skee/StringTable.cpp b/skee/StringTable.cpp index 9c84f96..5116dca 100644 --- a/skee/StringTable.cpp +++ b/skee/StringTable.cpp @@ -15,7 +15,6 @@ void DeleteStringEntry(const SKEEFixedString* string) StringTableItem StringTable::GetString(const SKEEFixedString & str) { IScopedCriticalSection locker(&m_lock); - auto it = m_table.find(str); if (it != m_table.end()) { return it->second.lock(); @@ -33,14 +32,15 @@ StringTableItem StringTable::GetString(const SKEEFixedString & str) void StringTable::RemoveString(const SKEEFixedString & str) { IScopedCriticalSection locker(&m_lock); - auto it = m_table.find(str); if (it != m_table.end()) { - for (long int i = m_tableVector.size() - 1; i >= 0; --i) + for (auto i = m_tableVector.begin(); i != m_tableVector.end(); ++i) { - if (m_tableVector[i].lock() == it->second.lock()) - m_tableVector.erase(m_tableVector.begin() + i); + if (i->lock() == it->second.lock()) { + i = m_tableVector.erase(i); + break; + } } m_table.erase(it); @@ -49,9 +49,11 @@ void StringTable::RemoveString(const SKEEFixedString & str) UInt32 StringTable::GetStringID(const StringTableItem & str) { - for (long int i = m_tableVector.size() - 1; i >= 0; --i) + IScopedCriticalSection locker(&m_lock); + UInt32 i = 0; + for (auto it = m_tableVector.begin(); it != m_tableVector.end(); ++it, ++i) { - auto item = m_tableVector[i].lock(); + auto item = it->lock(); if (item == str) return i; } @@ -63,6 +65,7 @@ void StringTable::Save(const SKSESerializationInterface * intfc, UInt32 kVersion { intfc->OpenRecord('STTB', kVersion); + IScopedCriticalSection locker(&m_lock); UInt32 totalStrings = m_tableVector.size(); WriteData(intfc, &totalStrings); @@ -106,7 +109,7 @@ bool StringTable::Load(const SKSESerializationInterface * intfc, UInt32 kVersion stringTable.emplace(i, item); } } - else if (kVersion >= kSerializationVersion2) + else if (kVersion >= kSerializationVersion1) { if (!intfc->ReadRecordData(&totalStrings, sizeof(totalStrings))) { diff --git a/skee/TintMaskInterface.cpp b/skee/TintMaskInterface.cpp index 371e9f8..cf28dd8 100644 --- a/skee/TintMaskInterface.cpp +++ b/skee/TintMaskInterface.cpp @@ -206,7 +206,7 @@ void TintMaskInterface::ApplyMasks(TESObjectREFR * refr, bool isFirstPerson, TES height = mask.resolutionWData; newTarget = CreateSourceTexture("TintMask"); - newTarget->rendererData = CALL_MEMBER_FN(g_renderManager, CreateRenderTexture)(width, height); + newTarget->rendererData = g_renderManager->CreateRenderTexture(width, height); if (newTarget && m_maskMap.IsCaching()) { m_maskMap.AddRenderTargetGroup(lightingShader, newTarget); @@ -420,7 +420,7 @@ void TintMaskInterface::ParseTintData(LPCTSTR filePath) BSResourceNiBinaryStream bStream(path.c_str()); std::string data; - BSReadAll(&bStream, &data); + BSFileUtil::ReadAll(&bStream, data); tinyxml2::XMLDocument tintDoc; tintDoc.Parse(data.c_str(), data.size()); diff --git a/skee/Utilities.h b/skee/Utilities.h new file mode 100644 index 0000000..6cb7200 --- /dev/null +++ b/skee/Utilities.h @@ -0,0 +1,17 @@ +#pragma once + +class ScopedCriticalSection +{ +public: + ScopedCriticalSection(LPCRITICAL_SECTION cs) : m_cs(cs) + { + EnterCriticalSection(m_cs); + }; + ~ScopedCriticalSection() + { + LeaveCriticalSection(m_cs); + } + +private: + LPCRITICAL_SECTION m_cs; +}; \ No newline at end of file diff --git a/skee/main.cpp b/skee/main.cpp index 2af1263..f9fe3ad 100644 --- a/skee/main.cpp +++ b/skee/main.cpp @@ -53,7 +53,6 @@ SKSEScaleformInterface * g_scaleform = nullptr; SKSETaskInterface * g_task = nullptr; SKSEMessagingInterface * g_messaging = nullptr; SKSEPapyrusInterface * g_papyrus = nullptr; -SKEETaskInterface g_taskOverride; // Handlers IInterfaceMap g_interfaceMap; @@ -105,27 +104,38 @@ bool g_deferredBodyMorph = false; UInt16 g_scaleMode = 0; UInt16 g_bodyMorphMode = 0; -// Chargen Start -#include "CDXBrush.h" - bool g_externalHeads = false; bool g_extendedMorphs = true; bool g_allowAllMorphs = true; bool g_disableFaceGenCache = true; float g_sliderMultiplier = 1.0f; float g_sliderInterval = 0.01f; -float g_panSpeed = 0.01f; -float g_cameraFOV = 45.0f; UInt32 g_numPresets = 10; UInt32 g_customDataMax = 10; std::string g_raceTemplate = "NordRace"; -#ifdef FIXME +// Compact DirectX vars +#include "CDXCamera.h" +#include "CDXNifScene.h" +#include "CDXBrush.h" + +CDXD3DDevice* g_Device = nullptr; +CDXModelViewerCamera g_Camera; +CDXNifScene g_World; + +float g_panSpeed = 0.01f; +float g_cameraFOV = 45.0f; +SInt32 g_viewWidth = 1024; +SInt32 g_viewHeight = 1024; +float g_backgroundA = 0.0f; +float g_backgroundR = 0.0f; +float g_backgroundG = 0.0f; +float g_backgroundB = 0.0f; + extern double g_brushProperties[CDXBrush::kBrushTypes][CDXBrush::kBrushProperties][CDXBrush::kBrushPropertyValues]; -#endif #define MIN_SERIALIZATION_VERSION 1 -#define MIN_TASK_VERSION 1 +#define MIN_TASK_VERSION 2 #define MIN_SCALEFORM_VERSION 1 #define MIN_PAPYRUS_VERSION 1 @@ -226,6 +236,7 @@ const char * SKEE64GetTypeFormatting(T * dataOut) return false; } +template<> const char * SKEE64GetTypeFormatting(double * dataOut) { return "%lf"; } template<> const char * SKEE64GetTypeFormatting(float * dataOut) { return "%f"; } template<> const char * SKEE64GetTypeFormatting(bool * dataOut) { return "%c"; } template<> const char * SKEE64GetTypeFormatting(SInt16 * dataOut) { return "%hd"; } @@ -467,6 +478,8 @@ bool RegisterCharGenScaleform(GFxMovieView * view, GFxValue * root) RegisterFunction (root, view, "DoPaintMesh"); RegisterFunction (root, view, "EndPaintMesh"); + RegisterFunction (root, view, "DoHoverMesh"); + RegisterFunction (root, view, "GetCurrentBrush"); RegisterFunction (root, view, "SetCurrentBrush"); @@ -698,14 +711,6 @@ bool SKSEPlugin_Query(const SKSEInterface * skse, PluginInfo * info) return false; } - if (g_task->interfaceVersion < 3) - { - g_taskOverride.AddTask = g_task->AddTask; - g_taskOverride.AddSKSETask = g_task->AddTask; - g_taskOverride.AddUITask = g_task->AddUITask; - g_task = &g_taskOverride; - } - g_messaging = (SKSEMessagingInterface *)skse->QueryInterface(kInterface_Messaging); if (!g_messaging) { _ERROR("couldn't get messaging interface"); @@ -818,10 +823,17 @@ bool SKSEPlugin_Load(const SKSEInterface * skse) SKEE64GetConfigValue("FaceGen", "bExternalHeads", &g_externalHeads); SKEE64GetConfigValue("FaceGen", "bExtendedMorphs", &g_extendedMorphs); SKEE64GetConfigValue("FaceGen", "bAllowAllMorphs", &g_allowAllMorphs); - SKEE64GetConfigValue("FaceGen", "fPanSpeed", &g_panSpeed); - SKEE64GetConfigValue("FaceGen", "fFOV", &g_cameraFOV); -#ifdef FIXME + SKEE64GetConfigValue("Sculpting", "fPanSpeed", &g_panSpeed); + SKEE64GetConfigValue("Sculpting", "fFOV", &g_cameraFOV); + SKEE64GetConfigValue("Sculpting", "iWidth", &g_viewWidth); + SKEE64GetConfigValue("Sculpting", "iHeight", &g_viewHeight); + + SKEE64GetConfigValue("Sculpting", "fBackgroundA", &g_backgroundA); + SKEE64GetConfigValue("Sculpting", "fBackgroundR", &g_backgroundR); + SKEE64GetConfigValue("Sculpting", "fBackgroundG", &g_backgroundG); + SKEE64GetConfigValue("Sculpting", "fBackgroundB", &g_backgroundB); + std::string types[CDXBrush::kBrushTypes]; types[CDXBrush::kBrushType_Mask_Add] = "Brush/MaskAdd/"; types[CDXBrush::kBrushType_Mask_Subtract] = "Brush/MaskSubtract/"; @@ -853,7 +865,6 @@ bool SKSEPlugin_Load(const SKSEInterface * skse) } } } -#endif if (g_serialization) { g_serialization->SetUniqueID(g_pluginHandle, 'SKEE'); diff --git a/skee/main_chargen.cpp b/skee/main_chargen.cpp deleted file mode 100644 index 8f1e5ec..0000000 --- a/skee/main_chargen.cpp +++ /dev/null @@ -1,514 +0,0 @@ -#include "skse/PluginAPI.h" -#include "skse/skse_version.h" -#include "skse/SafeWrite.h" - -#include "skse/GameRTTI.h" - -#include "skse/ScaleformMovie.h" -#include "skse/ScaleformLoader.h" - -#include "MorphHandler.h" -#include "PartHandler.h" -#include "Hooks.h" -#include "ScaleformFunctions.h" -#include "PapyrusCharGen.h" - -#include "interfaces/IPluginInterface.h" -#include "interfaces/OverrideInterface.h" -#include "interfaces/NiTransformInterface.h" -#include "interfaces/OverlayInterface.h" -#include "interfaces/BodyMorphInterface.h" - -#include "CDXBrush.h" - -#include -#include - -#define MIN_TASK_VERSION 1 -#define MIN_PAP_VERSION 1 -#define MIN_SCALEFORM_VERSION 1 -#define MIN_SERIALIZATION_VERSION 2 -#define PLUGIN_VERSION 6 - -IDebugLog gLog; -PluginHandle g_pluginHandle = kPluginHandle_Invalid; -const UInt32 kSerializationDataVersion = 2; - -// Interfaces -SKSESerializationInterface * g_serialization = NULL; -SKSEScaleformInterface * g_scaleform = NULL; -SKSETaskInterface * g_task = NULL; -SKSEPapyrusInterface * g_papyrus = NULL; -SKSEMessagingInterface * g_messaging = NULL; - -OverrideInterface * g_overrideInterface = NULL; -NiTransformInterface * g_transformInterface = NULL; -OverlayInterface * g_overlayInterface = NULL; -BodyMorphInterface * g_bodyMorphInterface = NULL; - -MorphHandler g_morphHandler; -PartSet g_partSet; -//CustomDataMap g_customDataMap; - -bool g_externalHeads = false; -bool g_extendedMorphs = true; -bool g_allowAllMorphs = true; -bool g_disableFaceGenCache = true; -float g_sliderMultiplier = 1.0f; -float g_sliderInterval = 0.01f; -float g_panSpeed = 0.01f; -float g_cameraFOV = 45.0f; -UInt32 g_numPresets = 10; -UInt32 g_customDataMax = 10; -std::string g_raceTemplate = "NordRace"; - -extern double g_brushProperties[CDXBrush::kBrushTypes][CDXBrush::kBrushProperties][CDXBrush::kBrushPropertyValues]; - -void Serialization_Revert(SKSESerializationInterface * intfc) -{ - g_morphHandler.Revert(); -} - -void Serialization_Save(SKSESerializationInterface * intfc) -{ - _DMESSAGE("Saving..."); - - PlayerCharacter * player = (*g_thePlayer); - TESNPC * playerBase = DYNAMIC_CAST(player->baseForm, TESForm, TESNPC); - - g_morphHandler.Save(playerBase, intfc, kSerializationDataVersion); - - _DMESSAGE("Save Complete."); -} - -void Serialization_Load(SKSESerializationInterface * intfc) -{ - _DMESSAGE("Loading..."); - -#ifdef _DEBUG_DATADUMP - g_morphHandler.DumpAll(); -#endif - - PlayerCharacter * player = (*g_thePlayer); - TESNPC * playerBase = DYNAMIC_CAST(player->baseForm, TESForm, TESNPC); - - g_morphHandler.Load(playerBase, intfc, kSerializationDataVersion); - - g_task->AddTask(new SKSETaskApplyMorphs(player)); - - _DMESSAGE("Load Complete."); -} - -const std::string & GetRuntimeDirectory(void) -{ - static std::string s_runtimeDirectory; - - if(s_runtimeDirectory.empty()) - { - // can't determine how many bytes we'll need, hope it's not more than MAX_PATH - char runtimePathBuf[MAX_PATH]; - UInt32 runtimePathLength = GetModuleFileName(GetModuleHandle(NULL), runtimePathBuf, sizeof(runtimePathBuf)); - - if(runtimePathLength && (runtimePathLength < sizeof(runtimePathBuf))) - { - std::string runtimePath(runtimePathBuf, runtimePathLength); - - // truncate at last slash - std::string::size_type lastSlash = runtimePath.rfind('\\'); - if(lastSlash != std::string::npos) // if we don't find a slash something is VERY WRONG - { - s_runtimeDirectory = runtimePath.substr(0, lastSlash + 1); - - _DMESSAGE("runtime root = %s", s_runtimeDirectory.c_str()); - } - else - { - _WARNING("no slash in runtime path? (%s)", runtimePath.c_str()); - } - } - else - { - _WARNING("couldn't find runtime path (len = %d, err = %08X)", runtimePathLength, GetLastError()); - } - } - - return s_runtimeDirectory; -} - -const std::string & GetConfigPath(void) -{ - static std::string s_configPath; - - if(s_configPath.empty()) - { - std::string runtimePath = GetRuntimeDirectory(); - if(!runtimePath.empty()) - { - s_configPath = runtimePath + "Data\\SKSE\\Plugins\\chargen.ini"; - - _DMESSAGE("config path = %s", s_configPath.c_str()); - } - } - - return s_configPath; -} - -std::string GetConfigOption(const char * section, const char * key) -{ - std::string result; - - const std::string & configPath = GetConfigPath(); - if(!configPath.empty()) - { - char resultBuf[256]; - resultBuf[0] = 0; - - UInt32 resultLen = GetPrivateProfileString(section, key, NULL, resultBuf, sizeof(resultBuf), configPath.c_str()); - - result = resultBuf; - } - - return result; -} - -template -bool GetConfigNumber(const char * section, const char * key, T * dataOut) -{ - std::string data = GetConfigOption(section, key); - if (data.empty()) - return false; - - return (sscanf_s(data.c_str(), "%d", dataOut) == 1); -} - -template<> -bool GetConfigNumber(const char * section, const char * key, float * dataOut) -{ - std::string data = GetConfigOption(section, key); - if(data.empty()) - return false; - - return (sscanf_s(data.c_str(), "%f", dataOut) == 1); -} - -template<> -bool GetConfigNumber(const char * section, const char * key, double * dataOut) -{ - std::string data = GetConfigOption(section, key); - if (data.empty()) - return false; - - return (sscanf_s(data.c_str(), "%lf", dataOut) == 1); -} - -bool RegisterScaleform(GFxMovieView * view, GFxValue * root) -{ - RegisterFunction (root, view, "ImportHead"); - RegisterFunction (root, view, "ExportHead"); - RegisterFunction (root, view, "SavePreset"); - RegisterFunction (root, view, "LoadPreset"); - RegisterFunction (root, view, "ReadPreset"); - RegisterFunction (root, view, "ReloadSliders"); - RegisterFunction (root, view, "GetSliderData"); - RegisterFunction (root, view, "GetModName"); - - RegisterFunction (root, view, "GetPlayerPosition"); - RegisterFunction (root, view, "GetPlayerRotation"); - RegisterFunction (root, view, "SetPlayerRotation"); - - RegisterFunction (root, view, "GetRaceSexCameraRot"); - RegisterFunction (root, view, "GetRaceSexCameraPos"); - RegisterFunction (root, view, "SetRaceSexCameraPos"); - - RegisterFunction (root, view, "CreateMorphEditor"); - RegisterFunction (root, view, "ReleaseMorphEditor"); - - RegisterFunction (root, view, "LoadImportedHead"); - RegisterFunction (root, view, "ReleaseImportedHead"); - - RegisterFunction (root, view, "BeginRotateMesh"); - RegisterFunction (root, view, "DoRotateMesh"); - RegisterFunction (root, view, "EndRotateMesh"); - - RegisterFunction (root, view, "BeginPanMesh"); - RegisterFunction (root, view, "DoPanMesh"); - RegisterFunction (root, view, "EndPanMesh"); - - RegisterFunction (root, view, "BeginPaintMesh"); - RegisterFunction (root, view, "DoPaintMesh"); - RegisterFunction (root, view, "EndPaintMesh"); - - RegisterFunction (root, view, "GetCurrentBrush"); - RegisterFunction (root, view, "SetCurrentBrush"); - - RegisterFunction (root, view, "GetBrushes"); - RegisterFunction (root, view, "SetBrushData"); - - RegisterFunction (root, view, "GetMeshes"); - RegisterFunction (root, view, "SetMeshData"); - - RegisterFunction (root, view, "UndoAction"); - RegisterFunction (root, view, "RedoAction"); - RegisterFunction (root, view, "GoToAction"); - RegisterFunction (root, view, "GetActionLimit"); - RegisterFunction (root, view, "ClearSculptData"); - - RegisterFunction (root, view, "GetMeshCameraRadius"); - RegisterFunction (root, view, "SetMeshCameraRadius"); - - RegisterFunction (root, view, "GetExternalFiles"); - return true; -} - -void SKSEMessageHandler(SKSEMessagingInterface::Message * message) -{ - switch (message->type) - { - case SKSEMessagingInterface::kMessage_PostLoad: - { - InterfaceExchangeMessage message; - g_messaging->Dispatch(g_pluginHandle, InterfaceExchangeMessage::kMessage_ExchangeInterface, (void*)&message, sizeof(InterfaceExchangeMessage*), "nioverride"); - if (message.interfaceMap) { - g_overrideInterface = (OverrideInterface*)message.interfaceMap->QueryInterface("Override"); - g_transformInterface = (NiTransformInterface *)message.interfaceMap->QueryInterface("NiTransform"); - g_overlayInterface = (OverlayInterface *)message.interfaceMap->QueryInterface("Overlay"); - g_bodyMorphInterface = (BodyMorphInterface *)message.interfaceMap->QueryInterface("BodyMorph"); - } - } - break; - } -} - -extern "C" -{ - -bool SKSEPlugin_Query(const SKSEInterface * skse, PluginInfo * info) -{ - SInt32 logLevel = IDebugLog::kLevel_DebugMessage; - if (GetConfigNumber("Debug", "iLogLevel", &logLevel)) - gLog.SetLogLevel((IDebugLog::LogLevel)logLevel); - - if (logLevel >= 0) - gLog.OpenRelative(CSIDL_MYDOCUMENTS, "\\My Games\\Skyrim\\SKSE\\skse_chargen.log"); - - _DMESSAGE("skse_chargen"); - - // populate info structure - info->infoVersion = PluginInfo::kInfoVersion; - info->name = "chargen"; - info->version = PLUGIN_VERSION; - - // store plugin handle so we can identify ourselves later - g_pluginHandle = skse->GetPluginHandle(); - - if(skse->isEditor) - { - _FATALERROR("loaded in editor, marking as incompatible"); - return false; - } - else if(skse->runtimeVersion != RUNTIME_VERSION_1_9_32_0) - { - _FATALERROR("unsupported runtime version %08X", skse->runtimeVersion); - return false; - } - - // get the serialization interface and query its version - g_serialization = (SKSESerializationInterface *)skse->QueryInterface(kInterface_Serialization); - if(!g_serialization) - { - _FATALERROR("couldn't get serialization interface"); - return false; - } - - if(g_serialization->version < MIN_SERIALIZATION_VERSION) - { - _FATALERROR("serialization interface too old (%d expected %d)", g_serialization->version, MIN_SERIALIZATION_VERSION); - return false; - } - - // get the scaleform interface and query its version - g_scaleform = (SKSEScaleformInterface *)skse->QueryInterface(kInterface_Scaleform); - if(!g_scaleform) - { - _FATALERROR("couldn't get scaleform interface"); - return false; - } - if(g_scaleform->interfaceVersion < MIN_SCALEFORM_VERSION) - { - _FATALERROR("scaleform interface too old (%d expected %d)", g_scaleform->interfaceVersion, MIN_SCALEFORM_VERSION); - return false; - } - - // get the task interface and query its version - g_task = (SKSETaskInterface *)skse->QueryInterface(kInterface_Task); - if(!g_task) - { - _FATALERROR("couldn't get task interface"); - return false; - } - if(g_task->interfaceVersion < MIN_TASK_VERSION) - { - _FATALERROR("task interface too old (%d expected %d)", g_task->interfaceVersion, MIN_TASK_VERSION); - return false; - } - - // get the papyrus interface and query its version - g_papyrus = (SKSEPapyrusInterface *)skse->QueryInterface(kInterface_Papyrus); - if(!g_papyrus) - { - _WARNING("couldn't get papyrus interface"); - } - if(g_papyrus && g_papyrus->interfaceVersion < MIN_PAP_VERSION) - { - _WARNING("papyrus interface too old (%d expected %d)", g_papyrus->interfaceVersion, MIN_PAP_VERSION); - } - - g_messaging = (SKSEMessagingInterface *)skse->QueryInterface(kInterface_Messaging); - if (!g_messaging) { - _ERROR("couldn't get messaging interface"); - } - - // supported runtime version - return true; -} - -bool RegisterFuncs(VMClassRegistry * registry) -{ - papyrusCharGen::RegisterFuncs(registry); - return true; -} - -bool SKSEPlugin_Load(const SKSEInterface * skse) -{ - _MESSAGE("CharGen Morph Support Enabled."); - - std::string data = GetConfigOption("FaceGen", "sTemplateRace"); - if (!data.empty()) - g_raceTemplate = data; - - float sliderMultiplier = 1.0f; - if (GetConfigNumber("FaceGen", "fSliderMultiplier", &sliderMultiplier)) - { - g_sliderMultiplier = sliderMultiplier; - if(g_sliderMultiplier <= 0) - g_sliderMultiplier = 0.01f; - } - float sliderInterval = 0.01f; - if (GetConfigNumber("FaceGen", "fSliderInterval", &sliderMultiplier)) - { - g_sliderInterval = sliderInterval; - if(g_sliderInterval <= 0) - g_sliderInterval = 0.01f; - if(g_sliderInterval > 1.0) - g_sliderInterval = 1.0; - } - - UInt32 disableFaceGenCache = 1; - if (GetConfigNumber("FaceGen", "bDisableFaceGenCache", &disableFaceGenCache)) - { - g_disableFaceGenCache = (disableFaceGenCache > 0); - } - - UInt32 externalHeads = 0; - if (GetConfigNumber("FaceGen", "bExternalHeads", &externalHeads)) - { - g_externalHeads = (externalHeads > 0); - } - UInt32 extendedMorphs = 1; - if (GetConfigNumber("FaceGen", "bExtendedMorphs", &extendedMorphs)) - { - g_extendedMorphs = (extendedMorphs > 0); - } - UInt32 allowAllMorphs = 1; - if (GetConfigNumber("FaceGen", "bAllowAllMorphs", &allowAllMorphs)) - { - g_allowAllMorphs = (allowAllMorphs > 0); - } - - float panSpeed = 0.01f; - if (GetConfigNumber("FaceGen", "fPanSpeed", &panSpeed)) - { - g_panSpeed = panSpeed; - } - - float cameraFOV = 45.0f; - if (GetConfigNumber("FaceGen", "fFOV", &cameraFOV)) - { - g_cameraFOV = cameraFOV; - } - - std::string types[CDXBrush::kBrushTypes]; - types[CDXBrush::kBrushType_Mask_Add] = "Brush/MaskAdd/"; - types[CDXBrush::kBrushType_Mask_Subtract] = "Brush/MaskSubtract/"; - types[CDXBrush::kBrushType_Inflate] = "Brush/Inflate/"; - types[CDXBrush::kBrushType_Deflate] = "Brush/Deflate/"; - types[CDXBrush::kBrushType_Smooth] = "Brush/Smooth/"; - types[CDXBrush::kBrushType_Move] = "Brush/Move/"; - - std::string properties[CDXBrush::kBrushProperties]; - properties[CDXBrush::kBrushProperty_Radius] = "Radius"; - properties[CDXBrush::kBrushProperty_Strength] = "Strength"; - properties[CDXBrush::kBrushProperty_Falloff] = "Falloff"; - - std::string values[CDXBrush::kBrushPropertyValues]; - values[CDXBrush::kBrushPropertyValue_Value] = "dbDefault"; - values[CDXBrush::kBrushPropertyValue_Min] = "dbMin"; - values[CDXBrush::kBrushPropertyValue_Max] = "dbMax"; - values[CDXBrush::kBrushPropertyValue_Interval] = "dbInterval"; - - CDXBrush::InitGlobals(); - - for (UInt32 b = 0; b < CDXBrush::kBrushTypes; b++) { - for (UInt32 p = 0; p < CDXBrush::kBrushProperties; p++) { - for (UInt32 v = 0; v < CDXBrush::kBrushPropertyValues; v++) { - std::string section = types[b] + properties[p]; - double val = 0.0; - if (GetConfigNumber(section.c_str(), values[v].c_str(), &val)) - g_brushProperties[b][p][v] = val; - } - } - } - - InstallHooks(); - - if(g_disableFaceGenCache) { - SafeWrite8(0x008868C0, 0xC3); // Disable PrecacheCharGen - SafeWrite8(0x00886B50, 0xC3); // Disable PrecacheCharGenClear - } - - //SafeWrite8(DATA_ADDR(0x005A0AB0, 0xF5) + 2, 0xFF); - - // Patch Morph Limit - /*SafeWrite8(DATA_ADDR(0x005A7570, 0x33) + 1, 0xFF); - SafeWrite8(DATA_ADDR(0x005A7870, 0x9D) + 1, 0xFF); - SafeWrite8(DATA_ADDR(0x005A7870, 0xA4) + 1, 0xFF);*/ - - /*SafeWrite8(0x005A7280 + 0x0F + 1, 0xFF); - SafeWrite8(0x005A7240 + 0x10 + 1, 0xFF); - SafeWrite8(0x005A7200 + 0x10 + 1, 0xFF); - SafeWrite8(0x005A71C0 + 0x10 + 1, 0xFF);*/ - - if (g_serialization) { - g_serialization->SetUniqueID(g_pluginHandle, 'FCGN'); - g_serialization->SetRevertCallback(g_pluginHandle, Serialization_Revert); - g_serialization->SetSaveCallback(g_pluginHandle, Serialization_Save); - g_serialization->SetLoadCallback(g_pluginHandle, Serialization_Load); - } - - // register scaleform callbacks - if (g_scaleform) { - g_scaleform->Register("CharGen", RegisterScaleform); - } - - if (g_papyrus) { - g_papyrus->Register(RegisterFuncs); - } - - if (g_messaging) { - g_messaging->RegisterListener(g_pluginHandle, "SKSE", SKSEMessageHandler); - } - - return true; -} - -}; diff --git a/skee/shader.ps b/skee/shader.ps new file mode 100644 index 0000000000000000000000000000000000000000..23aaea3c36bc842032a3f6222b7efaef421e5f91 GIT binary patch literal 1329 zcmb7ETaS}K6nVg^?wK3CL`~!c z&UbF#xskD>>Lr^jpx|ZMcWg?s0je8$pyCqgTDI#2m6uq-6y;Y|iq~pQyYEv%QhI0w zlc}PLffEqk<$YN)32THUr{bd#$uAO=qM_;3&LFu4UDrsRZ0bxQU-1uy)_#IkOC zmA$qMYXW?1S7imb(>_n zep;OsJKZP5=gBJBS}G+Jxp_aw6GkUecbJ!j`506W;3Kh4{FC9A1EE6-D9DB-47F6-B0ED-8867439C43CE} skee64 Win32Proj - 8.1 + 10.0.16299.0 @@ -51,8 +51,8 @@ Disabled - $(SolutionDir);$(SolutionDir)\..;$(SolutionDir)\..\..;$(SolutionDir)\skse64;$(SolutionDir)\jsoncpp;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_EXAMPLE_EXPORTS;%(PreprocessorDefinitions) + $(SolutionDir);$(SolutionDir)..;$(SolutionDir)..\..;$(SolutionDir)skse64;$(SolutionDir)jsoncpp;$(SolutionDir)DirectXTex;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_EXAMPLE_EXPORTS;HALF_ROUND_STYLE=1;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug @@ -65,8 +65,9 @@ exports.def true Windows - shlwapi.lib;%(AdditionalDependencies) + DirectXTex.lib;shlwapi.lib;%(AdditionalDependencies) true + $(SolutionDir)DirectXTex\Bin\Desktop_2015\$(IntDir);%(AdditionalLibraryDirectories) @@ -87,8 +88,8 @@ MaxSpeed true - $(SolutionDir);$(SolutionDir)\..;$(SolutionDir)\..\..;$(SolutionDir)\skse64;$(SolutionDir)\jsoncpp;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_EXAMPLE_EXPORTS;%(PreprocessorDefinitions) + $(SolutionDir);$(SolutionDir)..;$(SolutionDir)..\..;$(SolutionDir)skse64;$(SolutionDir)jsoncpp;$(WindowsSDK_IncludePath);$(SolutionDir)DirectXTex;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_EXAMPLE_EXPORTS;HALF_ROUND_STYLE=1;HALF_ENABLE_CPP11_CMATH=0;%(PreprocessorDefinitions) MultiThreaded true @@ -103,7 +104,8 @@ Windows true true - shlwapi.lib;%(AdditionalDependencies) + DirectXTex.lib;shlwapi.lib;%(AdditionalDependencies) + $(SolutionDir)DirectXTex\Bin\Desktop_2015\$(IntDir);%(AdditionalLibraryDirectories) @@ -155,6 +157,7 @@ + @@ -162,6 +165,7 @@ + @@ -169,12 +173,14 @@ + + @@ -182,7 +188,7 @@ - + @@ -193,7 +199,6 @@ - @@ -238,6 +243,7 @@ + @@ -245,27 +251,33 @@ + + + + + + - + @@ -276,13 +288,13 @@ - + diff --git a/skee/skee64.vcxproj.filters b/skee/skee64.vcxproj.filters index e257b5a..2839997 100644 --- a/skee/skee64.vcxproj.filters +++ b/skee/skee64.vcxproj.filters @@ -77,9 +77,6 @@ utils - - handlers - handlers @@ -113,9 +110,6 @@ scaleform\functions - - api\scaleform\api - api\scaleform\api @@ -242,6 +236,21 @@ hooks + + interfaces + + + renderer + + + renderer + + + scaleform\functions + + + renderer + @@ -384,9 +393,6 @@ utils - - handlers - handlers @@ -420,9 +426,6 @@ scaleform\functions - - api\scaleform\api - api\scaleform\api @@ -549,5 +552,32 @@ hooks + + utils + + + renderer + + + interfaces + + + renderer + + + renderer + + + scaleform\functions + + + renderer + + + renderer + + + utils + \ No newline at end of file