add comp tick, needs tracker and pawn rendering optimizations, cache more dates, fix reflection patches, default to disabled for texture atlas patch
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
// Copyright (c) 2026 Bradson
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using PerformanceFish.Prepatching;
|
||||
|
||||
namespace PerformanceFish.Rendering;
|
||||
|
||||
public sealed class PawnRenderingOptimizations : ClassWithFishPrepatches
|
||||
{
|
||||
private const int DAMAGE_FLASH_TICKS_TOTAL = 16;
|
||||
|
||||
public sealed class IsHiddenFromPlayerPatch : FishPrepatch
|
||||
{
|
||||
// not 100% on this even benefitting, bionics, scars, etc likely worsen performance here because of the extra check
|
||||
// probably better to just track if a hediff adds invisibility
|
||||
public override string? Description { get; }
|
||||
= "Fast-paths InvisibilityUtility.IsHiddenFromPlayer for the case where a pawn has no hediffs.";
|
||||
|
||||
public override MethodBase TargetMethodBase { get; }
|
||||
= AccessTools.DeclaredMethod(typeof(InvisibilityUtility),
|
||||
nameof(InvisibilityUtility.IsHiddenFromPlayer), [typeof(Pawn)]);
|
||||
|
||||
public override void Transpiler(ILProcessor ilProcessor, ModuleDefinition module)
|
||||
=> ilProcessor.ReplaceBodyWith(ReplacementBody);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool ReplacementBody(Pawn pawn)
|
||||
{
|
||||
if (DebugSettings.showHiddenPawns)
|
||||
return false;
|
||||
|
||||
if (pawn.Faction == Faction.OfPlayer)
|
||||
return false;
|
||||
|
||||
var hediffs = pawn.health.hediffSet.hediffs;
|
||||
if (hediffs.Count == 0)
|
||||
return false;
|
||||
|
||||
for (var i = 0; i < hediffs.Count; i++)
|
||||
{
|
||||
var comp = hediffs[i].TryGetComp<HediffComp_Invisibility>();
|
||||
if (comp != null && !comp.Props.visibleToPlayer && !comp.PsychologicallyVisible)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class PawnRenderTreeComputeMatrixPatch : FishPrepatch
|
||||
{
|
||||
public override string? Description { get; }
|
||||
= "Avoids Matrix4x4 inverse work when undoing a pivot translation in PawnRenderTree.ComputeMatrix.";
|
||||
|
||||
public override MethodBase TargetMethodBase { get; }
|
||||
= AccessTools.DeclaredMethod(typeof(PawnRenderTree), "ComputeMatrix");
|
||||
|
||||
public override void Transpiler(ILProcessor ilProcessor, ModuleDefinition module)
|
||||
=> ilProcessor.ReplaceBodyWith(ReplacementBody);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void ReplacementBody(PawnRenderTree instance, ref Matrix4x4 matrix, in Vector3 offset,
|
||||
in Vector3 pivot, in Quaternion rotation, in Vector3 scale, bool canRotate)
|
||||
{
|
||||
if (offset != Vector3.zero)
|
||||
matrix *= Matrix4x4.Translate(offset);
|
||||
|
||||
if (pivot != Vector3.zero)
|
||||
matrix *= Matrix4x4.Translate(pivot);
|
||||
|
||||
if (canRotate && rotation != Quaternion.identity)
|
||||
matrix *= Matrix4x4.Rotate(rotation);
|
||||
|
||||
if (scale != Vector3.one)
|
||||
matrix *= Matrix4x4.Scale(scale);
|
||||
|
||||
if (pivot != Vector3.zero)
|
||||
matrix *= Matrix4x4.Translate(-pivot);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class DamageFlasherCurColorPatch : FishPrepatch
|
||||
{
|
||||
private static readonly AccessTools.FieldRef<DamageFlasher, int> _lastDamageTick
|
||||
= AccessTools.FieldRefAccess<DamageFlasher, int>("lastDamageTick");
|
||||
|
||||
public override string? Description { get; }
|
||||
= "Fast-paths DamageFlasher.CurColor when no damage flash is active.";
|
||||
|
||||
public override MethodBase TargetMethodBase { get; }
|
||||
= AccessTools.DeclaredPropertyGetter(typeof(DamageFlasher), nameof(DamageFlasher.CurColor));
|
||||
|
||||
public override void Transpiler(ILProcessor ilProcessor, ModuleDefinition module)
|
||||
=> ilProcessor.ReplaceBodyWith(ReplacementBody);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Color ReplacementBody(DamageFlasher instance)
|
||||
{
|
||||
var ticksLeft = _lastDamageTick(instance) + DAMAGE_FLASH_TICKS_TOTAL - Find.TickManager.TicksGame;
|
||||
return ticksLeft <= 0
|
||||
? Color.white
|
||||
: Color.Lerp(Color.white, DamagedMatPool.DamagedMatStartingColor,
|
||||
(float)ticksLeft / DAMAGE_FLASH_TICKS_TOTAL);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class DamageFlasherGetDamagedMatPatch : FishPrepatch
|
||||
{
|
||||
private static readonly AccessTools.FieldRef<DamageFlasher, int> _lastDamageTick
|
||||
= AccessTools.FieldRefAccess<DamageFlasher, int>("lastDamageTick");
|
||||
|
||||
public override string? Description { get; }
|
||||
= "Fast-paths DamageFlasher.GetDamagedMat when no damage flash is active.";
|
||||
|
||||
public override MethodBase TargetMethodBase { get; }
|
||||
= AccessTools.DeclaredMethod(typeof(DamageFlasher), nameof(DamageFlasher.GetDamagedMat));
|
||||
|
||||
public override void Transpiler(ILProcessor ilProcessor, ModuleDefinition module)
|
||||
=> ilProcessor.ReplaceBodyWith(ReplacementBody);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Material ReplacementBody(DamageFlasher instance, Material baseMat)
|
||||
{
|
||||
var ticksLeft = _lastDamageTick(instance) + DAMAGE_FLASH_TICKS_TOTAL - Find.TickManager.TicksGame;
|
||||
return ticksLeft <= 0
|
||||
? baseMat
|
||||
: DamagedMatPool.GetDamageFlashMat(baseMat, (float)ticksLeft / DAMAGE_FLASH_TICKS_TOTAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user