From b1b107863715e9dc641e9aa064d493a86f89a6db Mon Sep 17 00:00:00 2001 From: furudee Date: Mon, 28 Jul 2025 22:39:16 +0300 Subject: [PATCH] wip --- .../Src/XComGame/Classes/XComHumanPawn.uc | 153 +++++++++++++----- .../Classes/XComLegsContentAdvanced.uc | 3 + .../Classes/XComTorsoContentAdvanced.uc | 4 + .../X2WOTCCommunityHighlander.x2proj | 6 + 4 files changed, 122 insertions(+), 44 deletions(-) create mode 100644 X2WOTCCommunityHighlander/Src/XComGame/Classes/XComLegsContentAdvanced.uc create mode 100644 X2WOTCCommunityHighlander/Src/XComGame/Classes/XComTorsoContentAdvanced.uc diff --git a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XComHumanPawn.uc b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XComHumanPawn.uc index 8e763df42..d0fff972c 100644 --- a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XComHumanPawn.uc +++ b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XComHumanPawn.uc @@ -113,6 +113,9 @@ var transient bool CustomizationRotationSet; // Issue #219: This class isn't native, but cooked. Adding a transient member is totally OK though. var private transient bool InitedHeadState; +var private transient SkeletalMesh DefaultSkeleton; +var private transient PhysicsAsset DefaultPhysics; + Delegate OnBodyPartLoadedDelegate(PawnContentRequest ContentRequest); simulated event PostBeginPlay () @@ -138,6 +141,9 @@ simulated event PostBeginPlay () } // End Issue #219 + DefaultSkeleton = Mesh.SkeletalMesh; + DefaultPhysics = Mesh.PhysicsAsset; + super.PostBeginPlay(); if (Voice != none && Voice.CurrentVoiceBank == none) @@ -1360,50 +1366,11 @@ simulated function OnHeadLoaded(PawnContentRequest ContentRequest) * already assigns something to m_kHeadMeshComponent. Thus we need InitedHeadState to properly * initialize our state. Ideally we somehow stored that info in the m_kHeadMeshComponent, but I didn't find a way */ - if (m_kHeadMeshComponent == none || !InitedHeadState) - { - // We initialize with the same head as our pawn mesh - m_kHeadMeshComponent = Mesh; - InitedHeadState = true; - } - // We have a valid head component (that *may* point to the pawn mesh component, or not) and need a different mesh - if (m_kHeadMeshComponent.SkeletalMesh != HeadContent.SkeletalMesh) - { - if (m_kHeadMeshComponent == Mesh) - { - // We have the pawn head, but need a custom head -- create it and hide the base - CreateCustomHead(HeadContent.SkeletalMesh); - HideBaseHead(); - } - else - { - // We already have a dedicated head component, but we want a different mesh. Check if we need to - // switch back to the pawn or change the head mesh - if (Mesh.SkeletalMesh != HeadContent.SkeletalMesh) - { - // Update mesh - m_kHeadMeshComponent.SetSkeletalMesh(HeadContent.SkeletalMesh); - Mesh.AppendSockets(m_kHeadMeshComponent.Sockets, true); - // Start Issue #21 - // Call function allowing DLC/Mods to append sockets to units - DLCAppendSockets(); - // End Issue #21 - m_kHeadMeshComponent.SetHidden(false); - } - else - { - // Switch back to the base pawn - m_kHeadMeshComponent.SetHidden(true); - DetachComponent(m_kHeadMeshComponent); - m_kHeadMeshComponent = Mesh; - // Start Issue #21 - // Call function allowing DLC/Mods to append sockets to units - DLCAppendSockets(); - // End Issue #21 - } - } - } + // always create a new head + CreateCustomHead(HeadContent.SkeletalMesh); + HideBaseHead(); + // End Issue #219 ResetMaterials(m_kHeadMeshComponent); @@ -1444,6 +1411,11 @@ simulated function OnHeadLoaded(PawnContentRequest ContentRequest) // Start Issue #219 simulated function CreateCustomHead(SkeletalMesh HeadMesh) { + if(m_kHeadMeshComponent != None && m_kHeadMeshComponent != Mesh) + { + DetachComponent(m_kHeadMeshComponent); + } + m_kHeadMeshComponent = new (self) class'SkeletalMeshComponent'; m_kHeadMeshComponent.SetHasPhysicsAssetInstance(false, true); m_kHeadMeshComponent.SetOwnerNoSee(false); @@ -1453,6 +1425,15 @@ simulated function CreateCustomHead(SkeletalMesh HeadMesh) m_kHeadMeshComponent.SetSkeletalMesh(HeadMesh); m_kHeadMeshComponent.SetParentAnimComponent(Mesh); + + // add face morphs from pawn mesh to the head + if(Mesh.MorphSets.Length > 0) + { + m_kHeadMeshComponent.MorphSets = Mesh.MorphSets; + m_kHeadMeshComponent.bUpdateMorphWhenParentAnimComponentExists = true; + m_kHeadMeshComponent.InitMorphTargets(); + } + AttachComponent(m_kHeadMeshComponent); Mesh.AppendSockets(m_kHeadMeshComponent.Sockets, true); // Start Issue #21 @@ -2261,6 +2242,14 @@ function UpdateMorphs(SkeletalMeshComponent CheckMeshComponent, MorphTargetSet U simulated function OnTorsoLoaded(PawnContentRequest ContentRequest) { local int AttachmentIndex; + local XComTorsoContentAdvanced AdvancedContent; + local SkeletalMeshComponent MeshComp; + local bool bSkeletonChanged; + + if(TorsoContent == XComTorsoContent(ContentRequest.kContent)) + { + return; + } if( TorsoContent != None ) { @@ -2271,14 +2260,90 @@ simulated function OnTorsoLoaded(PawnContentRequest ContentRequest) } TorsoContent = XComTorsoContent(ContentRequest.kContent); + AdvancedContent = XComTorsoContentAdvanced(ContentRequest.kContent); + + if(AdvancedContent != None) + { + if(AdvancedContent.SkeletonOverride != None && AdvancedContent.SkeletonPhysicsAsset != None) + { + Mesh.SetSkeletalMesh(AdvancedContent.SkeletonOverride, false); + Mesh.SetPhysicsAsset(AdvancedContent.SkeletonPhysicsAsset, true); + Mesh.SetHasPhysicsAssetInstance(true, false); + + Mesh.bEnableFullAnimWeightBodies = true; + Mesh.bUpdateKinematicBonesFromAnimation = true; + Mesh.PhysicsWeight = 1.0f; + + Mesh.UpdateAnimations(); + Mesh.ForceSkelUpdate(); + + Mesh.PhysicsAssetInstance.SetFullAnimWeightBonesFixed(false, Mesh); + + m_bHasFullAnimWeightBones = true; + bSkeletonChanged = true; + } + } + else + { + if(Mesh.SkeletalMesh != DefaultSkeleton) + { + Mesh.SetSkeletalMesh(DefaultSkeleton, false); + Mesh.SetPhysicsAsset(DefaultPhysics, true); + Mesh.SetHasPhysicsAssetInstance(true, false); + + Mesh.UpdateAnimations(); + Mesh.ForceSkelUpdate(); + + Mesh.PhysicsAssetInstance.SetAllBodiesFixed(true); + + m_bHasFullAnimWeightBones = false; + bSkeletonChanged = true; + } + } + + DetachComponent(m_kTorsoComponent); + + m_kTorsoComponent = new(self) class'SkeletalMeshComponent'; + m_kTorsoComponent.SetActorCollision(true, false, false); + m_kTorsoComponent.SetTraceBlocking(true, false); + m_kTorsoComponent.SetAcceptsDynamicDecals(true); + + AttachComponent(m_kTorsoComponent); + m_kTorsoComponent.SetSkeletalMesh(TorsoContent.SkeletalMesh); + + if(AdvancedContent != None) + { + m_kTorsoComponent.bEnableFullAnimWeightBodies = true; + m_kTorsoComponent.bUpdateKinematicBonesFromAnimation = true; + m_kTorsoComponent.PhysicsWeight = 1.0f; + } + else + { + m_kTorsoComponent.bEnableFullAnimWeightBodies = false; + m_kTorsoComponent.bUpdateKinematicBonesFromAnimation = false; + m_kTorsoComponent.PhysicsWeight = 0.0f; + } + + // update all components of the skeleton change to ensure proper bone mapping for animations + if(bSkeletonChanged) + { + foreach AllOwnedComponents(class'SkeletalMeshComponent', MeshComp) + { + MeshComp.UpdateParentBoneMap(); + MeshComp.UpdateAnimations(); + MeshComp.ForceSkelUpdate(); + } + } + ResetMaterials(m_kTorsoComponent); if(TorsoContent.OverrideMaterial != none) { m_kTorsoComponent.SetMaterial(0, TorsoContent.OverrideMaterial); } + m_kTorsoComponent.SetParentAnimComponent(Mesh); - + Mesh.AppendSockets(m_kTorsoComponent.Sockets, true); // Start Issue #21 // Call function allowing DLC/Mods to append sockets to units diff --git a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XComLegsContentAdvanced.uc b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XComLegsContentAdvanced.uc new file mode 100644 index 000000000..ea4cd6c06 --- /dev/null +++ b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XComLegsContentAdvanced.uc @@ -0,0 +1,3 @@ +class XComLegsContentAdvanced extends XComLegsContent; + +var() SkeletalMesh RequiredSkeleton; diff --git a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XComTorsoContentAdvanced.uc b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XComTorsoContentAdvanced.uc new file mode 100644 index 000000000..6416feb67 --- /dev/null +++ b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XComTorsoContentAdvanced.uc @@ -0,0 +1,4 @@ +class XComTorsoContentAdvanced extends XComTorsoContent; + +var() SkeletalMesh SkeletonOverride; +var() PhysicsAsset SkeletonPhysicsAsset; \ No newline at end of file diff --git a/X2WOTCCommunityHighlander/X2WOTCCommunityHighlander.x2proj b/X2WOTCCommunityHighlander/X2WOTCCommunityHighlander.x2proj index 8e2ba78ad..cf3e541c1 100644 --- a/X2WOTCCommunityHighlander/X2WOTCCommunityHighlander.x2proj +++ b/X2WOTCCommunityHighlander/X2WOTCCommunityHighlander.x2proj @@ -931,6 +931,9 @@ Content + + Content + Content @@ -967,6 +970,9 @@ Content + + Content + Content