Code: Select all
;
; https://www.purebasic.fr/english/viewtopic.php?p=594218
;
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
CompilerEndIf
Structure SpriteList_Structure
Sprite.i
Delay.i
EndStructure
Structure AnimatedGIFInfo_Structure
List SpriteList.SpriteList_Structure()
EndStructure
Structure AnimatedGIFSprite_Structure
Window.i
Map GIFInfoMap.AnimatedGIFInfo_Structure()
EndStructure
Global AnimatedGIFSprite.AnimatedGIFSprite_Structure
Procedure AnimateGIFSpritesTimerEvent()
Protected *AnimatedGIFSprite.AnimatedGIFInfo_Structure, Sprite.i
Sprite = EventTimer()
*AnimatedGIFSprite = FindMapElement(AnimatedGIFSprite\GIFInfoMap(), Str(Sprite))
If *AnimatedGIFSprite
RemoveWindowTimer(AnimatedGIFSprite\Window, Sprite)
If Not NextElement(*AnimatedGIFSprite\SpriteList())
FirstElement(*AnimatedGIFSprite\SpriteList())
EndIf
;Debug "AddWindowTimer: " + Str(Sprite) + " " + Str(*AnimatedGIFSprite\SpriteList()\Delay) + " " + Str(ListIndex(*AnimatedGIFSprite\SpriteList()))
AddWindowTimer(AnimatedGIFSprite\Window, Sprite, *AnimatedGIFSprite\SpriteList()\Delay)
EndIf
EndProcedure
Procedure AnimateGIFSpritesUpdate(EventLoop=#False)
If Not EventLoop
While WindowEvent() : Wend
EndIf
EndProcedure
Procedure.i LoadAnimatedGIFSprite(Sprite.i, Filename$, Mode.i=0, StartAnimationPosition.i=0)
Protected Image.i, Result.i, *AnimatedGIFSprite.AnimatedGIFInfo_Structure, Frame.i, ActualFrame
If AnimatedGIFSprite\Window = 0
AnimatedGIFSprite\Window = OpenWindow(#PB_Any, 0, 0, 0, 0, "", #PB_Window_Invisible)
BindEvent(#PB_Event_Timer, @AnimateGIFSpritesTimerEvent(), AnimatedGIFSprite\Window)
EndIf
Image = LoadImage(#PB_Any, Filename$)
If Image
If Sprite = #PB_Any
Sprite = CreateSprite(#PB_Any, ImageWidth(Image), ImageHeight(Image), Mode)
Result = Sprite
Else
Result = CreateSprite(Sprite, ImageWidth(Image), ImageHeight(Image), Mode)
EndIf
If Result
*AnimatedGIFSprite = AddMapElement(AnimatedGIFSprite\GIFInfoMap(), Str(Sprite))
AddElement(*AnimatedGIFSprite\SpriteList())
SetImageFrame(Image, 0)
*AnimatedGIFSprite\SpriteList()\Delay = GetImageFrameDelay(Image)
*AnimatedGIFSprite\SpriteList()\Sprite = Sprite
If StartDrawing(SpriteOutput(*AnimatedGIFSprite\SpriteList()\Sprite))
DrawImage(ImageID(Image), 0, 0)
StopDrawing()
EndIf
For Frame = 1 To ImageFrameCount(Image) - 1
AddElement(*AnimatedGIFSprite\SpriteList())
SetImageFrame(Image, Frame)
*AnimatedGIFSprite\SpriteList()\Delay = GetImageFrameDelay(Image)
*AnimatedGIFSprite\SpriteList()\Sprite = CreateSprite(#PB_Any, ImageWidth(Image), ImageHeight(Image), Mode)
If StartDrawing(SpriteOutput(*AnimatedGIFSprite\SpriteList()\Sprite))
DrawImage(ImageID(Image), 0, 0)
StopDrawing()
EndIf
Next Frame
If StartAnimationPosition > 0 And StartAnimationPosition <= 100
ActualFrame = Frame / (100 / StartAnimationPosition) - 1
If ActualFrame < 0
ActualFrame = 0
EndIf
EndIf
SelectElement(*AnimatedGIFSprite\SpriteList(), ActualFrame)
AddWindowTimer(AnimatedGIFSprite\Window, Sprite, *AnimatedGIFSprite\SpriteList()\Delay)
EndIf
EndIf
ProcedureReturn Result
EndProcedure
Procedure DisplayAnimatedSprite(Sprite.i, x.i, y.i)
Protected *AnimatedGIFSprite.AnimatedGIFInfo_Structure
*AnimatedGIFSprite = FindMapElement(AnimatedGIFSprite\GIFInfoMap(), Str(Sprite))
If *AnimatedGIFSprite
DisplaySprite(*AnimatedGIFSprite\SpriteList()\Sprite, x, y)
EndIf
EndProcedure
Procedure DisplayAnimatedTransparentSprite(Sprite.i, x.i, y.i, Intensity.i=255, Color.i=#PB_Ignore)
Protected *AnimatedGIFSprite.AnimatedGIFInfo_Structure
*AnimatedGIFSprite = FindMapElement(AnimatedGIFSprite\GIFInfoMap(), Str(Sprite))
If *AnimatedGIFSprite
If Color.i = #PB_Ignore
DisplayTransparentSprite(*AnimatedGIFSprite\SpriteList()\Sprite, x, y, Intensity)
Else
DisplayTransparentSprite(*AnimatedGIFSprite\SpriteList()\Sprite, x, y, Intensity, Color)
EndIf
EndIf
EndProcedure
;-Demo
CompilerIf #PB_Compiler_IsMainFile
Define.i Width, Height, Depth, ScreenReady, AnySprite
Define GIFFilename$
UseGIFImageDecoder()
If InitSprite() = 0 Or InitKeyboard() = 0
MessageRequester("Error", "Sprite system can't be initialized")
End
EndIf
If ExamineScreenModes()
While NextScreenMode()
Width = ScreenModeWidth()
If Width >= 800
Height = ScreenModeHeight()
Depth = ScreenModeDepth()
;Debug Str(Width) + "x" + Str(Height) + "," + Str(Depth)
Break
EndIf
Wend
Else
MessageRequester("Error", "Screen modes can't be detected")
End
EndIf
If MessageRequester("Choose screen mode", "Use OpenScreen()?", #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
If OpenScreen(Width, Height, Depth, "")
ScreenReady = #True
EndIf
Else
If OpenWindow(0, 0, 0, Width, Height, "Press ESC for exit", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
If OpenWindowedScreen(WindowID(0), 0, 0, Width, Height)
ScreenReady = #True
EndIf
EndIf
EndIf
If ScreenReady
GIFFilename$ = GetUserDirectory(#PB_Directory_Downloads) + "animated-dog-image-0175.gif"
ReceiveHTTPFile("https://www.animatedimages.org/data/media/202/animated-dog-image-0175.gif", GIFFilename$)
If FileSize(GIFFilename$) > 0
LoadAnimatedGIFSprite(1, GIFFilename$)
AnySprite = LoadAnimatedGIFSprite(#PB_Any, GIFFilename$, 0, 50)
Else
LoadAnimatedGIFSprite(1, #PB_Compiler_Home + "Examples/Sources/Data/PureBasicLogo.gif")
AnySprite = LoadAnimatedGIFSprite(#PB_Any, #PB_Compiler_Home + "Examples/Sources/Data/PureBasicLogo.gif", 0, 50)
EndIf
Repeat
FlipBuffers()
AnimateGIFSpritesUpdate() ; !!! only needed if no windows event loop is available !!!
ClearScreen(RGB(0, 128, 0))
DisplayAnimatedSprite(1, 100, 100)
DisplayAnimatedTransparentSprite(AnySprite, 300, 300)
ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)
If FileSize(GIFFilename$) > 0
DeleteFile(GIFFilename$)
EndIf
EndIf
CompilerEndIf