rimworld-animations-patch_m.../Source/Scripts/Utilities/HandAnimationUtility.cs

100 lines
4.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Verse;
using RimWorld;
using HarmonyLib;
using Rimworld_Animations;
namespace Rimworld_Animations_Patch
{
public static class HandAnimationUtility
{
public static BodyPartDef handDef;
public static bool BodyPartIsBeingTouched(Pawn pawn, ActorAnimationData actorAnimationData, string bodypartFilePath, out List<HandAnimationData> handAnimationData)
{
handAnimationData = new List<HandAnimationData>();
HandAnimationDef handAnimationDef = pawn?.TryGetComp<CompPawnSexData>()?.handAnimationDef;
if (handAnimationDef == null || actorAnimationData == null || bodypartFilePath.NullOrEmpty())
{ return false; }
foreach (HandAnimationData datum in handAnimationDef.handAnimationData)
{
if (datum.stageID != actorAnimationData.currentStage || datum.actorID != actorAnimationData.actorID) continue;
if (datum.bodySide.NullOrEmpty() == false && bodypartFilePath.Contains(datum.bodySide, StringComparison.OrdinalIgnoreCase) == false) continue;
if ((datum.targetBodyPart.NullOrEmpty() == false && bodypartFilePath.Contains(datum.targetBodyPart, StringComparison.OrdinalIgnoreCase)) ||
datum.targetBodyParts.Any(x => bodypartFilePath.Contains(x, StringComparison.OrdinalIgnoreCase)))
{ handAnimationData.Add(datum); }
}
return handAnimationData.NullOrEmpty() == false;
}
public static Vector3 GetHandPosition(Pawn pawn, HandAnimationData handAnimationData, Vector3 basePosition, float baseAngle)
{
Vector3 handPosition = handAnimationData.Motion.GetHandPosition(pawn, handAnimationData, baseAngle);
return handPosition * pawn.RaceProps.baseBodySize + basePosition + new Vector3(0f, 0.3f, 0f);
}
public static float GetGenitalSize(Pawn pawn, string genitalName)
{
CompPawnSexData data = pawn?.TryGetComp<CompPawnSexData>();
if (data == null) return 0f;
switch (genitalName)
{
case "penis": return data.sizeOfPenis;
case "breasts": return data.sizeOfBreasts;
case "Penis": return data.sizeOfPenis;
case "Breasts": return data.sizeOfBreasts;
}
return 0.1f;
}
public static Graphic GetHandGraphic(Pawn touchingPawn)
{
CompPawnSexData comp = touchingPawn?.TryGetComp<CompPawnSexData>();
if (comp == null) return null;
if (comp.handGraphic == null)
{
string handGraphicPath = "Hands/HandClean";
comp.handGraphic = GraphicDatabase.Get<Graphic_Single>(handGraphicPath, ShaderDatabase.Cutout,
new Vector2(0.6667f * touchingPawn.RaceProps.baseBodySize, 0.6667f * touchingPawn.RaceProps.baseBodySize), touchingPawn.story.SkinColor);
}
return comp.handGraphic;
}
public static bool TryToDrawHand(Pawn pawn, ActorAnimationData pawnAnimationData, string bodyAddonName, Vector3 bodyAddonPosition, float bodyAddonAngle, Rot4 bodyAddonRotation, PawnRenderFlags renderFlags)
{
if (BodyPartIsBeingTouched(pawn, pawnAnimationData, bodyAddonName, out List<HandAnimationData> handAnimationData))
{
foreach (HandAnimationData datum in handAnimationData)
{
Pawn touchingPawn = datum.touchingActorID >= 0 && pawn.GetAllSexParticipants().Count > datum.touchingActorID ? pawn.GetAllSexParticipants()[datum.touchingActorID] : pawn;
Graphic handGraphic = GetHandGraphic(touchingPawn);
if (handGraphic == null) return false;
Vector3 handPosition = GetHandPosition(pawn, datum, bodyAddonPosition, bodyAddonAngle);
GenDraw.DrawMeshNowOrLater(mesh: handGraphic.MeshAt(rot: bodyAddonRotation),
loc: handPosition + new Vector3(0f, 0.022f, 0f),
quat: Quaternion.identity,
mat: handGraphic.MatAt(rot: bodyAddonRotation), renderFlags.FlagSet(PawnRenderFlags.DrawNow));
return true;
}
}
return false;
}
}
}