1. Eugene Veretennikov
  2. spinehx

Commits

Eugene Veretennikov  committed 8901878 Merge

Merge pull request #4 from bendmorris/master

Implementing DrawOrderTimeline

  • Participants
  • Parent commits 8194364, 105488b
  • Branches default

Comments (0)

Files changed (4)

File src/spinehx/Animation.hx

View file
  • Ignore whitespace
     }
 }
 
+
+class DrawOrderTimeline implements Timeline {
+    private var frames:Vector<Float>;
+    private var drawOrders:Vector<Vector<Int>>;
+    
+    public function new (frameCount:Int) {
+        frames = new Vector(frameCount);
+        drawOrders = new Vector(frameCount);
+    }
+    
+    public function getFrameCount():Int {
+        return frames.length;
+    }
+    
+    public function getFrames():Vector<Float> {
+        return frames;
+    }
+    
+    public function getDrawOrders():Vector<Vector<Int>> {
+        return drawOrders;
+    }
+    
+    /** Sets the time of the specified keyframe.
+     * @param drawOrder May be null to use bind pose draw order. */
+    public function setFrame(frameIndex:Int, time:Float, drawOrder:Vector<Int>) {
+        frames[frameIndex] = time;
+        drawOrders[frameIndex] = drawOrder;
+    }
+
+    public function apply(skeleton:Skeleton, time:Float, alpha:Float) {
+        var frames = this.frames;
+        if (time < frames[0]) return; // Time is before first frame.
+        
+        var frameIndex:Int;
+        if (time >= frames[frames.length - 1]) // Time is after last frame.
+            frameIndex = frames.length - 1;
+        else
+            frameIndex = Animation.binarySearch(frames, time, 1) - 1;
+        
+        var slots:Array<Slot> = skeleton.slots;
+        var drawOrderToSetupIndex:Vector<Int> = drawOrders[frameIndex];
+        if (drawOrderToSetupIndex == null) {
+            for (i in 0 ... slots.length)
+                skeleton.drawOrder[i] = slots[i];
+        } else {
+            for (i in 0 ... drawOrderToSetupIndex.length)
+                skeleton.drawOrder[i] = slots[drawOrderToSetupIndex[i]];
+        }
+    }
+}

File src/spinehx/AnimationStateData.hx

View file
  • Ignore whitespace
 
 /** Stores mixing times between animations. */
 class AnimationStateData {
+    public var defaultMixTime:Float=0;
+    
 	private var skeletonData:SkeletonData;
 	var animationToMixTime:Map<String, Null<Float>> ;
 
 	public function getMix (_from:Animation, _to:Animation):Float {
 		var id = makeId(_from, _to);
 		var time:Null<Float> = animationToMixTime.get(id);
-		if (time == null) return 0;
+		if (time == null) return defaultMixTime;
 		return time;
 	}
 

File src/spinehx/JsonUtils.hx

View file
  • Ignore whitespace
     public static function getInt(node:JsonNode, field:String):Int {
         return cast Reflect.getProperty(node, field);
     }
-
+    public static function getFlt(node:JsonNode, field:String):Float {
+        return cast Reflect.getProperty(node, field);
+    }
     public static function getStr(node:JsonNode, field:String):String {
         return cast Reflect.getProperty(node, field);
     }

File src/spinehx/SkeletonJson.hx

View file
  • Ignore whitespace
 import spinehx.attachments.AtlasAttachmentLoader;
 import spinehx.atlas.TextureAtlas;
 import spinehx.JsonUtils;
+import haxe.ds.Vector;
 using spinehx.JsonUtils;
 
 class SkeletonJson {
                 }
             }
         }
-
+        
+        var drawOrdersMap:JsonNode = map.getNode("draworder");
+        if (drawOrdersMap != null) {
+            var timeline:DrawOrderTimeline = new DrawOrderTimeline(drawOrdersMap.length);
+            var slotCount:Int = skeletonData.slots.length;
+            var frameIndex:Int = 0;
+            for (drawOrderMap in cast(drawOrdersMap, Array<JsonNode>)) {
+                var drawOrder:Vector<Int> = null;
+                var offsets:JsonNode = drawOrderMap.getNode("offsets");
+                if (offsets != null) {
+                    drawOrder = new Vector(slotCount);
+                    for (i in 0 ... slotCount) {
+                        drawOrder[slotCount - i - 1] = -1;
+                    }
+                    var unchanged:Vector<Int> = new Vector(cast (slotCount - offsets.fields().length));
+                    var originalIndex:Int = 0, unchangedIndex:Int = 0;
+                    for (offsetMap in cast(offsets, Array<JsonNode>)) {
+                        var slotIndex:Int = skeletonData.findSlotIndex(offsetMap.getStr("slot"));
+                        if (slotIndex == -1) throw new SerializationException("Slot not found: " + offsetMap.getString("slot"));
+                        // Collect unchanged items.
+                        while (originalIndex != slotIndex)
+                            unchanged[unchangedIndex++] = originalIndex++;
+                        // Set changed items.
+                        drawOrder[originalIndex + offsetMap.getInt("offset")] = originalIndex++;
+                    }
+                    // Collect remaining unchanged items.
+                    while (originalIndex < slotCount)
+                        unchanged[unchangedIndex++] = originalIndex++;
+                    // Fill in unchanged items.
+                    for (i in 0 ... slotCount) {
+                        var j = slotCount - i - 1;
+                        if (drawOrder[j] == -1) drawOrder[j] = unchanged[--unchangedIndex];
+                    }
+                }
+                timeline.setFrame(frameIndex++, drawOrderMap.getFlt("time"), drawOrder);
+            }
+            timelines.push(timeline);
+            duration = Math.max(duration, timeline.getFrames()[timeline.getFrameCount() - 1]);
+        }
+        
         //timelines.shrink();
         skeletonData.addAnimation(new Animation(name, timelines, duration));
     }