diff --git a/visor-core/src/main/java/org/vmstudio/visor/core/client/player/VRLocalPlayerImpl.java b/visor-core/src/main/java/org/vmstudio/visor/core/client/player/VRLocalPlayerImpl.java index 860b045a..3f767726 100644 --- a/visor-core/src/main/java/org/vmstudio/visor/core/client/player/VRLocalPlayerImpl.java +++ b/visor-core/src/main/java/org/vmstudio/visor/core/client/player/VRLocalPlayerImpl.java @@ -29,6 +29,7 @@ import org.vmstudio.visor.core.client.network.ClientNetworking; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionHand; import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.AABB; @@ -331,16 +332,19 @@ public void updatePlayerLook(LocalPlayer player, PlayerPoseType stage) { return; } if (player.isBlocking()) { - //block direction - if (ClientContext.localPlayer.getActiveHand() == HandType.MAIN) { - player.setYRot(data.getHand(HandType.MAIN).getYawDegrees()); - player.setYHeadRot(player.getYRot()); - player.setXRot(-data.getHand(HandType.MAIN).getPitchDegrees()); - } else { - player.setYRot(data.getHand(HandType.OFFHAND).getYawDegrees()); - player.setYHeadRot(player.getYRot()); - player.setXRot(-data.getHand(HandType.OFFHAND).getPitchDegrees()); - } + HandType activeHand = ClientContext.localPlayer.getActiveHand() == HandType.MAIN + ? HandType.MAIN + : HandType.OFFHAND; + visor$applyPoseLook(player, data.getHand(activeHand)); + return; + } + + if (VRClientSettings.isCompatibleLookDirection() + && player.isUsingItem()) { + HandType usingHand = player.getUsedItemHand() == InteractionHand.MAIN_HAND + ? HandType.MAIN + : HandType.OFFHAND; + visor$applyPoseLook(player, data.getHand(usingHand)); return; } @@ -351,38 +355,21 @@ public void updatePlayerLook(LocalPlayer player, PlayerPoseType stage) { && player.zza > 0.0F) { VRPose rotationElement = getRotationElement(data.getType()); - player.setYRot(rotationElement.getYawDegrees()); - player.setYHeadRot(player.getYRot()); - player.setXRot(-rotationElement.getPitchDegrees()); + visor$applyPoseLook(player, rotationElement); return; } - if (((GameRendererExtension) MC.gameRenderer).visor$getCrossVec() != null) { - //Look AT the crosshair by default, most compatible with mods. - Vec3 playerToCrosshair = player.getEyePosition(1) - .subtract(((GameRendererExtension) MC.gameRenderer) - .visor$getCrossVec()); //backwards - double what = playerToCrosshair.y / playerToCrosshair.length(); - if (what > 1) { - what = 1; - } - if (what < -1) { - what = -1; - } - float pitch = (float) Math.toDegrees(Math.asin(what)); - float yaw = (float) Math.toDegrees( - Mth.atan2(playerToCrosshair.x, -playerToCrosshair.z) + Vec3 crossVec = ((GameRendererExtension) MC.gameRenderer).visor$getCrossVec(); + if (!VRClientSettings.isCompatibleLookDirection() + && crossVec != null) { + visor$applyVectorLook( + player, + crossVec.subtract(player.getEyePosition(1.0F)).normalize() ); - player.setXRot(pitch); - player.setYRot(yaw); - player.setYHeadRot(yaw); return; } - //use HMD if no other option found - player.setYRot(data.getHmd().getUsedRotationY()); - player.setYHeadRot(player.getYRot()); - player.setXRot(-data.getHmd().getPitchDegrees()); + visor$applyPoseLook(player, data.getHmd()); } public void recenterOrigin(@NotNull Entity cameraEntity, @@ -519,6 +506,29 @@ public String toString() { ); } + private void visor$applyPoseLook(@NotNull LocalPlayer player, + @NotNull VRPose pose) { + player.setYRot(pose.getYawDegrees()); + player.setYHeadRot(player.getYRot()); + player.setXRot(-pose.getPitchDegrees()); + } + + private void visor$applyVectorLook(@NotNull LocalPlayer player, + @NotNull Vec3 view) { + double length = view.length(); + if (length < 1.0E-6D) { + return; + } + + double normalizedY = Mth.clamp(-view.y / length, -1.0D, 1.0D); + float pitch = (float) Math.toDegrees(Math.asin(normalizedY)); + float yaw = (float) Math.toDegrees(Mth.atan2(-view.x, view.z)); + + player.setXRot(pitch); + player.setYRot(yaw); + player.setYHeadRot(yaw); + } + } diff --git a/visor-core/src/main/java/org/vmstudio/visor/core/client/settings/VRClientSettings.java b/visor-core/src/main/java/org/vmstudio/visor/core/client/settings/VRClientSettings.java index 5fab3654..19374a17 100644 --- a/visor-core/src/main/java/org/vmstudio/visor/core/client/settings/VRClientSettings.java +++ b/visor-core/src/main/java/org/vmstudio/visor/core/client/settings/VRClientSettings.java @@ -78,6 +78,11 @@ public class VRClientSettings { @VROptionField(widgetType = VROptionWidgetType.WALK_UP, key = "walk_up") protected static boolean walkUpEnabled = true; + @Getter + @VROptionField(widgetType = VROptionWidgetType.COMPATIBLE_LOOK_DIRECTION, + key = "compatible_look_direction") + protected static boolean compatibleLookDirection = false; + @Getter diff --git a/visor-core/src/main/java/org/vmstudio/visor/core/client/settings/VROptionWidgetType.java b/visor-core/src/main/java/org/vmstudio/visor/core/client/settings/VROptionWidgetType.java index 2bbc5442..6b5cc6bc 100644 --- a/visor-core/src/main/java/org/vmstudio/visor/core/client/settings/VROptionWidgetType.java +++ b/visor-core/src/main/java/org/vmstudio/visor/core/client/settings/VROptionWidgetType.java @@ -172,6 +172,10 @@ public enum VROptionWidgetType { VROptionCategory.MOVEMENT, (it) -> null ), + COMPATIBLE_LOOK_DIRECTION( + VROptionCategory.MOVEMENT, + (it) -> null + ), WORLD_ROTATION_STEP( VROptionCategory.MOVEMENT, (it) -> { diff --git a/visor-core/src/main/resources/assets/visor/lang/en_us.json b/visor-core/src/main/resources/assets/visor/lang/en_us.json index 5633ed60..c8d5dc8b 100644 --- a/visor-core/src/main/resources/assets/visor/lang/en_us.json +++ b/visor-core/src/main/resources/assets/visor/lang/en_us.json @@ -53,6 +53,9 @@ "visor.options.movement.walk_up.tooltip": "§bWalk Up§r\n\nAutomatically step up onto blocks while walking.", + "visor.options.movement.compatible_look_direction": "Compatible Look", + "visor.options.movement.compatible_look_direction.tooltip": "§bCompatible Look Direction§r\n\nUses the §eHMD direction§r as your default reported look direction.\n\nWhen you actively use an item, the look direction temporarily follows the §eusing hand§r instead.\n\n§7This can help mods that depend on player look direction, but it is a best-effort compatibility mode and may change aiming behavior.§r", + "_comment.gui": "----GUI Settings----", "visor.options.gui.button": "GUI", "visor.options.gui.shader_gui_render": "Shaders GUI",