playerAnimator

playerAnimator

28M Downloads

Preventing Animation Model Rotation

TunYuntuwuQWQ opened this issue ยท 1 comments

commented

When using Player Animator to play animations, I want to ensure that the animated model does not rotate with the player's view.

How can I achieve this? (in 1.21 neoforge)

Does Player Animator support this feature? If not, would it be possible to consider adding it?

I have tried subscribing to the 'RendererPlayerEvent.Pre' event and making some adjustments, but the results were not satisfactory. Although the animation plays, the body position animation no longer functions correctly.

I look forward to your response. (I am using translation software.)

commented
What I did was like this
@EventBusSubscriber(modid = HugMe.MODID, value = Dist.CLIENT, bus = EventBusSubscriber.Bus.GAME)
public class RenderPlayerEventHandler {
    private static final Minecraft client = Minecraft.getInstance();
    private static final Map<UUID, UUID> playerLockMap = new HashMap<>();
    private static final Map<UUID, Boolean> playerLockState = new HashMap<>();

    @SubscribeEvent
    public static void onRenderPlayer(RenderPlayerEvent.Pre event) {
        Player player = event.getEntity();
        PlayerRenderer renderer = event.getRenderer();
        float partialTicks = event.getPartialTick();
        PoseStack poseStack = event.getPoseStack();
        MultiBufferSource buffer = event.getMultiBufferSource();
        int packedLight = event.getPackedLight();

        if (player instanceof AbstractClientPlayer clientPlayer) {
            UUID playerId = player.getUUID();
            if (playerLockMap.containsKey(playerId)) {
                UUID targetPlayerUUID = playerLockMap.get(playerId);
                if (targetPlayerUUID == null) return;
                if (client.level == null) return;
                AbstractClientPlayer targetPlayer = (AbstractClientPlayer) client.level.getPlayerByUUID(targetPlayerUUID);
                if (targetPlayer == null) return;
                float targetYaw = calculateYawToTarget(clientPlayer, targetPlayer);

                poseStack.pushPose();

                poseStack.mulPose(Axis.XP.rotationDegrees(180.0F));
                poseStack.translate(0, -1.5, 0);
                poseStack.mulPose(new org.joml.Quaternionf().rotationY((float) Math.toRadians(targetYaw)));
                renderPlayerModel(renderer, clientPlayer, partialTicks, poseStack, buffer, packedLight);

                poseStack.popPose();
                event.setCanceled(true);
            }
        }
    }

    private static void renderPlayerModel(PlayerRenderer renderer, AbstractClientPlayer entity, float partialTicks, PoseStack poseStack, MultiBufferSource buffer, int packedLight) {
        PlayerModel<AbstractClientPlayer> model = renderer.getModel();
        model.young = entity.isBaby();

        if (entity == client.player && client.options.getCameraType() == CameraType.FIRST_PERSON) {
            model.head.visible = false;
        }

        model.setupAnim(entity, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F);
        RenderType renderType = RenderType.entityCutoutNoCull(renderer.getTextureLocation(entity));

        model.renderToBuffer(poseStack, buffer.getBuffer(renderType), packedLight, OverlayTexture.NO_OVERLAY, -1);
    }

    private static float calculateYawToTarget(AbstractClientPlayer fromPlayer, AbstractClientPlayer toPlayer) {
        double deltaX = toPlayer.getX() - fromPlayer.getX();
        double deltaZ = toPlayer.getZ() - fromPlayer.getZ();
        return (float) Math.toDegrees(Math.atan2(deltaZ, deltaX)) - 90.0F;
    }

    public static void lockPlayers(AbstractClientPlayer player1, AbstractClientPlayer player2) {
        playerLockMap.put(player1.getUUID(), player2.getUUID());
        playerLockMap.put(player2.getUUID(), player1.getUUID());
        playerLockState.put(player1.getUUID(), true);
        playerLockState.put(player2.getUUID(), true);
        HugMe.LOGGER.debug("Locked " + player1.getName().getString() + " and " + player2.getName().getString());
    }

    public static void unlockPlayers(AbstractClientPlayer player1, AbstractClientPlayer player2) {
        playerLockMap.remove(player1.getUUID());
        playerLockMap.remove(player2.getUUID());
        playerLockState.remove(player1.getUUID());
        playerLockState.remove(player2.getUUID());
        HugMe.LOGGER.debug("Unlocked " + player1.getName().getString() + " and " + player2.getName().getString());
    }

    public static boolean isPlayerLocked(AbstractClientPlayer player) {
        return playerLockState.getOrDefault(player.getUUID(), false);
    }
}