Move all the transformations out into their own classes

This commit is contained in:
Sollace 2018-05-26 22:47:38 +02:00
parent cea593e68e
commit 658a48fe83
21 changed files with 459 additions and 353 deletions

View file

@ -13,6 +13,7 @@ import com.minelittlepony.pony.data.PonySize;
import com.minelittlepony.render.AbstractPonyRenderer;
import com.minelittlepony.render.PonyRenderer;
import com.minelittlepony.render.plane.PlaneRenderer;
import com.minelittlepony.transformation.PonyTransformation;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.model.ModelPlayer;
@ -33,7 +34,7 @@ import static com.minelittlepony.model.PonyModelConstants.*;
*/
public abstract class AbstractPonyModel extends ModelPlayer implements IModel {
protected boolean isSleeping;
public boolean isSleeping;
private boolean isFlying;
private boolean isSwimming;
@ -666,6 +667,11 @@ public abstract class AbstractPonyModel extends ModelPlayer implements IModel {
return metadata.getSize() == PonySize.FOAL || isChild;
}
@Override
public PonyTransformation getBodyTransformation() {
return (isChild ? PonySize.FOAL : metadata.getSize()).getTranformation();
}
@Override
public float getSwingAmount() {
return swingProgress;
@ -770,110 +776,7 @@ public abstract class AbstractPonyModel extends ModelPlayer implements IModel {
rotate(motionPitch, 1, 0, 0);
}
// TODO: Get these out of here
if (isChild()) {
transformFoal(part);
} else if (metadata.getSize() == PonySize.LARGE) {
transformLarge(part);
} else if (metadata.getSize() == PonySize.TALL) {
transformTall(part);
} else {
transformNormal(part);
}
}
private void transformNormal(BodyPart part) {
if (isSleeping) translate(0, -0.61F, 0.25F);
switch (part) {
case NECK:
if (isCrouching()) translate(-0.03F, 0.03F, 0.1F);
default:
}
}
private void transformTall(BodyPart part) {
if (isSleeping) translate(0, -0.5F, 0.25F);
switch (part) {
case HEAD:
translate(0, -0.15F, 0.01F);
if (isCrouching()) translate(0, 0.05F, 0);
break;
case NECK:
translate(0, -0.09F, -0.01F);
scale(1, 1.1F, 1);
if (isCrouching()) translate(-0.02F, -0.02F, 0.1F);
break;
case BODY:
case TAIL:
translate(0, -0.1F, 0);
scale(1, 1, 1);
break;
case LEGS:
translate(0, -0.25F, 0.03F);
scale(1, 1.18F, 1);
if (rainboom) translate(0, 0.05F, 0);
break;
}
}
private void transformLarge(BodyPart part) {
if (isSleeping) translate(0, -0.98F, 0.2F);
switch (part) {
case HEAD:
translate(0, -0.17F, -0.04F);
if (isSleeping) translate(0, 0, -0.1F);
if (isCrouching()) translate(0, 0.15F, 0);
break;
case NECK:
translate(0, -0.15F, -0.07F);
if (isCrouching()) translate(-0.03F, 0.16F, 0.07F);
break;
case BODY:
translate(0, -0.2F, -0.04F);
scale(1.15F, 1.2F, 1.2F);
break;
case TAIL:
translate(0, -0.2F, 0.08F);
break;
case LEGS:
translate(0, -0.14F, 0);
scale(1.15F, 1.12F, 1.15F);
break;
}
}
private void transformFoal(BodyPart part) {
if (isCrouching()) translate(0, -0.12F, 0);
if (isSleeping) translate(0, -1.48F, 0.25F);
if (isRiding) translate(0, 0.1F, 0);
switch (part) {
case NECK:
case HEAD:
translate(0, 0.76F, 0);
scale(0.9F, 0.9F, 0.9F);
if (part == BodyPart.HEAD)
break;
if (isCrouching()) translate(0, -0.01F, 0.15F);
break;
case BODY:
case TAIL:
translate(0, 0.76F, -0.04F);
scale(0.6F, 0.6F, 0.6F);
break;
case LEGS:
translate(0, 0.89F, 0);
scale(0.6F, 0.41F, 0.6F);
if (isCrouching()) translate(0, 0.12F, 0);
if (rainboom) translate(0, -0.08F, 0);
break;
}
getBodyTransformation().transform(this, part);
}
/**

View file

@ -5,5 +5,6 @@ public enum BodyPart {
BODY,
TAIL,
NECK,
LEGS,
LEGS;
}

View file

@ -16,7 +16,7 @@ public class ModelWrapper implements IModelWrapper {
* Created a new model wrapper to contain the given pony.
*/
public ModelWrapper(AbstractPonyModel model) {
this.body = model;
body = model;
armor = model.createArmour();
armor.apply(model.metadata);
}

View file

@ -4,6 +4,7 @@ import com.minelittlepony.model.BodyPart;
import com.minelittlepony.model.armour.PonyArmor;
import com.minelittlepony.pony.data.IPonyData;
import com.minelittlepony.pony.data.PonyWearable;
import com.minelittlepony.transformation.PonyTransformation;
public interface IModel extends ICapitated {
@ -19,6 +20,8 @@ public interface IModel extends ICapitated {
*/
void transform(BodyPart part);
PonyTransformation getBodyTransformation();
/**
* Returns a new pony armour to go with this model. Called on startup by a model wrapper.
*/

View file

@ -1,22 +1,26 @@
package com.minelittlepony.pony.data;
import com.minelittlepony.MineLittlePony;
import com.minelittlepony.transformation.*;
public enum PonySize implements ITriggerPixelMapped<PonySize> {
NORMAL(0, 0.4f, 1f),
LARGE(0xce3254, 0.5f, 0.8f),
FOAL(0xffbe53, 0.25f, 0.8f),
TALL(0x534b76, 0.45f, 1f);
NORMAL(0, 0.4f, 1f, new TransformNormal()),
LARGE(0xce3254, 0.5f, 0.8f, new TransformLarge()),
FOAL(0xffbe53, 0.25f, 0.8f, new TransformFoal()),
TALL(0x534b76, 0.45f, 1f, new TransformTall());
private int triggerValue;
private float shadowSize;
private float scale;
PonySize(int pixel, float shadowSz, float scaleF) {
private PonyTransformation transform;
PonySize(int pixel, float shadowSz, float scaleF, PonyTransformation transformation) {
triggerValue = pixel;
shadowSize = shadowSz;
scale = scaleF;
transform = transformation;
}
public float getShadowSize() {
@ -33,6 +37,10 @@ public enum PonySize implements ITriggerPixelMapped<PonySize> {
return scale;
}
public PonyTransformation getTranformation() {
return transform;
}
@Override
public int getTriggerPixel() {
return triggerValue;

View file

@ -42,8 +42,13 @@ public abstract class AbstractPonyLayer<T extends EntityLivingBase> implements L
return renderer;
}
@SuppressWarnings("unchecked")
protected IRenderPony getPonyRenderer() {
return (IRenderPony)renderer;
}
public AbstractPonyModel getPlayerModel() {
return ((IRenderPony) getRenderer()).getModelWrapper().getBody();
return getPonyRenderer().getModelWrapper().getBody();
}
@SuppressWarnings("unchecked")

View file

@ -32,7 +32,7 @@ public class LayerHeldPonyItem<T extends EntityLivingBase> extends AbstractPonyL
ItemStack right = mainRight ? itemMain : itemOff;
if (!left.isEmpty() || !right.isEmpty()) {
ModelBase model = getRenderer().getMainModel();
ModelBase model = getMainModel();
pushMatrix();
if (model instanceof IModel) {
@ -83,7 +83,7 @@ public class LayerHeldPonyItem<T extends EntityLivingBase> extends AbstractPonyL
* Renders the main arm
*/
protected void renderArm(EnumHandSide side) {
((ModelBiped) getRenderer().getMainModel()).postRenderArm(0.0625F, side);
this.<ModelBiped>getMainModel().postRenderArm(0.0625F, side);
}
@Override

View file

@ -2,7 +2,6 @@ package com.minelittlepony.render.layer;
import com.google.common.collect.Maps;
import com.minelittlepony.ForgeProxy;
import com.minelittlepony.ducks.IRenderPony;
import com.minelittlepony.model.ModelWrapper;
import com.minelittlepony.model.armour.ModelPonyArmor;
import com.minelittlepony.util.coordinates.Color;
@ -40,7 +39,7 @@ public class LayerPonyArmor<T extends EntityLivingBase> extends AbstractPonyLaye
@Override
public void doPonyRender(T entity, float move, float swing, float partialTicks, float ticks, float headYaw, float headPitch, float scale) {
pony = ((IRenderPony) getRenderer()).getModelWrapper();
pony = getPonyRenderer().getModelWrapper();
for (EntityEquipmentSlot i : EntityEquipmentSlot.values()) {
if (i.getSlotType() == Type.ARMOR) {

View file

@ -1,8 +1,7 @@
package com.minelittlepony.render.layer;
import com.minelittlepony.ducks.IRenderPony;
import com.minelittlepony.model.AbstractPonyModel;
import com.minelittlepony.model.BodyPart;
import com.minelittlepony.model.ModelWrapper;
import net.minecraft.client.entity.AbstractClientPlayer;
import net.minecraft.client.renderer.entity.RenderLivingBase;
@ -24,16 +23,17 @@ public class LayerPonyCape extends AbstractPonyLayer<AbstractClientPlayer> {
@Override
public void doPonyRender(@Nonnull AbstractClientPlayer player, float move, float swing, float partialTicks, float ticks, float headYaw, float headPitch, float scale) {
ModelWrapper model = ((IRenderPony) getRenderer()).getModelWrapper();
AbstractPonyModel model = getPlayerModel();
if (player.hasPlayerInfo() && !player.isInvisible()
&& player.isWearing(EnumPlayerModelParts.CAPE) && player.getLocationCape() != null
&& player.getItemStackFromSlot(EntityEquipmentSlot.CHEST).getItem() != Items.ELYTRA) {
pushMatrix();
model.getBody().transform(BodyPart.BODY);
model.transform(BodyPart.BODY);
translate(0, 0.24F, 0);
model.getBody().bipedBody.postRender(scale);
model.bipedBody.postRender(scale);
double capeX = player.prevChasingPosX + (player.chasingPosX - player.prevChasingPosX) * scale - (player.prevPosX + (player.posX - player.prevPosX) * scale);
double capeY = player.prevChasingPosY + (player.chasingPosY - player.prevChasingPosY) * scale - (player.prevPosY + (player.posY - player.prevPosY) * scale);
@ -64,7 +64,7 @@ public class LayerPonyCape extends AbstractPonyLayer<AbstractClientPlayer> {
rotate(180, 0, 0, 1);
rotate(90, 1, 0, 0);
getRenderer().bindTexture(player.getLocationCape());
model.getBody().renderCape(0.0625F);
model.renderCape(0.0625F);
popMatrix();
}
}

View file

@ -1,164 +0,0 @@
package com.minelittlepony.render.player;
import com.minelittlepony.MineLittlePony;
import com.minelittlepony.ducks.IRenderPony;
import com.minelittlepony.model.AbstractPonyModel;
import com.minelittlepony.model.ModelWrapper;
import com.minelittlepony.pony.data.Pony;
import com.minelittlepony.render.layer.LayerEntityOnPonyShoulder;
import com.minelittlepony.render.layer.LayerHeldPonyItemMagical;
import com.minelittlepony.render.layer.LayerPonyArmor;
import com.minelittlepony.render.layer.LayerPonyCape;
import com.minelittlepony.render.layer.LayerPonyCustomHead;
import com.minelittlepony.render.layer.LayerPonyElytra;
import net.minecraft.client.entity.AbstractClientPlayer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.entity.RenderPlayer;
import net.minecraft.client.renderer.entity.layers.LayerArrow;
import net.minecraft.entity.Entity;
import net.minecraft.util.ResourceLocation;
public abstract class RenderPonyBase extends RenderPlayer implements IRenderPony {
private ModelWrapper playerModel;
protected AbstractPonyModel ponyModel;
private Pony pony;
public RenderPonyBase(RenderManager manager, boolean useSmallArms, ModelWrapper model) {
super(manager, useSmallArms);
setPonyModel(model);
layerRenderers.clear();
addLayers();
}
protected void addLayers() {
addLayer(new LayerPonyArmor<>(this));
addLayer(new LayerHeldPonyItemMagical<>(this));
addLayer(new LayerArrow(this));
addLayer(new LayerPonyCustomHead<>(this));
addLayer(new LayerPonyElytra<>(this));
addLayer(new LayerPonyCape(this));
addLayer(new LayerEntityOnPonyShoulder(renderManager, this));
}
@Override
public float prepareScale(AbstractClientPlayer player, float ticks) {
if (!player.isRiding()) {
float x = player.width/2;
float y = 0;
if (player.isSneaking()) {
// Sneaking makes the player 1/15th shorter.
// This should be compatible with height-changing mods.
y += player.height / 15;
}
super.doRenderShadowAndFire(player, 0, y, x, 0, ticks);
}
return super.prepareScale(player, ticks);
}
@Override
protected void preRenderCallback(AbstractClientPlayer player, float ticks) {
updateModel(player);
ponyModel.updateLivingState(player, pony);
super.preRenderCallback(player, ticks);
shadowSize = getShadowScale();
float s = getScaleFactor();
GlStateManager.scale(s, s, s);
if (player.isRiding()) {
GlStateManager.translate(0, player.getYOffset(), 0);
}
}
@Override
public void doRenderShadowAndFire(Entity player, double x, double y, double z, float yaw, float ticks) {
if (player.isRiding()) {
super.doRenderShadowAndFire(player, x, y, z, yaw, ticks);
}
}
@Override
public void renderRightArm(AbstractClientPlayer player) {
updateModel(player);
bindEntityTexture(player);
GlStateManager.pushMatrix();
GlStateManager.translate(0, -0.37, 0);
super.renderRightArm(player);
GlStateManager.popMatrix();
}
@Override
public void renderLeftArm(AbstractClientPlayer player) {
updateModel(player);
bindEntityTexture(player);
GlStateManager.pushMatrix();
GlStateManager.translate(0.06, -0.37, 0);
super.renderLeftArm(player);
GlStateManager.popMatrix();
}
@Override
protected void applyRotations(AbstractClientPlayer player, float yaw, float pitch, float ticks) {
super.applyRotations(player, yaw, pitch, ticks);
double motionX = player.posX - player.prevPosX;
double motionY = player.onGround ? 0 : player.posY - player.prevPosY;
double motionZ = player.posZ - player.prevPosZ;
if (player.isElytraFlying()) {
transformElytraFlight(player, motionX, motionY, motionZ, ticks);
return;
}
if (player.isEntityAlive() && player.isPlayerSleeping()) return;
if (ponyModel.isGoingFast()) {
transformPegasusFlight(player, motionX, motionY, motionZ, yaw, pitch, ticks);
return;
}
// require arms to be stretched out (sorry mud ponies, no flight skills for you)
ponyModel.motionPitch = 0;
}
@Override
public ResourceLocation getEntityTexture(AbstractClientPlayer player) {
updateModel(player);
return pony.getTexture();
}
@Override
public ModelWrapper getModelWrapper() {
return playerModel;
}
protected void setPonyModel(ModelWrapper model) {
playerModel = model;
mainModel = ponyModel = playerModel.getBody();
}
protected void updateModel(AbstractClientPlayer player) {
pony = MineLittlePony.getInstance().getManager().getPony(player);
playerModel.apply(pony.getMetadata());
}
public Pony getPony() {
return pony;
}
protected abstract void transformElytraFlight(AbstractClientPlayer player, double motionX, double motionY, double motionZ, float ticks);
protected abstract void transformPegasusFlight(AbstractClientPlayer player, double motionX, double motionY, double motionZ, float yaw, float pitch, float ticks);
}

View file

@ -3,13 +3,23 @@ package com.minelittlepony.render.player;
import java.util.Map;
import java.util.Optional;
import com.minelittlepony.MineLittlePony;
import com.minelittlepony.PonyConfig;
import com.minelittlepony.ducks.IRenderPony;
import com.minelittlepony.model.AbstractPonyModel;
import com.minelittlepony.model.ModelWrapper;
import com.minelittlepony.model.components.ModelDeadMau5Ears;
import com.minelittlepony.pony.data.Pony;
import com.minelittlepony.pony.data.PonyLevel;
import com.minelittlepony.render.PonySkull;
import com.minelittlepony.render.PonySkullRenderer.ISkull;
import com.minelittlepony.util.math.MathUtil;
import com.minelittlepony.render.layer.LayerEntityOnPonyShoulder;
import com.minelittlepony.render.layer.LayerHeldPonyItemMagical;
import com.minelittlepony.render.layer.LayerPonyArmor;
import com.minelittlepony.render.layer.LayerPonyCape;
import com.minelittlepony.render.layer.LayerPonyCustomHead;
import com.minelittlepony.render.layer.LayerPonyElytra;
import com.minelittlepony.transformation.PonyPosture;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
@ -19,12 +29,16 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.AbstractClientPlayer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.resources.DefaultPlayerSkin;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.MathHelper;
import net.minecraft.client.renderer.entity.RenderPlayer;
import net.minecraft.client.renderer.entity.layers.LayerArrow;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
public class RenderPonyPlayer extends RenderPonyBase {
public class RenderPonyPlayer extends RenderPlayer implements IRenderPony {
public static final ISkull SKULL = new PonySkull() {
@ -70,76 +84,153 @@ public class RenderPonyPlayer extends RenderPonyBase {
}
}.register(ISkull.PLAYER);
public RenderPonyPlayer(RenderManager renderManager, boolean useSmallArms, ModelWrapper model) {
super(renderManager, useSmallArms, model);
private ModelWrapper playerModel;
protected AbstractPonyModel ponyModel;
protected Pony pony;
public RenderPonyPlayer(RenderManager manager, boolean useSmallArms, ModelWrapper model) {
super(manager, useSmallArms);
playerModel = model;
mainModel = ponyModel = playerModel.getBody();
layerRenderers.clear();
addLayers();
}
protected void addLayers() {
addLayer(new LayerPonyArmor<>(this));
addLayer(new LayerArrow(this));
addLayer(new LayerPonyCustomHead<>(this));
addLayer(new LayerPonyElytra<>(this));
addLayer(new LayerHeldPonyItemMagical<>(this));
addLayer(new LayerPonyCape(this));
addLayer(new LayerEntityOnPonyShoulder(renderManager, this));
}
@Override
public float prepareScale(AbstractClientPlayer player, float ticks) {
if (!player.isRiding()) {
float x = player.width/2;
float y = 0;
if (player.isSneaking()) {
// Sneaking makes the player 1/15th shorter.
// This should be compatible with height-changing mods.
y += player.height / 15;
}
super.doRenderShadowAndFire(player, 0, y, x, 0, ticks);
}
return super.prepareScale(player, ticks);
}
@Override
protected void preRenderCallback(AbstractClientPlayer player, float ticks) {
updateModel(player);
ponyModel.updateLivingState(player, pony);
super.preRenderCallback(player, ticks);
shadowSize = getShadowScale();
float s = getScaleFactor();
GlStateManager.scale(s, s, s);
if (player.isRiding()) {
GlStateManager.translate(0, player.getYOffset(), 0);
}
}
@Override
public void doRenderShadowAndFire(Entity player, double x, double y, double z, float yaw, float ticks) {
if (player.isRiding()) {
super.doRenderShadowAndFire(player, x, y, z, yaw, ticks);
}
}
@Override
public void renderRightArm(AbstractClientPlayer player) {
updateModel(player);
bindEntityTexture(player);
GlStateManager.pushMatrix();
GlStateManager.translate(0, -0.37, 0);
super.renderRightArm(player);
GlStateManager.popMatrix();
}
@Override
public void renderLeftArm(AbstractClientPlayer player) {
updateModel(player);
bindEntityTexture(player);
GlStateManager.pushMatrix();
GlStateManager.translate(0.06, -0.37, 0);
super.renderLeftArm(player);
GlStateManager.popMatrix();
}
@SuppressWarnings("unchecked")
@Override
protected void applyRotations(AbstractClientPlayer player, float yaw, float pitch, float ticks) {
super.applyRotations(player, yaw, pitch, ticks);
PonyPosture<?> posture = getPosture(player);
if (posture != null && posture.applies(player)) {
double motionX = player.posX - player.prevPosX;
double motionY = player.onGround ? 0 : player.posY - player.prevPosY;
double motionZ = player.posZ - player.prevPosZ;
((PonyPosture<EntityLivingBase>)posture).transform(getModelWrapper().getBody(), player, motionX, motionY, motionZ, pitch, yaw, ticks);
}
}
protected PonyPosture<?> getPosture(EntityLivingBase entity) {
if (entity.isElytraFlying()) {
return PonyPosture.ELYTRA;
}
if (entity.isEntityAlive() && entity.isPlayerSleeping()) return null;
if (getModelWrapper().getBody().isGoingFast()) {
return PonyPosture.FLIGHT;
}
//TODO: MC1.13 transformSwimming()
return PonyPosture.FALLING;
}
@Override
public ResourceLocation getEntityTexture(AbstractClientPlayer player) {
updateModel(player);
return pony.getTexture();
}
@Override
public ModelWrapper getModelWrapper() {
return playerModel;
}
protected void setPonyModel(ModelWrapper model) {
playerModel = model;
mainModel = ponyModel = playerModel.getBody();
}
protected void updateModel(AbstractClientPlayer player) {
pony = MineLittlePony.getInstance().getManager().getPony(player);
playerModel.apply(pony.getMetadata());
}
@Override
public float getShadowScale() {
return getPony().getMetadata().getSize().getShadowSize();
return pony.getMetadata().getSize().getShadowSize();
}
@Override
public float getScaleFactor() {
return getPony().getMetadata().getSize().getScaleFactor();
}
@Override
protected void transformElytraFlight(AbstractClientPlayer player, double motionX, double motionY, double motionZ, float ticks) {
GlStateManager.rotate(90, 1, 0, 0);
GlStateManager.translate(0, player.isSneaking() ? 0.2F : -1, 0);
}
private double calculateRoll(AbstractClientPlayer player, double motionX, double motionY, double motionZ) {
// since model roll should probably be calculated from model rotation rather than entity rotation...
double roll = MathUtil.sensibleAngle(player.prevRenderYawOffset - player.renderYawOffset);
double horMotion = Math.sqrt(motionX * motionX + motionZ * motionZ);
float modelYaw = MathUtil.sensibleAngle(player.renderYawOffset);
// detecting that we're flying backwards and roll must be inverted
if (Math.abs(MathUtil.sensibleAngle((float) Math.toDegrees(Math.atan2(motionX, motionZ)) + modelYaw)) > 90) {
roll *= -1;
}
// ayyy magic numbers (after 5 - an approximation of nice looking coefficients calculated by hand)
// roll might be zero, in which case Math.pow produces +Infinity. Anything x Infinity = NaN.
double pow = roll != 0 ? Math.pow(Math.abs(roll), -0.191) : 0;
roll *= horMotion * 5 * (3.6884f * pow);
assert !Float.isNaN((float)roll);
return MathHelper.clamp(roll, -54, 54);
}
@Override
protected void transformPegasusFlight(AbstractClientPlayer player, double motionX, double motionY, double motionZ, float yaw, float pitch, float ticks) {
double dist = Math.sqrt(motionX * motionX + motionZ * motionZ);
double angle = Math.atan2(motionY, dist);
if (!player.capabilities.isFlying) {
if (angle > 0) {
angle = 0;
} else {
angle /= 2;
return pony.getMetadata().getSize().getScaleFactor();
}
}
angle = MathUtil.clampLimit(angle, Math.PI / 3);
ponyModel.motionPitch = (float) Math.toDegrees(angle);
GlStateManager.rotate(ponyModel.motionPitch, 1, 0, 0);
float roll = (float)calculateRoll(player, motionX, motionY, motionZ);
roll = getPony().getMetadata().getInterpolator().interpolate("pegasusRoll", roll, 10);
GlStateManager.rotate((float)roll, 0, 0, 1);
}
//TODO: MC1.13 transformSwimming()
}

View file

@ -0,0 +1,17 @@
package com.minelittlepony.transformation;
import com.minelittlepony.model.AbstractPonyModel;
import net.minecraft.entity.EntityLivingBase;
public interface PonyPosture<T extends EntityLivingBase> {
PonyPosture<EntityLivingBase> ELYTRA = new PostureElytra();
PonyPosture<? extends EntityLivingBase> FLIGHT = new PostureFlight();
PonyPosture<EntityLivingBase> FALLING = new PostureFalling();
default boolean applies(EntityLivingBase entity) {
return true;
}
void transform(AbstractPonyModel model, T entity, double motionX, double motionY, double motionZ, float pitch, float yaw, float ticks);
}

View file

@ -0,0 +1,8 @@
package com.minelittlepony.transformation;
import com.minelittlepony.model.AbstractPonyModel;
import com.minelittlepony.model.BodyPart;
public interface PonyTransformation {
void transform(AbstractPonyModel model, BodyPart part);
}

View file

@ -0,0 +1,14 @@
package com.minelittlepony.transformation;
import com.minelittlepony.model.AbstractPonyModel;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.EntityLivingBase;
public class PostureElytra implements PonyPosture<EntityLivingBase> {
@Override
public void transform(AbstractPonyModel model, EntityLivingBase entity, double motionX, double motionY, double motionZ, float pitch, float yaw, float ticks) {
GlStateManager.rotate(90, 1, 0, 0);
GlStateManager.translate(0, entity.isSneaking() ? 0.2F : -1, 0);
}
}

View file

@ -0,0 +1,12 @@
package com.minelittlepony.transformation;
import com.minelittlepony.model.AbstractPonyModel;
import net.minecraft.entity.EntityLivingBase;
public class PostureFalling implements PonyPosture<EntityLivingBase> {
@Override
public void transform(AbstractPonyModel model, EntityLivingBase entity, double motionX, double motionY, double motionZ, float pitch, float yaw, float ticks) {
model.motionPitch = 0;
}
}

View file

@ -0,0 +1,67 @@
package com.minelittlepony.transformation;
import com.minelittlepony.model.AbstractPonyModel;
import com.minelittlepony.util.math.MathUtil;
import net.minecraft.client.entity.AbstractClientPlayer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.math.MathHelper;
public class PostureFlight implements PonyPosture<AbstractClientPlayer> {
@Override
public boolean applies(EntityLivingBase entity) {
return entity instanceof AbstractClientPlayer;
}
private double calculateRoll(AbstractClientPlayer player, double motionX, double motionY, double motionZ) {
// since model roll should probably be calculated from model rotation rather than entity rotation...
double roll = MathUtil.sensibleAngle(player.prevRenderYawOffset - player.renderYawOffset);
double horMotion = Math.sqrt(motionX * motionX + motionZ * motionZ);
float modelYaw = MathUtil.sensibleAngle(player.renderYawOffset);
// detecting that we're flying backwards and roll must be inverted
if (Math.abs(MathUtil.sensibleAngle((float) Math.toDegrees(Math.atan2(motionX, motionZ)) + modelYaw)) > 90) {
roll *= -1;
}
// ayyy magic numbers (after 5 - an approximation of nice looking coefficients calculated by hand)
// roll might be zero, in which case Math.pow produces +Infinity. Anything x Infinity = NaN.
double pow = roll != 0 ? Math.pow(Math.abs(roll), -0.191) : 0;
roll *= horMotion * 5 * (3.6884f * pow);
assert !Float.isNaN((float)roll);
return MathHelper.clamp(roll, -54, 54);
}
@Override
public void transform(AbstractPonyModel model, AbstractClientPlayer player, double motionX, double motionY, double motionZ, float pitch, float yaw, float ticks) {
double dist = Math.sqrt(motionX * motionX + motionZ * motionZ);
double angle = Math.atan2(motionY, dist);
if (!player.capabilities.isFlying) {
if (angle > 0) {
angle = 0;
} else {
angle /= 2;
}
}
angle = MathUtil.clampLimit(angle, Math.PI / 3);
model.motionPitch = (float) Math.toDegrees(angle);
GlStateManager.rotate(model.motionPitch, 1, 0, 0);
float roll = (float)calculateRoll(player, motionX, motionY, motionZ);
roll = model.getMetadata().getInterpolator().interpolate("pegasusRoll", roll, 10);
GlStateManager.rotate((float)roll, 0, 0, 1);
}
}

View file

@ -0,0 +1,40 @@
package com.minelittlepony.transformation;
import static net.minecraft.client.renderer.GlStateManager.scale;
import static net.minecraft.client.renderer.GlStateManager.translate;
import com.minelittlepony.model.AbstractPonyModel;
import com.minelittlepony.model.BodyPart;
public class TransformFoal implements PonyTransformation {
@Override
public void transform(AbstractPonyModel model, BodyPart part) {
if (model.isCrouching()) translate(0, -0.12F, 0);
if (model.isSleeping) translate(0, -1.48F, 0.25F);
if (model.isRiding) translate(0, -0.1F, 0);
switch (part) {
case NECK:
translate(0, 0.76F, 0);
scale(0.9F, 0.9F, 0.9F);
if (model.isCrouching()) translate(0, -0.01F, 0.15F);
break;
case HEAD:
translate(0, 0.76F, 0);
scale(0.9F, 0.9F, 0.9F);
break;
case BODY:
case TAIL:
translate(0, 0.76F, -0.04F);
scale(0.6F, 0.6F, 0.6F);
break;
case LEGS:
translate(0, 0.89F, 0);
scale(0.6F, 0.41F, 0.6F);
if (model.isCrouching()) translate(0, 0.12F, 0);
if (model.isGoingFast()) translate(0, -0.08F, 0);
break;
}
}
}

View file

@ -0,0 +1,38 @@
package com.minelittlepony.transformation;
import static net.minecraft.client.renderer.GlStateManager.scale;
import static net.minecraft.client.renderer.GlStateManager.translate;
import com.minelittlepony.model.AbstractPonyModel;
import com.minelittlepony.model.BodyPart;
public class TransformLarge implements PonyTransformation {
@Override
public void transform(AbstractPonyModel model, BodyPart part) {
if (model.isSleeping) translate(0, -0.98F, 0.2F);
switch (part) {
case NECK:
translate(0, -0.15F, -0.07F);
if (model.isCrouching()) translate(-0.03F, 0.16F, 0.07F);
break;
case HEAD:
translate(0, -0.17F, -0.04F);
if (model.isSleeping) translate(0, 0, -0.1F);
if (model.isCrouching()) translate(0, 0.15F, 0);
break;
case BODY:
translate(0, -0.2F, -0.04F);
scale(1.15F, 1.2F, 1.2F);
break;
case TAIL:
translate(0, -0.2F, 0.08F);
break;
case LEGS:
translate(0, -0.14F, 0);
scale(1.15F, 1.12F, 1.15F);
break;
}
}
}

View file

@ -0,0 +1,19 @@
package com.minelittlepony.transformation;
import static net.minecraft.client.renderer.GlStateManager.translate;
import com.minelittlepony.model.AbstractPonyModel;
import com.minelittlepony.model.BodyPart;
public class TransformNormal implements PonyTransformation {
@Override
public void transform(AbstractPonyModel model, BodyPart part) {
if (model.isSleeping) translate(0, -0.61F, 0.25F);
switch (part) {
case NECK:
if (model.isCrouching()) translate(-0.03F, 0.03F, 0.1F);
default:
}
}
}

View file

@ -0,0 +1,38 @@
package com.minelittlepony.transformation;
import static net.minecraft.client.renderer.GlStateManager.scale;
import static net.minecraft.client.renderer.GlStateManager.translate;
import com.minelittlepony.model.AbstractPonyModel;
import com.minelittlepony.model.BodyPart;
public class TransformTall implements PonyTransformation {
@Override
public void transform(AbstractPonyModel model, BodyPart part) {
if (model.isSleeping) translate(0, -0.5F, 0.25F);
switch (part) {
case NECK:
translate(0, -0.09F, -0.01F);
scale(1, 1.1F, 1);
if (model.isCrouching()) translate(-0.02F, -0.02F, 0.1F);
break;
case HEAD:
translate(0, -0.15F, 0.01F);
if (model.isCrouching()) translate(0, 0.05F, 0);
break;
case BODY:
translate(0, -0.1F, 0);
break;
case TAIL:
translate(0, -0.1F, 0);
break;
case LEGS:
translate(0, -0.25F, 0.03F);
scale(1, 1.18F, 1);
if (model.isGoingFast()) translate(0, 0.05F, 0);
break;
}
}
}

View file

@ -0,0 +1,7 @@
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
package com.minelittlepony.transformation;
import mcp.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;