Skip to content

Commit

Permalink
Change state encapsulation and handling of the slim model (one render…
Browse files Browse the repository at this point in the history
…er for each model).
  • Loading branch information
MoonstoneWebber committed Jan 24, 2025
1 parent 1646969 commit ab20cae
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 135 deletions.
Original file line number Diff line number Diff line change
@@ -1,25 +1,16 @@
package it.crystalnest.fancy_entity_renderer.api.entity.player;

import com.mojang.blaze3d.vertex.PoseStack;
import it.crystalnest.fancy_entity_renderer.api.Rotation;
import it.crystalnest.fancy_entity_renderer.api.entity.player.model.FancyPlayerModel;
import it.crystalnest.fancy_entity_renderer.api.entity.player.state.FancyPlayerRenderState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
import net.minecraft.client.renderer.entity.state.PlayerRenderState;
import net.minecraft.client.resources.DefaultPlayerSkin;
import net.minecraft.client.resources.PlayerSkin;
import net.minecraft.client.resources.model.EquipmentAssetManager;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.Pose;
import net.minecraft.world.entity.animal.Parrot;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joml.Quaternionf;

public class FancyPlayerRenderer extends PlayerRenderer {
Expand All @@ -34,41 +25,15 @@ public class FancyPlayerRenderer extends PlayerRenderer {
Minecraft.getInstance().font
);

public final Rotation leftArmRot = new Rotation();
private final FancyPlayerModel adultModel;

public final Rotation rightArmRot = new Rotation();
private final FancyPlayerModel babyModel;

public final Rotation leftLegRot = new Rotation();

public final Rotation rightLegRot = new Rotation();

public final Rotation headRot = new Rotation();

public final Rotation bodyRot = new Rotation();

public final PlayerRenderState state = createRenderState();

public PlayerSkin skin = DefaultPlayerSkin.get(Minecraft.getInstance().getGameProfile());

public boolean isCrouching = false;

public boolean isBaby = false;

public boolean isSlim = false;

public boolean isGlowing = false;

public Pose pose = Pose.STANDING;

@Nullable
public Parrot.Variant leftShoulderParrot = null;

@Nullable
public Parrot.Variant rightShoulderParrot = null;

public FancyPlayerRenderer() {
super(RENDER_CONTEXT, false);
model = new FancyPlayerModel(this::updateModel, isSlim, isBaby);
public FancyPlayerRenderer(boolean slim) {
super(RENDER_CONTEXT, slim);
adultModel = new FancyPlayerModel(slim, false);
babyModel = new FancyPlayerModel(slim, true);
model = adultModel;
entityRenderDispatcher.overrideCameraOrientation(new Quaternionf());
}

Expand All @@ -78,72 +43,10 @@ public PlayerRenderState createRenderState() {
return new FancyPlayerRenderState();
}

public void updateRenderState(@NotNull PlayerRenderState state) {
// TODO: Implement copying the local player (name, texture, showCape/showHat/show..., cape texture)
// TODO: Implement choosing local texture files (both skin and cape), as well as choosing the texture from a player's name/uuid.
state.skin = skin;
state.isCrouching = isCrouching;
state.parrotOnLeftShoulder = leftShoulderParrot;
state.parrotOnRightShoulder = rightShoulderParrot;
// reusedState.nameTag = this.getNameTag(p_entity);
// reusedState.nameTagAttachment = new Player().getAttachments().getNullable(EntityAttachment.NAME_TAG, 0, p_entity.getYRot(partialTick));
/**
* Values below copied from {@link EntityType.Builder#nameTagOffset(float)}
*/
state.nameTag = Component.literal("TEST");
state.nameTagAttachment = new Vec3(0.0F, 2.05F, 0.0F);
// TODO: Fix name tag. It doesn't render currently.
state.customName = null;
state.isBaby = isBaby;
// TODO: Glowing effect doesn't work. The entity renders the same regardless. Could ignore this, since it was not in the original FancyManu, but it would be nice to have (not even sure this is the right property).
state.appearsGlowing = isGlowing;
state.isSpectator = false;
state.pose = isCrouching ? Pose.CROUCHING : pose;
state.isDiscrete = isCrouching;
// TODO: Works almost fine, but the item model is kind of transparent to itself.
// Minecraft.getInstance().getItemModelResolver().updateForTopItem(state.rightHandItem, Items.NETHERITE_SWORD.getDefaultInstance(), ItemDisplayContext.THIRD_PERSON_RIGHT_HAND, false, null, null, ItemDisplayContext.THIRD_PERSON_RIGHT_HAND.ordinal());
// TODO: Why is armor not rendered?
// state.headEquipment = Items.NETHERITE_HELMET.getDefaultInstance();
// state.chestEquipment = Items.NETHERITE_CHESTPLATE.getDefaultInstance();
// TODO: The reason why the flame doesn't render might be the same reason why the name tag doesn't render.
// state.displayFireAnimation = true;
// TODO: Render elytra (if cape has a texture, elytra should be renderer with that texture too).
}

public void updateModel(@NotNull PlayerRenderState state) {
model.leftArm.xRot = leftArmRot.getX();
model.leftArm.yRot = leftArmRot.getY();
model.leftArm.zRot = leftArmRot.getZ();

model.rightArm.xRot = rightArmRot.getX();
model.rightArm.yRot = rightArmRot.getY();
model.rightArm.zRot = rightArmRot.getZ();

model.leftLeg.xRot = leftLegRot.getX();
model.leftLeg.yRot = leftLegRot.getY();
model.leftLeg.zRot = leftLegRot.getZ();

model.rightLeg.xRot = rightLegRot.getX();
model.rightLeg.yRot = rightLegRot.getY();
model.rightLeg.zRot = rightLegRot.getZ();

model.root().xRot = bodyRot.getX();
model.root().yRot = bodyRot.getY();
model.root().zRot = bodyRot.getZ();

model.head.xRot = headRot.getX();
model.head.yRot = headRot.getY();
model.head.zRot = headRot.getZ();
}

@Override
@ApiStatus.Internal
public void render(@NotNull PlayerRenderState state, @NotNull PoseStack poseStack, @NotNull MultiBufferSource bufferSource, int packedLight) {
updateRenderState(state);
model = state.isBaby ? babyModel : adultModel;
super.render(state, poseStack, bufferSource, packedLight);
}

public void render(@NotNull PoseStack poseStack, @NotNull MultiBufferSource bufferSource, int packedLight) {
render(state, poseStack, bufferSource, packedLight);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,29 @@

import com.mojang.blaze3d.platform.Lighting;
import com.mojang.math.Axis;
import it.crystalnest.fancy_entity_renderer.api.entity.player.state.FancyPlayerRenderState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.narration.NarrationElementOutput;
import net.minecraft.client.resources.DefaultPlayerSkin;
import net.minecraft.client.resources.PlayerSkin;
import net.minecraft.client.sounds.SoundManager;
import net.minecraft.network.chat.CommonComponents;
import org.jetbrains.annotations.NotNull;

public class FancyPlayerWidget extends AbstractWidget {
private final FancyPlayerRenderer renderer = new FancyPlayerRenderer();
private final FancyPlayerRenderer renderer;

private static final FancyPlayerRenderer WIDE_RENDERER = new FancyPlayerRenderer(false);

private static final FancyPlayerRenderer SLIM_RENDERER = new FancyPlayerRenderer(true);

private final FancyPlayerRenderState renderState = new FancyPlayerRenderState();

public FancyPlayerWidget(int x, int y, int width, int height) {
super(x, y, width, height, CommonComponents.EMPTY);
renderer = DefaultPlayerSkin.get(Minecraft.getInstance().getGameProfile()).model() == PlayerSkin.Model.SLIM ? SLIM_RENDERER : WIDE_RENDERER;
}

@Override
Expand All @@ -24,8 +35,8 @@ protected void renderWidget(GuiGraphics gfx, int mouseX, int mouseY, float parti
float h = (float) Math.atan(((c - mouseX) / 40.0F));
float i = (float) Math.atan(((g - mouseY) / 40.0F));
// Must rotate around Y axis when mouse moves along X axis and vice versa.
renderer.bodyRot.setX((float) Math.toRadians(-i * 20.0F));
renderer.bodyRot.setY((float) -Math.toRadians(h * 20.0F));
renderState.bodyRot.setX((float) Math.toRadians(-i * 20.0F));
renderState.bodyRot.setY((float) -Math.toRadians(h * 20.0F));
// } else {
// renderer.bodyRot.setX((float) Math.toRadians(this.stringToFloat(this.bodyXRot)));
// renderer.bodyRot.setY((float) Math.toRadians(this.stringToFloat(this.bodyYRot)));
Expand All @@ -36,15 +47,48 @@ protected void renderWidget(GuiGraphics gfx, int mouseX, int mouseY, float parti
float f = getHeight() / 2.125F;
gfx.pose().scale(f, f, f);
gfx.pose().translate(0, -0.0625F, 0);
gfx.pose().rotateAround(Axis.XP.rotationDegrees(renderer.bodyRot.getX()), 0, -1.0625F, 0);
gfx.pose().mulPose(Axis.YP.rotationDegrees(renderer.bodyRot.getY()));
gfx.pose().rotateAround(Axis.XP.rotationDegrees(renderState.bodyRot.getX()), 0, -1.0625F, 0);
gfx.pose().mulPose(Axis.YP.rotationDegrees(renderState.bodyRot.getY()));
gfx.flush();
Lighting.setupForEntityInInventory(Axis.XP.rotationDegrees(renderer.bodyRot.getX()));
gfx.drawSpecial(src -> renderer.render(gfx.pose(), src, 15728880));
Lighting.setupForEntityInInventory(Axis.XP.rotationDegrees(renderState.bodyRot.getX()));
gfx.drawSpecial(src -> renderer.render(renderState, gfx.pose(), src, 15728880));
Lighting.setupFor3DItems();
gfx.pose().popPose();
}


// public void updateRenderState(@NotNull PlayerRenderState state) {
// // TODO: Implement copying the local player (name, texture, showCape/showHat/show..., cape texture)
// // TODO: Implement choosing local texture files (both skin and cape), as well as choosing the texture from a player's name/uuid.
// state.skin = skin;
// state.isCrouching = isCrouching;
// state.parrotOnLeftShoulder = leftShoulderParrot;
// state.parrotOnRightShoulder = rightShoulderParrot;
//// reusedState.nameTag = this.getNameTag(p_entity);
//// reusedState.nameTagAttachment = new Player().getAttachments().getNullable(EntityAttachment.NAME_TAG, 0, p_entity.getYRot(partialTick));
// /**
// * Values below copied from {@link EntityType.Builder#nameTagOffset(float)}
// */
// state.nameTag = Component.literal("TEST");
// state.nameTagAttachment = new Vec3(0.0F, 2.05F, 0.0F);
// // TODO: Fix name tag. It doesn't render currently.
// state.customName = null;
// state.isBaby = isBaby;
// // TODO: Glowing effect doesn't work. The entity renders the same regardless. Could ignore this, since it was not in the original FancyManu, but it would be nice to have (not even sure this is the right property).
// state.appearsGlowing = isGlowing;
// state.isSpectator = false;
// state.pose = isCrouching ? Pose.CROUCHING : pose;
// state.isDiscrete = isCrouching;
// // TODO: Works almost fine, but the item model is kind of transparent to itself.
//// Minecraft.getInstance().getItemModelResolver().updateForTopItem(state.rightHandItem, Items.NETHERITE_SWORD.getDefaultInstance(), ItemDisplayContext.THIRD_PERSON_RIGHT_HAND, false, null, null, ItemDisplayContext.THIRD_PERSON_RIGHT_HAND.ordinal());
// // TODO: Why is armor not rendered?
//// state.headEquipment = Items.NETHERITE_HELMET.getDefaultInstance();
//// state.chestEquipment = Items.NETHERITE_CHESTPLATE.getDefaultInstance();
// // TODO: The reason why the flame doesn't render might be the same reason why the name tag doesn't render.
//// state.displayFireAnimation = true;
// // TODO: Render elytra (if cape has a texture, elytra should be renderer with that texture too).
// }

@Override
public void playDownSound(@NotNull SoundManager soundManager) {
// Disable playing any sound when clicked.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
package it.crystalnest.fancy_entity_renderer.api.entity.player.model;

import it.crystalnest.fancy_entity_renderer.api.entity.player.state.FancyPlayerRenderState;
import net.minecraft.client.model.PlayerModel;
import net.minecraft.client.model.geom.ModelPart;
import net.minecraft.client.model.geom.builders.CubeDeformation;
import net.minecraft.client.model.geom.builders.LayerDefinition;
import net.minecraft.client.renderer.entity.state.PlayerRenderState;
import org.jetbrains.annotations.NotNull;

import java.util.function.Consumer;

public class FancyPlayerModel extends PlayerModel {
private static final LayerDefinition FANCY_PLAYER = LayerDefinition.create(createMesh(CubeDeformation.NONE, false), 64, 64);

private static final LayerDefinition FANCY_PLAYER_SLIM = LayerDefinition.create(createMesh(CubeDeformation.NONE, true), 64, 64);

private final Consumer<PlayerRenderState> updater;

public FancyPlayerModel(Consumer<PlayerRenderState> updater, boolean isSlim, boolean isBaby) {
public FancyPlayerModel(boolean isSlim, boolean isBaby) {
super(getModelPart(isSlim, isBaby), isSlim);
this.updater = updater;
}

private static ModelPart getModelPart(boolean isSlim, boolean isBaby) {
Expand All @@ -32,6 +28,32 @@ private static ModelPart getModelPart(boolean isSlim, boolean isBaby) {
@Override
public void setupAnim(@NotNull PlayerRenderState state) {
super.setupAnim(state);
updater.accept(state);
update((FancyPlayerRenderState) state);
}

private void update(@NotNull FancyPlayerRenderState state) {
leftArm.xRot = state.leftArmRot.getX();
leftArm.yRot = state.leftArmRot.getY();
leftArm.zRot = state.leftArmRot.getZ();

rightArm.xRot = state.rightArmRot.getX();
rightArm.yRot = state.rightArmRot.getY();
rightArm.zRot = state.rightArmRot.getZ();

leftLeg.xRot = state.leftLegRot.getX();
leftLeg.yRot = state.leftLegRot.getY();
leftLeg.zRot = state.leftLegRot.getZ();

rightLeg.xRot = state.rightLegRot.getX();
rightLeg.yRot = state.rightLegRot.getY();
rightLeg.zRot = state.rightLegRot.getZ();

root().xRot = state.bodyRot.getX();
root().yRot = state.bodyRot.getY();
root().zRot = state.bodyRot.getZ();

head.xRot = state.headRot.getX();
head.yRot = state.headRot.getY();
head.zRot = state.headRot.getZ();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
package it.crystalnest.fancy_entity_renderer.api.entity.player.state;

import it.crystalnest.fancy_entity_renderer.api.Rotation;
import net.minecraft.client.renderer.entity.state.PlayerRenderState;

public class FancyPlayerRenderState extends PlayerRenderState {

public boolean isSlim = false;

public final Rotation leftArmRot = new Rotation();

public final Rotation rightArmRot = new Rotation();

public final Rotation leftLegRot = new Rotation();

public final Rotation rightLegRot = new Rotation();

public final Rotation headRot = new Rotation();

public final Rotation bodyRot = new Rotation();

public FancyPlayerRenderState() {
isUpsideDown = true;
}
Expand Down

0 comments on commit ab20cae

Please sign in to comment.