Blitz3D+ Command Reference

ExtractAnimSeq ( entity,first_frame,last_frame[,anim_seq] )

Parameters

entity - handle of an animated entity

first_frame - first frame of the range to copy

last_frame - last frame of the range to copy

anim_seq (optional) - sequence to copy the frames from; 0 (default)

Description

Copies a range of frames from an animation sequence into a new sequence, and returns its number.

Plenty of characters ship as one long take: frames 0-30 are the idle, 31-60 the walk, 61-80 the attack, all crammed into a single animation. ExtractAnimSeq is how you carve that take into the separate clips your game actually wants to play. Slice each range out once during setup, keep the numbers it returns, and from then on you can Animate them independently.

The new clip is appended to the end of the entity's sequence list, so CountAnimSeqs goes up by one and the returned number is the last valid sequence. Its length is last_frame minus first_frame - pulling frames 5 to 15 out of a walk gives you a 10-frame clip. The original sequence is untouched, and any animation events that fall inside the range come along, retimed so they still fire at the right moment in the new clip.

The new sequence has no name. FindAnimSeq will never find it and AnimSeqName returns an empty string for it, so store the number ExtractAnimSeq gave you - it is the only handle you get.

One trap to watch: if the arguments do not make sense - a sequence number that does not exist, a negative first frame, or a last frame before the first - nothing is added, but the call still returns the number of the last existing sequence rather than -1. If bad frame ranges are a real possibility in your code, compare CountAnimSeqs before and after the call to be sure a clip was actually created.

See also: AddAnimSeq, CountAnimSeqs, AnimSeqName, LoadAnimSeq, Animate, SetAnimTime.

Example

; ExtractAnimSeq Example
; ----------------------

Graphics3D 640,480,0,2
SetBuffer BackBuffer()

camera=CreateCamera()
PositionEntity camera,0,2,-6
RotateEntity camera,12,0,0

light=CreateLight()
RotateEntity light,45,45,0

; A grassy paddock for the fox to roam
ground=CreatePlane()
EntityTexture ground,LoadTexture("media/MossyGround.BMP")

fox=LoadAnimMesh("../../../samples/glTF/assets/Fox/Fox.glb")
If fox=0 Then RuntimeError "Could not load Fox.glb: "+ModelLoadError()

; Shrink the fox to game scale (the file is modelled about 100 units tall)
FitMesh fox,-0.8,0,-0.8,1.6,1.6,1.6,True

walk=FindAnimSeq(fox,"Walk")
seqs_before=CountAnimSeqs(fox)

; Carve frames 5 to 15 out of the Walk clip into a brand new sequence -
; the sort of thing you do when one long take holds several game moves
snippet=ExtractAnimSeq(fox,5,15,walk)
seqs_after=CountAnimSeqs(fox)

seq=walk
Animate fox,1,0.6,seq

While Not KeyDown(1)

    ; Space swaps between the whole Walk clip and the extracted snippet
    If KeyHit(57)
        If seq=walk
            seq=snippet
        Else
            seq=walk
        EndIf
        Animate fox,1,0.6,seq
    EndIf

    UpdateWorld

    ; Arrow keys move the camera
    If KeyDown(200) Then MoveEntity camera,0,0,0.1
    If KeyDown(208) Then MoveEntity camera,0,0,-0.1
    If KeyDown(203) Then TurnEntity camera,0,1,0
    If KeyDown(205) Then TurnEntity camera,0,-1,0

    RenderWorld

    Text 0,0,"Space: full Walk / extracted snippet   Arrows: camera   Esc: exit"
    Text 0,20,"ExtractAnimSeq(fox,5,15,"+walk+") returned sequence "+snippet
    Text 0,40,"CountAnimSeqs went from "+seqs_before+" to "+seqs_after
    Text 0,60,"Playing sequence "+seq+"   AnimLength "+AnimLength(fox)

    ; Extracted clips are born nameless - name lookups will not find them
    Text 0,80,"AnimSeqName$ of the snippet is "+Chr$(34)+AnimSeqName$(fox,snippet)+Chr$(34)

    Flip

Wend

End

Index