Making a MaxGUI Application: StripAnimMakerLite Part 12 - Saving and Loading Animation Strips
(c) Assari Feb 5 2005

We've finally come to the last tutorial where we now are going to add the final functionality, saving and loading animation strips. I will also add a BlitzMax application which will allow us to test that our animation strip is working properly.

New Additions to Part 1 - Variable Definitions

No new variables required here.

New Additions to Part 2 - Gadget Creation Block

We do not need any new gadget but we do have to modify our CreateMenu function to add in new menu items for loading and saving animation strips

New Additions to Part 3 - MAIN LOOP

We do not need anything new here

New Additions to Part 4 - Function Definitions

In this block we need to do the following
Function CreateMenu()

We need to add in the two new menus, one for saving and one for loading:- 
    Function CreateMenus:Int()

  Local FileMenu:TGadget=CreateMenu("File",200,MyWindow)
  CreateMenu("Exit",210,FileMenu,KEY_F4,MODIFIER_OPTION)
  CreateMenu("Open",220,FileMenu)

  ToolMenu:TGadget=CreateMenu("AnimTool",300,MyWindow)
  CreateMenu("Toggle Animation",310,ToolMenu)
  CreateMenu("Clear Animation",320,ToolMenu)
  CreateMenu("Cut",330,ToolMenu)
  PasteMenuAfter:TGadget=CreateMenu("Paste After",340,ToolMenu)
  PasteMenuBefore:TGadget=CreateMenu("Before",350,ToolMenu)
  CreateMenu("Save Animation",360,ToolMenu)
  CreateMenu("Load Animation",370,ToolMenu)

  DisableMenu(PasteMenuAfter)
  DisableMenu(PasteMenuBefore)
 
  UpdateWindowMenu MyWindow

End Function



Function Process_MenuActionEvent

We now have to add in the 2 cases to handle the loading and saving functions:-
    Function Process_MenuActionEvent:Int()

 Select EventData()

     Case 210 'Exit or ALT-F4
       End

     Case 220 'File Open
       LoadCanvasImage("")

    Case 310    'Toggle Animation
        AnimFlag= True ~ AnimFlag
       
    Case 320 ;AnimClearAll
    Case 330 ;AnimListPtr=AnimCut()
    Case 340 ;AnimPaste(0)
    Case 350 ;AnimPaste(1)
    Case 360 ;SaveAnimation()
    Case 370 ;LoadAnimation()

  End Select

End Function



Function SaveAnimation()

What this function does is collect all the individual pixmaps which were in the Animation List into a "long" strip temporary pixmap and then save that whole tmp pixmap into a png file, retaining the transparency attribute.
    Function SaveAnimation:Int()

 Local AnimCount:Int=CountList(AnimList)
 If AnimCount=0
    Notify "Nothing to Save"
    Return -1
 EndIf
 
 Local Tmp:TPixmap=CreatePixmap:TPixMap(AnimSize*AnimCount,AnimSize,PixmapFormat(PixMap1))
 Local i:Int=0
 For Local p:TPixmap=EachIn AnimList
    For Local jx:Int=0 To AnimSize-1
     For Local jy:Int=0 To AnimSize-1
        Local argb:Int=ReadPixel(P,jx,jy)
        WritePixel(Tmp,jx+i*(AnimSize),jy,argb)
     Next
    Next
    i=i+1
 Next

 Local file:String=RequestFile("File to Save","png",True)
 If file>"" SavePixmapPNG(Tmp,file)

End Function



Function LoadAnimation()

This function requests for an image file to load, then loads the image file into a pixmap. This pixmap is then broken down into our square animation images and added to our Animation Strip List.

The global variables, xsize,ysize, AnimSize and AnimListPtr are updated accordingly.
    Function LoadAnimation:Int()

  Local file:String=RequestFile("Load An Animation Strip","Image Files:png,jpg,bmp")
  If file>"" Then
    Local PixImg:TPixmap=LoadPixmap(file)
    If PixImg=Null Then Return -1
    ClearList(AnimList)
    AnimListPtr=Null
    xsize=PixmapHeight(PixImg)
    ysize=xsize
    AnimSize=xsize
    Local maxframes:Int=PixmapWidth(PixImg)/ysize-1
   
    For Local i:Int=0 To MaxFrames
        Local Tmp:TPixmap=CreatePixmap(xsize,ysize,PixmapFormat(PixMap1))
        For Local jx:Int=0 To AnimSize-1
            For Local jy:Int=0 To AnimSize-1
                Local argb:Int=ReadPixel(PixImg,jx+i*(AnimSize),jy)
                WritePixel(Tmp,jx,jy,argb)
             Next
        Next
        AnimListPtr:TLink=ListAddLast(AnimList,Tmp)
    Next
  EndIf
  RedrawGadget(Canvas3)

End Function


Well, we finally come to the end of our long journey. I hope that it has been worth it. Blitzmax with (or without MaxGUI) is an amazing language and for me has been a pleasure to program in.

The final source code can be downloaded here. You can also download a tester program here. See source below:-
    SuperStrict
Graphics 640,480,0,0
Local bck:timage=LoadImage("1945.bmp")
Local file:String=
"whatever.png" '<----replace with the filename you have saved earlier
Local img:timage=LoadImage(file)  
Local maxframes:Int=ImageWidth(img)/ImageHeight(img)-1
Img=LoadAnimImage(file,ImageHeight(img),ImageHeight(img),0,maxframes)

Local frame:Int=0
While Not AppTerminate()
 Cls
 DrawImage bck,0,0
 DrawImage Img, 10,10, frame
 Flip
 frame=frame+1
 If frame>=maxframes Then frame=0
 Delay(100)
Wend

Final Words

There are still a lot of things that we can add to this program. I decided to call this the Lite version because I wanted to keep the scope of the program manageable, bearing in mind that the real objective of this program was as an example to a learning tutorial.

In the course of this journey, I was distracted many times in terms of the functionalities that I wanted to add but had to remind myself many times to first get the tutorial done and then re-visit the program later., add more functionalities and remove the "lite" moniker from its name.

I have since decided to release the program code as public domain so as to allow as many people as possible to built upon the existing code and add the functionalities that they want without worrying about infringing copyright.

The functionalities I have been thinking about were
 I'm sure there are many more. Be my guest and modify and add functionalities to your hearts content. The best way to learn is by doing.

Take care and success.

Return to Main Index.