From 5445f9632700385b26fc7c320b32b84dbf4570b7 Mon Sep 17 00:00:00 2001 From: RainWarrior Date: Fri, 13 May 2016 12:46:34 +0300 Subject: [PATCH] Extended Animation State Machine format to allow multiple transitions from one state. --- .../common/animation/TimeValues.java | 2 +- .../animation/AnimationStateMachine.java | 97 +++++++++++++++++-- .../asms/block/engine.json | 2 +- 3 files changed, 89 insertions(+), 12 deletions(-) diff --git a/src/main/java/net/minecraftforge/common/animation/TimeValues.java b/src/main/java/net/minecraftforge/common/animation/TimeValues.java index 74811384b..d1a2b7ea7 100644 --- a/src/main/java/net/minecraftforge/common/animation/TimeValues.java +++ b/src/main/java/net/minecraftforge/common/animation/TimeValues.java @@ -332,7 +332,7 @@ public final class TimeValues if(SimpleExprValue.opsPattern.matcher(type).matches()) { ImmutableList.Builder builder = ImmutableList.builder(); - while(in.peek() != JsonToken.END_ARRAY) + while(in.hasNext()) { builder.add(read(in)); } diff --git a/src/main/java/net/minecraftforge/common/model/animation/AnimationStateMachine.java b/src/main/java/net/minecraftforge/common/model/animation/AnimationStateMachine.java index 6418b0c5c..c7c1ef853 100644 --- a/src/main/java/net/minecraftforge/common/model/animation/AnimationStateMachine.java +++ b/src/main/java/net/minecraftforge/common/model/animation/AnimationStateMachine.java @@ -2,8 +2,19 @@ package net.minecraftforge.common.model.animation; import java.io.IOException; import java.io.InputStreamReader; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.Map; +import java.util.Set; import java.util.concurrent.TimeUnit; +import com.google.common.base.Supplier; +import com.google.common.collect.*; +import com.google.gson.*; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; import net.minecraft.client.resources.IResource; import net.minecraft.client.resources.IResourceManager; import net.minecraft.util.ResourceLocation; @@ -25,12 +36,6 @@ import com.google.common.base.Predicate; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonParseException; import com.google.gson.annotations.SerializedName; public final class AnimationStateMachine implements IAnimationStateMachine @@ -38,7 +43,7 @@ public final class AnimationStateMachine implements IAnimationStateMachine private final ImmutableMap parameters; private final ImmutableMap clips; private final ImmutableList states; - private final ImmutableMap transitions; + private final ImmutableMultimap transitions; @SerializedName("start_state") private final String startState; @@ -58,7 +63,25 @@ public final class AnimationStateMachine implements IAnimationStateMachine } }); + @Deprecated public AnimationStateMachine(ImmutableMap parameters, ImmutableMap clips, ImmutableList states, ImmutableMap transitions, String startState) + { + this(parameters, clips, states, ImmutableMultimap.copyOf(Multimaps.newSetMultimap(Maps.transformValues(transitions, new Function>() + { + public Collection apply(String input) + { + return ImmutableSet.of(input); + } + }), new Supplier>() + { + public Set get() + { + return Sets.newHashSet(); + } + })), startState); + } + + public AnimationStateMachine(ImmutableMap parameters, ImmutableMap clips, ImmutableList states, ImmutableMultimap transitions, String startState) { this.parameters = parameters; this.clips = clips; @@ -148,7 +171,7 @@ public final class AnimationStateMachine implements IAnimationStateMachine { throw new IllegalStateException("unknown state: " + newState); } - if(!transitions.get(currentStateName).equals(newState)) + if(!transitions.containsEntry(currentStateName, newState)) { throw new IllegalArgumentException("no transition from current clip \"" + currentStateName + "\" to the clip \"" + newState + "\" found."); } @@ -208,7 +231,7 @@ public final class AnimationStateMachine implements IAnimationStateMachine ImmutableMap.of(), ImmutableMap.of("missingno", (IClip)Clips.IdentityClip.INSTANCE), ImmutableList.of("missingno"), - ImmutableMap.of(), + ImmutableMultimap.of(), "missingno"); static @@ -216,7 +239,7 @@ public final class AnimationStateMachine implements IAnimationStateMachine missing.initialize(); } - public static final AnimationStateMachine getMissing() + public static AnimationStateMachine getMissing() { return missing; } @@ -257,8 +280,62 @@ public final class AnimationStateMachine implements IAnimationStateMachine .registerTypeAdapterFactory(Clips.CommonClipTypeAdapterFactory.INSTANCE) //.registerTypeAdapterFactory(ClipProviders.CommonClipProviderTypeAdapterFactory.INSTANCE) .registerTypeAdapterFactory(TimeValues.CommonTimeValueTypeAdapterFactory.INSTANCE) + .registerTypeAdapterFactory(TransitionsAdapterFactory.INSTANCE) .setPrettyPrinting() .enableComplexMapKeySerialization() .disableHtmlEscaping() .create(); + + private enum TransitionsAdapterFactory implements TypeAdapterFactory + { + INSTANCE; + + @SuppressWarnings("unchecked") + public TypeAdapter create(Gson gson, TypeToken type) + { + if(type.getRawType() != ImmutableMultimap.class || !(type.getType() instanceof ParameterizedType)) + { + return null; + } + final Type[] typeArguments = ((ParameterizedType) type.getType()).getActualTypeArguments(); + if(typeArguments.length != 2 || typeArguments[0] != String.class || typeArguments[1] != String.class) + { + return null; + } + final TypeAdapter>> mapAdapter = gson.getAdapter(new TypeToken>>(){}); + final TypeAdapter> collectionAdapter = gson.getAdapter(new TypeToken>(){}); + return (TypeAdapter)new TypeAdapter>() + { + @Override + public void write(JsonWriter out, ImmutableMultimap value) throws IOException + { + mapAdapter.write(out, value.asMap()); + } + + @Override + public ImmutableMultimap read(JsonReader in) throws IOException + { + ImmutableMultimap.Builder builder = ImmutableMultimap.builder(); + in.beginObject(); + while(in.hasNext()) + { + String key = in.nextName(); + switch(in.peek()) + { + case STRING: + builder.put(key, in.nextString()); + break; + case BEGIN_ARRAY: + builder.putAll(key, collectionAdapter.read(in)); + break; + default: + throw new JsonParseException("Expected String or Array, got " + in.peek()); + } + } + in.endObject(); + return builder.build(); + } + }; + } + } } diff --git a/src/test/resources/assets/forgedebugmodelanimation/asms/block/engine.json b/src/test/resources/assets/forgedebugmodelanimation/asms/block/engine.json index 8ee1f8cdd..558cb24f8 100644 --- a/src/test/resources/assets/forgedebugmodelanimation/asms/block/engine.json +++ b/src/test/resources/assets/forgedebugmodelanimation/asms/block/engine.json @@ -18,7 +18,7 @@ ], "transitions": { "default": "starting", - "starting": "moving", + "starting": [ "moving" ], "moving": "stopping", "stopping": "default" },