Switched animation system to capabilities, added animated item example, fixed state passing in MultiModel.

This commit is contained in:
RainWarrior 2016-03-21 09:15:39 +03:00
parent 558348125d
commit 5f62404f8a
14 changed files with 338 additions and 99 deletions

View file

@ -8,7 +8,7 @@
public ResourceLocation func_188021_a(ItemStack p_188021_1_, World p_188021_2_, EntityLivingBase p_188021_3_) public ResourceLocation func_188021_a(ItemStack p_188021_1_, World p_188021_2_, EntityLivingBase p_188021_3_)
{ {
if (!this.field_188023_b.isEmpty()) if (!this.field_188023_b.isEmpty())
@@ -42,4 +43,18 @@ @@ -42,4 +43,23 @@
return null; return null;
} }
@ -25,5 +25,10 @@
+ } + }
+ } + }
+ return originalModel; + return originalModel;
+ }
+
+ public com.google.common.collect.ImmutableList<ItemOverride> getOverrides()
+ {
+ return com.google.common.collect.ImmutableList.copyOf(field_188023_b);
+ } + }
} }

View file

@ -57,7 +57,7 @@
Vec3d vec3d1 = vec3d.func_72441_c((double)f6 * d3, (double)f5 * d3, (double)f7 * d3); Vec3d vec3d1 = vec3d.func_72441_c((double)f6 * d3, (double)f5 * d3, (double)f7 * d3);
return p_77621_1_.func_147447_a(vec3d, vec3d1, p_77621_3_, !p_77621_3_, false); return p_77621_1_.func_147447_a(vec3d, vec3d1, p_77621_3_, !p_77621_3_, false);
} }
@@ -422,11 +431,588 @@ @@ -422,11 +431,606 @@
return false; return false;
} }
@ -641,12 +641,30 @@
+ { + {
+ return null; + return null;
+ } + }
+
+ public com.google.common.collect.ImmutableMap<String, net.minecraftforge.client.model.animation.ITimeValue> getAnimationParameters(final ItemStack stack, final World world, final EntityLivingBase entity)
+ {
+ com.google.common.collect.ImmutableMap.Builder<String, net.minecraftforge.client.model.animation.ITimeValue> builder = com.google.common.collect.ImmutableMap.builder();
+ for(ResourceLocation location : field_185051_m.func_148742_b())
+ {
+ final IItemPropertyGetter parameter = field_185051_m.func_82594_a(location);
+ builder.put(location.toString(), new net.minecraftforge.client.model.animation.ITimeValue()
+ {
+ public float apply(float input)
+ {
+ return parameter.func_185085_a(stack, world, entity);
+ }
+ });
+ }
+ return builder.build();
+ }
+
+ /* ======================================== FORGE END =====================================*/ + /* ======================================== FORGE END =====================================*/
+ +
public static void func_150900_l() public static void func_150900_l()
{ {
func_179214_a(Blocks.field_150348_b, (new ItemMultiTexture(Blocks.field_150348_b, Blocks.field_150348_b, new Function<ItemStack, String>() func_179214_a(Blocks.field_150348_b, (new ItemMultiTexture(Blocks.field_150348_b, Blocks.field_150348_b, new Function<ItemStack, String>()
@@ -935,6 +1521,10 @@ @@ -935,6 +1539,10 @@
private final float field_78011_i; private final float field_78011_i;
private final int field_78008_j; private final int field_78008_j;
@ -657,7 +675,7 @@
private ToolMaterial(int p_i1874_3_, int p_i1874_4_, float p_i1874_5_, float p_i1874_6_, int p_i1874_7_) private ToolMaterial(int p_i1874_3_, int p_i1874_4_, float p_i1874_5_, float p_i1874_6_, int p_i1874_7_)
{ {
this.field_78001_f = p_i1874_3_; this.field_78001_f = p_i1874_3_;
@@ -969,9 +1559,36 @@ @@ -969,9 +1577,36 @@
return this.field_78008_j; return this.field_78008_j;
} }

View file

@ -185,9 +185,7 @@ public class BlockStateLoader
IModel model = ModelLoaderRegistry.getModelOrLogError(part.getModelLocation(), "Unable to load block sub-model: \'" + part.getModelLocation()); IModel model = ModelLoaderRegistry.getModelOrLogError(part.getModelLocation(), "Unable to load block sub-model: \'" + part.getModelLocation());
IModelState partState = new ModelStateComposition(baseTr, part.getState()); models.put(entry.getKey(), Pair.<IModel, IModelState>of(runModelHooks(model, part.smooth, part.gui3d, part.uvLock, part.getTextures(), part.getCustomData()), part.getState()));
models.put(entry.getKey(), Pair.<IModel, IModelState>of(runModelHooks(model, part.smooth, part.gui3d, part.uvLock, part.getTextures(), part.getCustomData()), partState));
} }
return new MultiModel(getModelLocation(), hasBase ? base : null, baseTr, models.build()); return new MultiModel(getModelLocation(), hasBase ? base : null, baseTr, models.build());

View file

@ -28,6 +28,7 @@ import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms; import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType; import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.block.model.ItemModelGenerator; import net.minecraft.client.renderer.block.model.ItemModelGenerator;
import net.minecraft.client.renderer.block.model.ItemOverrideList;
import net.minecraft.client.renderer.block.model.ModelBakery; import net.minecraft.client.renderer.block.model.ModelBakery;
import net.minecraft.client.renderer.block.model.ModelBlock; import net.minecraft.client.renderer.block.model.ModelBlock;
import net.minecraft.client.renderer.block.model.ModelBlockDefinition; import net.minecraft.client.renderer.block.model.ModelBlockDefinition;
@ -57,6 +58,7 @@ import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.IRegistry; import net.minecraft.util.registry.IRegistry;
import net.minecraftforge.client.model.animation.Animation; import net.minecraftforge.client.model.animation.Animation;
import net.minecraftforge.client.model.animation.AnimationItemOverrideList;
import net.minecraftforge.client.model.animation.IAnimatedModel; import net.minecraftforge.client.model.animation.IAnimatedModel;
import net.minecraftforge.client.model.animation.IClip; import net.minecraftforge.client.model.animation.IClip;
import net.minecraftforge.client.model.animation.ModelBlockAnimation; import net.minecraftforge.client.model.animation.ModelBlockAnimation;
@ -497,17 +499,18 @@ public final class ModelLoader extends ModelBakery
return new ItemLayerModel(model).bake(perState, format, bakedTextureGetter); return new ItemLayerModel(model).bake(perState, format, bakedTextureGetter);
} }
if(isCustomRenderer(model)) return new BuiltInModel(transforms, model.createOverrides()); if(isCustomRenderer(model)) return new BuiltInModel(transforms, model.createOverrides());
return bakeNormal(model, perState, state.apply(Optional.<IModelPart>absent()).or(TRSRTransformation.identity()), newTransforms, format, bakedTextureGetter, uvlock); return bakeNormal(model, perState, state, newTransforms, format, bakedTextureGetter, uvlock);
} }
private IBakedModel bakeNormal(ModelBlock model, IModelState perState, final TRSRTransformation modelState, List<TRSRTransformation> newTransforms, final VertexFormat format, final Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter, boolean uvLocked) private IBakedModel bakeNormal(ModelBlock model, IModelState perState, final IModelState modelState, List<TRSRTransformation> newTransforms, final VertexFormat format, final Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter, boolean uvLocked)
{ {
final TRSRTransformation baseState = modelState.apply(Optional.<IModelPart>absent()).or(TRSRTransformation.identity());
TextureAtlasSprite particle = bakedTextureGetter.apply(new ResourceLocation(model.resolveTextureName("particle"))); TextureAtlasSprite particle = bakedTextureGetter.apply(new ResourceLocation(model.resolveTextureName("particle")));
SimpleBakedModel.Builder builder = (new SimpleBakedModel.Builder(model, model.createOverrides())).setTexture(particle); SimpleBakedModel.Builder builder = (new SimpleBakedModel.Builder(model, model.createOverrides())).setTexture(particle);
for(int i = 0; i < model.getElements().size(); i++) for(int i = 0; i < model.getElements().size(); i++)
{ {
BlockPart part = model.getElements().get(i); BlockPart part = model.getElements().get(i);
TRSRTransformation transformation = modelState; TRSRTransformation transformation = baseState;
if(newTransforms.get(i) != null) if(newTransforms.get(i) != null)
{ {
transformation = transformation.compose(newTransforms.get(i)); transformation = transformation.compose(newTransforms.get(i));
@ -525,13 +528,15 @@ public final class ModelLoader extends ModelBakery
} }
else else
{ {
builder.addFaceQuad(modelState.rotate(e.getValue().cullFace), makeBakedQuad(part, e.getValue(), textureatlassprite1, e.getKey(), transformation, uvLocked)); builder.addFaceQuad(baseState.rotate(e.getValue().cullFace), makeBakedQuad(part, e.getValue(), textureatlassprite1, e.getKey(), transformation, uvLocked));
} }
} }
} }
return new IPerspectiveAwareModel.MapWrapper(builder.makeBakedModel(), perState) return new IPerspectiveAwareModel.MapWrapper(builder.makeBakedModel(), perState)
{ {
private final ItemOverrideList overrides = new AnimationItemOverrideList(VanillaModelWrapper.this, modelState, format, bakedTextureGetter, super.getOverrides());
@Override @Override
public List<BakedQuad> getQuads(IBlockState state, EnumFacing side, long rand) public List<BakedQuad> getQuads(IBlockState state, EnumFacing side, long rand)
{ {
@ -550,6 +555,12 @@ public final class ModelLoader extends ModelBakery
} }
return super.getQuads(state, side, rand); return super.getQuads(state, side, rand);
}; };
@Override
public ItemOverrideList getOverrides()
{
return overrides;
}
}; };
} }

View file

@ -14,11 +14,15 @@ import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.IBakedModel; import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms; import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType; import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.block.model.ItemOverride;
import net.minecraft.client.renderer.block.model.ItemOverrideList; import net.minecraft.client.renderer.block.model.ItemOverrideList;
import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat; import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.FMLLog; import net.minecraftforge.fml.common.FMLLog;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
@ -28,6 +32,7 @@ import com.google.common.base.Function;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
// TODO: Switch to vanilla class, or to something similar // TODO: Switch to vanilla class, or to something similar
@ -36,15 +41,55 @@ public final class MultiModel implements IModel
{ {
private static final class Baked implements IPerspectiveAwareModel private static final class Baked implements IPerspectiveAwareModel
{ {
private final ResourceLocation location;
private final IBakedModel base; private final IBakedModel base;
private final ImmutableMap<String, IBakedModel> parts; private final ImmutableMap<String, IBakedModel> parts;
private final IBakedModel internalBase; private final IBakedModel internalBase;
private ImmutableMap<Optional<EnumFacing>, ImmutableList<BakedQuad>> quads; private ImmutableMap<Optional<EnumFacing>, ImmutableList<BakedQuad>> quads;
private final ImmutableMap<TransformType, Pair<Baked, TRSRTransformation>> transforms; private final ImmutableMap<TransformType, Pair<Baked, TRSRTransformation>> transforms;
private final ItemOverrideList overrides = new ItemOverrideList(Lists.<ItemOverride>newArrayList())
{
@Override
public IBakedModel handleItemState(IBakedModel originalModel, ItemStack stack, World world, EntityLivingBase entity)
{
if(originalModel != Baked.this)
{
return originalModel;
}
boolean dirty = false;
IBakedModel newBase = null;
if(base != null)
{
newBase = base.getOverrides().handleItemState(base, stack, world, entity);
if(base != newBase)
{
dirty = true;
}
}
ImmutableMap.Builder<String, IBakedModel> builder = ImmutableMap.builder();
for(Map.Entry<String, IBakedModel> entry : parts.entrySet())
{
IBakedModel newPart = entry.getValue().getOverrides().handleItemState(entry.getValue(), stack, world, entity);
builder.put(entry.getKey(), newPart);
if(entry.getValue() != newPart)
{
dirty = true;
}
}
if(dirty)
{
// TODO: caching?
return new Baked(location, newBase instanceof IPerspectiveAwareModel, newBase, builder.build());
}
return Baked.this;
}
};
public Baked(ResourceLocation location, boolean perspective, IBakedModel base, ImmutableMap<String, IBakedModel> parts) public Baked(ResourceLocation location, boolean perspective, IBakedModel base, ImmutableMap<String, IBakedModel> parts)
{ {
this.location = location;
this.base = base; this.base = base;
this.parts = parts; this.parts = parts;
@ -120,22 +165,22 @@ public final class MultiModel implements IModel
ImmutableList.Builder<BakedQuad> quads = ImmutableList.builder(); ImmutableList.Builder<BakedQuad> quads = ImmutableList.builder();
if (base != null) if (base != null)
{ {
quads.addAll(base.getQuads(null, face, 0)); quads.addAll(base.getQuads(state, face, 0));
} }
for (IBakedModel bakedPart : parts.values()) for (IBakedModel bakedPart : parts.values())
{ {
quads.addAll(bakedPart.getQuads(null, face, 0)); quads.addAll(bakedPart.getQuads(state, face, 0));
} }
builder.put(Optional.of(face), quads.build()); builder.put(Optional.of(face), quads.build());
} }
ImmutableList.Builder<BakedQuad> quads = ImmutableList.builder(); ImmutableList.Builder<BakedQuad> quads = ImmutableList.builder();
if (base != null) if (base != null)
{ {
quads.addAll(base.getQuads(null, null, 0)); quads.addAll(base.getQuads(state, null, 0));
} }
for (IBakedModel bakedPart : parts.values()) for (IBakedModel bakedPart : parts.values())
{ {
quads.addAll(bakedPart.getQuads(null, null, 0)); quads.addAll(bakedPart.getQuads(state, null, 0));
} }
builder.put(Optional.<EnumFacing>absent(), quads.build()); builder.put(Optional.<EnumFacing>absent(), quads.build());
this.quads = builder.build(); this.quads = builder.build();
@ -154,7 +199,7 @@ public final class MultiModel implements IModel
@Override @Override
public ItemOverrideList getOverrides() public ItemOverrideList getOverrides()
{ {
return ItemOverrideList.NONE; return overrides;
} }
} }
@ -217,7 +262,7 @@ public final class MultiModel implements IModel
for (Entry<String, Pair<IModel, IModelState>> entry : parts.entrySet()) for (Entry<String, Pair<IModel, IModelState>> entry : parts.entrySet())
{ {
Pair<IModel, IModelState> pair = entry.getValue(); Pair<IModel, IModelState> pair = entry.getValue();
mapBuilder.put(entry.getKey(), pair.getLeft().bake(pair.getRight(), format, bakedTextureGetter)); mapBuilder.put(entry.getKey(), pair.getLeft().bake(new ModelStateComposition(state, pair.getRight()), format, bakedTextureGetter));
} }
if(bakedBase == null && parts.isEmpty()) if(bakedBase == null && parts.isEmpty())

View file

@ -107,7 +107,7 @@ public enum Animation implements IResourceManagerReloadListener
return defaultModelBlockAnimation; return defaultModelBlockAnimation;
} }
ModelBlockAnimation mba = mbaGson.fromJson(new InputStreamReader(resource.getInputStream(), "UTF-8"), ModelBlockAnimation.class); ModelBlockAnimation mba = mbaGson.fromJson(new InputStreamReader(resource.getInputStream(), "UTF-8"), ModelBlockAnimation.class);
String json = mbaGson.toJson(mba); //String json = mbaGson.toJson(mba);
return mba; return mba;
} }
catch(IOException e) catch(IOException e)
@ -124,7 +124,7 @@ public enum Animation implements IResourceManagerReloadListener
private IResourceManager manager; private IResourceManager manager;
private final AnimationStateMachine missing = new AnimationStateMachine( protected final AnimationStateMachine missing = new AnimationStateMachine(
ImmutableMap.<String, ITimeValue>of(), ImmutableMap.<String, ITimeValue>of(),
ImmutableMap.of("missingno", (IClip)Clips.IdentityClip.instance), ImmutableMap.of("missingno", (IClip)Clips.IdentityClip.instance),
ImmutableList.of("missingno"), ImmutableList.of("missingno"),

View file

@ -0,0 +1,63 @@
package net.minecraftforge.client.model.animation;
import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ItemOverride;
import net.minecraft.client.renderer.block.model.ItemOverrideList;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.client.model.IModel;
import net.minecraftforge.client.model.IModelState;
import net.minecraftforge.client.model.ModelStateComposition;
import net.minecraftforge.common.model.animation.IAnimationStateMachine;
import com.google.common.base.Function;
public final class AnimationItemOverrideList extends ItemOverrideList
{
private final IModel model;
private final IModelState state;
private final VertexFormat format;
private final Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter;
public AnimationItemOverrideList(IModel model, IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter, ItemOverrideList overrides)
{
this(model, state, format, bakedTextureGetter, overrides.getOverrides());
}
public AnimationItemOverrideList(IModel model, IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter, List<ItemOverride> overrides)
{
super(overrides);
this.model = model;
this.state = state;
this.format = format;
this.bakedTextureGetter = bakedTextureGetter;
}
@Override
public IBakedModel handleItemState(IBakedModel originalModel, ItemStack stack, World world, EntityLivingBase entity)
{
if(stack.hasCapability(net.minecraftforge.client.model.animation.CapabilityAnimation.ANIMATION_CAPABILITY, null))
{
// TODO: caching?
IAnimationStateMachine asm = stack.getCapability(CapabilityAnimation.ANIMATION_CAPABILITY, null);
if(world == null)
{
world = entity.worldObj;
}
if(world == null)
{
world = Minecraft.getMinecraft().theWorld;
}
IModelState state = asm.apply(Animation.getWorldTime(world, Animation.getPartialTickTime())).getLeft();
return model.bake(new ModelStateComposition(state, this.state), format, bakedTextureGetter);
}
return originalModel;
}
}

View file

@ -14,9 +14,11 @@ import net.minecraft.entity.Entity;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.IModel; import net.minecraftforge.client.model.IModel;
import net.minecraftforge.client.model.IModelState; import net.minecraftforge.client.model.IModelState;
import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.client.model.pipeline.VertexLighterFlat; import net.minecraftforge.client.model.pipeline.VertexLighterFlat;
import net.minecraftforge.client.model.pipeline.VertexBufferConsumer; import net.minecraftforge.client.model.pipeline.VertexBufferConsumer;
@ -28,14 +30,14 @@ import org.lwjgl.opengl.GL11;
* Some quirks are still left, deprecated for the moment. * Some quirks are still left, deprecated for the moment.
*/ */
@Deprecated @Deprecated
public class AnimationModelBase<T extends Entity & IAnimationProvider> extends ModelBase implements IEventHandler<T> public class AnimationModelBase<T extends Entity> extends ModelBase implements IEventHandler<T>
{ {
private final VertexLighterFlat lighter; private final VertexLighterFlat lighter;
private final IModel model; private final ResourceLocation modelLocation;
public AnimationModelBase(IModel model, VertexLighterFlat lighter) public AnimationModelBase(ResourceLocation modelLocation, VertexLighterFlat lighter)
{ {
this.model = model; this.modelLocation = modelLocation;
this.lighter = lighter; this.lighter = lighter;
} }
@ -43,13 +45,14 @@ public class AnimationModelBase<T extends Entity & IAnimationProvider> extends M
@Override @Override
public void render(Entity entity, float limbSwing, float limbSwingSpeed, float timeAlive, float yawHead, float rotationPitch, float scale) public void render(Entity entity, float limbSwing, float limbSwingSpeed, float timeAlive, float yawHead, float rotationPitch, float scale)
{ {
if(!(entity instanceof IAnimationProvider)) if(!(entity.hasCapability(CapabilityAnimation.ANIMATION_CAPABILITY, null)))
{ {
throw new ClassCastException("AnimationModelBase expects IAnimationProvider"); return;
} }
Pair<IModelState, Iterable<Event>> pair = ((IAnimationProvider)entity).asm().apply(timeAlive / 20); Pair<IModelState, Iterable<Event>> pair = entity.getCapability(CapabilityAnimation.ANIMATION_CAPABILITY, null).apply(timeAlive / 20);
handleEvents((T)entity, timeAlive / 20, pair.getRight()); handleEvents((T)entity, timeAlive / 20, pair.getRight());
IModel model = ModelLoaderRegistry.getModelOrMissing(modelLocation);
IBakedModel bakedModel = model.bake(pair.getLeft(), DefaultVertexFormats.ITEM, ModelLoader.defaultTextureGetter()); IBakedModel bakedModel = model.bake(pair.getLeft(), DefaultVertexFormats.ITEM, ModelLoader.defaultTextureGetter());
BlockPos pos = new BlockPos(entity.posX, entity.posY + entity.height, entity.posZ); BlockPos pos = new BlockPos(entity.posX, entity.posY + entity.height, entity.posZ);

View file

@ -18,12 +18,16 @@ import org.apache.commons.lang3.tuple.Pair;
/** /**
* Generic TileEntitySpecialRenderer that works with the Forge model system and animations. * Generic TileEntitySpecialRenderer that works with the Forge model system and animations.
*/ */
public class AnimationTESR<T extends TileEntity & IAnimationProvider> extends FastTESR<T> implements IEventHandler<T> public class AnimationTESR<T extends TileEntity> extends FastTESR<T> implements IEventHandler<T>
{ {
protected static BlockRendererDispatcher blockRenderer; protected static BlockRendererDispatcher blockRenderer;
public void renderTileEntityFast(T te, double x, double y, double z, float partialTick, int breakStage, VertexBuffer renderer) public void renderTileEntityFast(T te, double x, double y, double z, float partialTick, int breakStage, VertexBuffer renderer)
{ {
if(!te.hasCapability(CapabilityAnimation.ANIMATION_CAPABILITY, null))
{
return;
}
if(blockRenderer == null) blockRenderer = Minecraft.getMinecraft().getBlockRendererDispatcher(); if(blockRenderer == null) blockRenderer = Minecraft.getMinecraft().getBlockRendererDispatcher();
BlockPos pos = te.getPos(); BlockPos pos = te.getPos();
IBlockAccess world = MinecraftForgeClient.getRegionRenderCache(te.getWorld(), pos); IBlockAccess world = MinecraftForgeClient.getRegionRenderCache(te.getWorld(), pos);
@ -38,7 +42,7 @@ public class AnimationTESR<T extends TileEntity & IAnimationProvider> extends Fa
if(exState.getUnlistedNames().contains(Properties.AnimationProperty)) if(exState.getUnlistedNames().contains(Properties.AnimationProperty))
{ {
float time = Animation.getWorldTime(getWorld(), partialTick); float time = Animation.getWorldTime(getWorld(), partialTick);
Pair<IModelState, Iterable<Event>> pair = te.asm().apply(time); Pair<IModelState, Iterable<Event>> pair = te.getCapability(CapabilityAnimation.ANIMATION_CAPABILITY, null).apply(time);
handleEvents(te, time, pair.getRight()); handleEvents(te, time, pair.getRight());
// TODO: caching? // TODO: caching?

View file

@ -0,0 +1,61 @@
package net.minecraftforge.client.model.animation;
import java.util.concurrent.Callable;
import net.minecraft.nbt.NBTBase;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.model.animation.IAnimationStateMachine;
public class CapabilityAnimation
{
@CapabilityInject(IAnimationStateMachine.class)
public static Capability<IAnimationStateMachine> ANIMATION_CAPABILITY = null;
public static void register()
{
CapabilityManager.INSTANCE.register(IAnimationStateMachine.class, new Capability.IStorage<IAnimationStateMachine>()
{
public NBTBase writeNBT(Capability<IAnimationStateMachine> capability, IAnimationStateMachine instance, EnumFacing side)
{
return null;
}
public void readNBT(Capability<IAnimationStateMachine> capability, IAnimationStateMachine instance, EnumFacing side, NBTBase nbt) {}
}, new Callable<IAnimationStateMachine>()
{
public IAnimationStateMachine call() throws Exception
{
return Animation.INSTANCE.missing;
}
});
}
public static class DefaultItemAnimationCapabilityProvider implements ICapabilityProvider
{
private final IAnimationStateMachine asm;
public DefaultItemAnimationCapabilityProvider(IAnimationStateMachine asm)
{
this.asm = asm;
}
public boolean hasCapability(Capability<?> capability, EnumFacing facing)
{
return capability == ANIMATION_CAPABILITY;
}
@SuppressWarnings("unchecked")
public <T> T getCapability(Capability<T> capability, EnumFacing facing)
{
if(capability == ANIMATION_CAPABILITY)
{
return (T)asm;
}
return null;
}
}
}

View file

@ -1,12 +0,0 @@
package net.minecraftforge.client.model.animation;
import net.minecraftforge.common.model.animation.IAnimationStateMachine;
/**
* Something that can provide the Animation State Machine, for example and Entity or a Block
*/
public interface IAnimationProvider
{
public IAnimationStateMachine asm();
}

View file

@ -49,7 +49,6 @@ import net.minecraftforge.client.model.b3d.B3DModel.Mesh;
import net.minecraftforge.client.model.b3d.B3DModel.Node; import net.minecraftforge.client.model.b3d.B3DModel.Node;
import net.minecraftforge.client.model.b3d.B3DModel.Texture; import net.minecraftforge.client.model.b3d.B3DModel.Texture;
import net.minecraftforge.client.model.b3d.B3DModel.Vertex; import net.minecraftforge.client.model.b3d.B3DModel.Vertex;
import net.minecraftforge.client.model.pipeline.LightUtil;
import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad; import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad;
import net.minecraftforge.common.property.IExtendedBlockState; import net.minecraftforge.common.property.IExtendedBlockState;
import net.minecraftforge.common.property.IUnlistedProperty; import net.minecraftforge.common.property.IUnlistedProperty;
@ -680,9 +679,16 @@ public final class B3DLoader implements ICustomModelLoader
if(quads == null) if(quads == null)
{ {
ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder(); ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();
generateQuads(builder, node, modelState); generateQuads(builder, node, this.state);
quads = builder.build(); quads = builder.build();
} }
// TODO: caching?
if(this.state != modelState)
{
ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();
generateQuads(builder, node, modelState);
return builder.build();
}
return quads; return quads;
} }

View file

@ -1,7 +1,5 @@
package net.minecraftforge.debug; package net.minecraftforge.debug;
import java.io.IOException;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockPistonBase; import net.minecraft.block.BlockPistonBase;
import net.minecraft.block.material.Material; import net.minecraft.block.material.Material;
@ -20,7 +18,9 @@ import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand; import net.minecraft.util.EnumHand;
@ -28,23 +28,17 @@ import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess; import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.client.model.IModel;
import net.minecraftforge.client.model.IModelState;
import net.minecraftforge.client.model.IRetexturableModel;
import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.client.model.ModelProcessingHelper;
import net.minecraftforge.client.model.MultiModel;
import net.minecraftforge.client.model.TRSRTransformation;
import net.minecraftforge.client.model.animation.Animation; import net.minecraftforge.client.model.animation.Animation;
import net.minecraftforge.client.model.animation.AnimationModelBase;
import net.minecraftforge.client.model.animation.AnimationTESR; import net.minecraftforge.client.model.animation.AnimationTESR;
import net.minecraftforge.client.model.animation.CapabilityAnimation;
import net.minecraftforge.client.model.animation.Event; import net.minecraftforge.client.model.animation.Event;
import net.minecraftforge.client.model.animation.IAnimationProvider;
import net.minecraftforge.client.model.animation.ITimeValue; import net.minecraftforge.client.model.animation.ITimeValue;
import net.minecraftforge.client.model.animation.TimeValues.VariableValue; import net.minecraftforge.client.model.animation.TimeValues.VariableValue;
import net.minecraftforge.client.model.b3d.B3DLoader; import net.minecraftforge.client.model.b3d.B3DLoader;
import net.minecraftforge.client.model.pipeline.VertexLighterSmoothAo; import net.minecraftforge.client.model.pipeline.VertexLighterSmoothAo;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.model.animation.IAnimationStateMachine; import net.minecraftforge.common.model.animation.IAnimationStateMachine;
import net.minecraftforge.common.property.ExtendedBlockState; import net.minecraftforge.common.property.ExtendedBlockState;
import net.minecraftforge.common.property.IUnlistedProperty; import net.minecraftforge.common.property.IUnlistedProperty;
@ -60,8 +54,6 @@ import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.registry.EntityRegistry; import net.minecraftforge.fml.common.registry.EntityRegistry;
import net.minecraftforge.fml.common.registry.GameRegistry; import net.minecraftforge.fml.common.registry.GameRegistry;
import org.apache.commons.lang3.tuple.Pair;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
@Mod(modid = ModelAnimationDebug.MODID, version = ModelAnimationDebug.VERSION) @Mod(modid = ModelAnimationDebug.MODID, version = ModelAnimationDebug.VERSION)
@ -156,6 +148,14 @@ public class ModelAnimationDebug
} }
return true; return true;
} }
}, null, blockName);
GameRegistry.registerItem(new ItemBlock(GameRegistry.findBlock(MODID, blockName))
{
@Override
public ICapabilityProvider initCapabilities(ItemStack stack, NBTTagCompound nbt)
{
return new ItemAnimationHolder();
}
}, blockName); }, blockName);
GameRegistry.registerTileEntity(Chest.class, MODID + ":" + "tile_" + blockName); GameRegistry.registerTileEntity(Chest.class, MODID + ":" + "tile_" + blockName);
} }
@ -192,6 +192,7 @@ public class ModelAnimationDebug
EntityRegistry.registerModEntity(EntityChest.class, entityName, 0, ModelAnimationDebug.instance, 64, 20, true, 0xFFAAAA00, 0xFFDDDD00); EntityRegistry.registerModEntity(EntityChest.class, entityName, 0, ModelAnimationDebug.instance, 64, 20, true, 0xFFAAAA00, 0xFFDDDD00);
RenderingRegistry.registerEntityRenderingHandler(EntityChest.class, new IRenderFactory<EntityChest>() RenderingRegistry.registerEntityRenderingHandler(EntityChest.class, new IRenderFactory<EntityChest>()
{ {
@SuppressWarnings("deprecation")
public Render<EntityChest> createRenderFor(RenderManager manager) public Render<EntityChest> createRenderFor(RenderManager manager)
{ {
/*model = ModelLoaderRegistry.getModel(new ResourceLocation(ModelLoaderRegistryDebug.MODID, "block/chest.b3d")); /*model = ModelLoaderRegistry.getModel(new ResourceLocation(ModelLoaderRegistryDebug.MODID, "block/chest.b3d"));
@ -203,25 +204,8 @@ public class ModelAnimationDebug
{ {
model = ((IModelCustomData)model).process(ImmutableMap.of("mesh", "[\"Base\", \"Lid\"]")); model = ((IModelCustomData)model).process(ImmutableMap.of("mesh", "[\"Base\", \"Lid\"]"));
}*/ }*/
IModel base = ModelLoaderRegistry.getModelOrMissing(new ResourceLocation(ModelAnimationDebug.MODID, "block/engine")); ResourceLocation location = new ModelResourceLocation(new ResourceLocation(MODID, blockName), "entity");
IModel ring = ModelLoaderRegistry.getModelOrMissing(new ResourceLocation(ModelAnimationDebug.MODID, "block/engine_ring")); return new RenderLiving<EntityChest>(manager, new net.minecraftforge.client.model.animation.AnimationModelBase<EntityChest>(location, new VertexLighterSmoothAo(Minecraft.getMinecraft().getBlockColors()))
ImmutableMap<String, String> textures = ImmutableMap.of(
"base", "blocks/stone",
"front", "blocks/log_oak",
"chamber", "blocks/redstone_block",
"trunk", "blocks/end_stone"
);
base = ModelProcessingHelper.retexture(base, textures);
ring = ModelProcessingHelper.retexture(base, textures);
IModel model = new MultiModel(
new ResourceLocation(ModelAnimationDebug.MODID, "builtin/engine"),
ring,
TRSRTransformation.identity(),
ImmutableMap.of(
"base", Pair.<IModel, IModelState>of(base, TRSRTransformation.identity())
)
);
return new RenderLiving<EntityChest>(manager, new AnimationModelBase<EntityChest>(model, new VertexLighterSmoothAo(Minecraft.getMinecraft().getBlockColors()))
{ {
@Override @Override
public void handleEvents(EntityChest chest, float time, Iterable<Event> pastEvents) public void handleEvents(EntityChest chest, float time, Iterable<Event> pastEvents)
@ -246,10 +230,34 @@ public class ModelAnimationDebug
} }
private static class ItemAnimationHolder implements ICapabilityProvider
{
private final VariableValue cycleLength = new VariableValue(4);
private final IAnimationStateMachine asm = proxy.load(new ResourceLocation(MODID.toLowerCase(), "asms/block/engine.json"), ImmutableMap.<String, ITimeValue>of(
"cycle_length", cycleLength
));
public boolean hasCapability(Capability<?> capability, EnumFacing facing)
{
return capability == CapabilityAnimation.ANIMATION_CAPABILITY;
}
@SuppressWarnings("unchecked")
public <T> T getCapability(Capability<T> capability, EnumFacing facing)
{
if(capability == CapabilityAnimation.ANIMATION_CAPABILITY)
{
return (T)asm;
}
return null;
}
}
@EventHandler @EventHandler
public void preInit(FMLPreInitializationEvent event) { proxy.preInit(event); } public void preInit(FMLPreInitializationEvent event) { proxy.preInit(event); }
public static class Chest extends TileEntity implements IAnimationProvider public static class Chest extends TileEntity
{ {
private final IAnimationStateMachine asm; private final IAnimationStateMachine asm;
private final VariableValue cycleLength = new VariableValue(4); private final VariableValue cycleLength = new VariableValue(4);
@ -319,25 +327,37 @@ public class ModelAnimationDebug
} }
} }
public IAnimationStateMachine asm() @Override
public boolean hasCapability(Capability<?> capability, EnumFacing side)
{ {
return asm; if(capability == CapabilityAnimation.ANIMATION_CAPABILITY)
{
return true;
}
return super.hasCapability(capability, side);
}
@SuppressWarnings("unchecked")
@Override
public <T> T getCapability(Capability<T> capability, EnumFacing side)
{
if(capability == CapabilityAnimation.ANIMATION_CAPABILITY)
{
return (T)asm;
}
return super.getCapability(capability, side);
} }
} }
public static class EntityChest extends EntityLiving implements IAnimationProvider public static class EntityChest extends EntityLiving
{ {
private final IAnimationStateMachine asm; private final IAnimationStateMachine asm;
private VariableValue cycleLength; private final VariableValue cycleLength = new VariableValue(getHealth() / 5);
public EntityChest(World world) public EntityChest(World world)
{ {
super(world); super(world);
setSize(1, 1); setSize(1, 1);
if(cycleLength == null)
{
cycleLength = new VariableValue(getHealth() / 5);
}
asm = proxy.load(new ResourceLocation(MODID.toLowerCase(), "asms/block/engine.json"), ImmutableMap.<String, ITimeValue>of( asm = proxy.load(new ResourceLocation(MODID.toLowerCase(), "asms/block/engine.json"), ImmutableMap.<String, ITimeValue>of(
"cycle_length", cycleLength "cycle_length", cycleLength
)); ));
@ -348,25 +368,15 @@ public class ModelAnimationDebug
// TODO Auto-generated method stub // TODO Auto-generated method stub
} }
public IAnimationStateMachine asm() @Override
public void onEntityUpdate()
{ {
return asm; super.onEntityUpdate();
} if(worldObj.isRemote && cycleLength != null)
// FIXME update health
/*@Override
public void func_184206_a(DataParameter<?> key)
{ {
super.func_184206_a(key);
if(field_184632_c.equals(key)) // health
{
if(cycleLength == null)
{
cycleLength = new VariableValue(0);
}
cycleLength.setValue(getHealth() / 5); cycleLength.setValue(getHealth() / 5);
} }
}*/ }
@Override @Override
protected void applyEntityAttributes() protected void applyEntityAttributes()
@ -374,6 +384,27 @@ public class ModelAnimationDebug
super.applyEntityAttributes(); super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(60); this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(60);
} }
@Override
public boolean hasCapability(Capability<?> capability, EnumFacing side)
{
if(capability == CapabilityAnimation.ANIMATION_CAPABILITY)
{
return true;
}
return super.hasCapability(capability, side);
}
@SuppressWarnings("unchecked")
@Override
public <T> T getCapability(Capability<T> capability, EnumFacing side)
{
if(capability == CapabilityAnimation.ANIMATION_CAPABILITY)
{
return (T)asm;
}
return super.getCapability(capability, side);
}
} }
} }

View file

@ -43,6 +43,12 @@
}*/ }*/
"model": "forgedebugmodelanimation:engine_ring" "model": "forgedebugmodelanimation:engine_ring"
} }
} },
"entity": [{
"model": "forgedebugmodelanimation:engine",
"submodel": {
"ring": { "model": "forgedebugmodelanimation:engine_ring" }
}
}]
} }
} }