Seite 1 von 1

PureWaitingCircle

Verfasst: 18.05.2008 10:37
von coder
Moin,

ich hab mal aus langerweile ein kleinen Codes geschrieben, welcher die das darstellen von Warteanimationen erlaubt!

Wäre dankbar für 'ne bisschen Feedback! :allright:

Code: Alles auswählen

; gPreferences[460-5-1-1-794-154-0-252-111]
;
;PureWaitingCircle - Engine
;
;geschrieben in PureBasic 4.10
;   (C) 2008 by Martin 'coder' Peters
;   einfach.martin [at] t-online [dot] de
;
;-OS:
;   Windows          (X)
;   Linux            (?)
;   MacOS            (?)
;
;
;-HAVE:
;   PB only          (X)
;   Without Userlibs (X)
;   Without any DLLs (X)
;   EnableExplicit   (X)
;   Unicode          (X)
;   
;   
;-NEED:
;   ThreadSafe       (X)
;   Unicode          ( )
;   UserMode         (?)
;   AdminMode        ( )
;   InlineASM        ( )
;   PBOSL            ( )
;   DLLs             ( )


EnableExplicit    ;->>>EnableExplicit<<<

;-______________________________
;-DECLARATION

#PWC_CMax = 8

Structure PWC
  w.l   ;width
  h.l   ;height
  Gadget.l    ;ImageGadget
  Image.l   ;ImageID welche genutzt werden kann
  
  Play.b    ;Soll die Animation abgespielt werden?
  Wait.l    ;Zeit die minimal ein Bild zu sehen sein soll (in ms)
  Thread.l    ;ThreadID
  Pos.l   ;Position von dem hervorgehobenen Segment
  
  CSize.l   ;Durchmesser der Kreise
  
  BackColor.l   ;Hintergrundfarbe
  Color.l   ;Standardfarbe
  Color1.l    ;1 Farbe
  Color2.l    ;2 Farbe
  Color3.l    ;3 Farbe
EndStructure

Structure Punkt2D 
  X.d 
  Y.d 
EndStructure 

;-______________________________
;-HELP PROCS

Procedure EllipseAnglePoint(X, Y, RadiusX, RadiusY, EllipseAngle.d, PositionAngle.d, *Point.Punkt2D) 
;RadiusX = Vertikaler Radius
;RadiusY = Horizontaler Radius
;EllipseAngle = Neigung der Ellipse in Grad
;PositionAngle = benötigter Punkt in Grad
;*Point.Punkt2D = Structurierte Variable welche später die Koordinaten des Punktes enthält
Protected dx.d, dy.d
 EllipseAngle = EllipseAngle * #PI/180 
 PositionAngle = PositionAngle * #PI/180
 
 dx = Cos(PositionAngle)*RadiusX - Sin(PositionAngle)*RadiusX 
 dy = Sin(PositionAngle)*RadiusY + Cos(PositionAngle)*RadiusY 
 *Point\X = X + Cos(EllipseAngle)*dx - Sin(EllipseAngle)*dy 
 *Point\Y = Y + Sin(EllipseAngle)*dx + Cos(EllipseAngle)*dy 
EndProcedure

Procedure myAbs(Zahl, Min, Max)
  If Zahl > Min And Zahl < Max
    ProcedureReturn Zahl
  EndIf
  If Zahl > Max
    Repeat
      Zahl = Zahl - Max
    Until Zahl <= Max
  EndIf
  If Zahl < Min
    Repeat
      Zahl = Zahl + Max
    Until Zahl >= Min
  EndIf
  ProcedureReturn Zahl
EndProcedure

;-______________________________
;-PROCS

Procedure PWC_Thread(*Info.PWC)
  Protected P.Punkt2D
  Protected Color
  Protected Start
  Protected n
  Protected x, y
  Protected RadiusX, RadiusY
  
  If *Info\Image = #PB_Any
    *Info\Image = CreateImage(#PB_Any, *Info\w, *Info\h)
  Else
    CreateImage(*Info\Image, *Info\w, *Info\h)
  EndIf
  
  SetGadgetState(*Info\Gadget, 0)
  
  Repeat
    If *Info\Play = -1
      ProcedureReturn 0
    EndIf
    Delay(100)
  Until *Info\Play = #True
  
  x = *Info\w/2
  y = *Info\h/2
  RadiusX = *Info\w/4
  RadiusY = *Info\h/4
  
  Repeat
    
    Start = ElapsedMilliseconds()
    
    StartDrawing(ImageOutput(*Info\Image))
      Box(0, 0, *Info\w, *Info\h, *Info\BackColor)
      
      For n = 0 To #PWC_CMax
        If *Info\Pos = n
          Color = *Info\Color1
        ElseIf *Info\Pos = myAbs(n+1, 0, #PWC_CMax)
          Color = *Info\Color2
        ElseIf *Info\Pos = myAbs(n+2, 0, #PWC_CMax)
          Color = *Info\Color3
        Else
          Color = *Info\Color
        EndIf
        
        EllipseAnglePoint(x, y, RadiusX, RadiusY, 0, n*45, P)
        Circle(P\x, P\y, *Info\CSize, Color)
      Next
    StopDrawing()
    
    SetGadgetState(*Info\Gadget, ImageID(*Info\Image))
    
    Repeat
      Delay(10)
    Until ElapsedMilliseconds()-Start >= *Info\Wait
    
    If *Info\Play <> 1
      ;SetGadgetState(*Info\Gadget, 0)
      Repeat
        If *Info\Play = -1
          Break 2
        EndIf
        Delay(100)
      Until *Info\Play = #True
    EndIf
    
    *Info\Pos = myAbs(*Info\Pos+1, 0, #PWC_CMax)
    
  ForEver
  
  SetGadgetState(*Info\Gadget, 0)
          
EndProcedure

Procedure PWC_Create(Gadget, w, h, CSize, Image = #PB_Any, Wait = 100, Color = $dddddd, Color1 = $aaaaaa, Color2 = $bbbbbb, Color3 = $cccccc, BackColor = $eeeeee)  
  Protected *Sys.PWC
  Protected Thread
  
  *Sys = AllocateMemory(SizeOf(PWC))
  
  With *Sys
    \w = w   ;width
    \h = h   ;height
    \Gadget = Gadget    ;ImageGadget
    \Image = Image    ;ImageID welche genutzt werden kann
    
    \Play = 0    ;Soll die Animation abgespielt werden?
    \Wait = Wait    ;Zeit die minimal ein Bild zu sehen sein soll (in ms)
    \Thread = 0    ;ThreadID
    \Pos = 0   ;Position von dem hervorgehobenen Segment
    
    \CSize = CSize   ;Durchmesser der Kreise
    
    \BackColor = BackColor   ;Hintergrundfarbe
    \Color = Color   ;Standardfarbe
    \Color1 = Color1    ;1 Farbe
    \Color2 = Color2    ;2 Farbe
    \Color3 = Color3    ;3 Farbe
  EndWith
  
  Thread = CreateThread(@PWC_Thread(), *Sys.PWC)
  *Sys\Thread = Thread
  ProcedureReturn *Sys
EndProcedure

Procedure PWC_Play(*Sys.PWC)
  *Sys\Play = 1
EndProcedure

Procedure PWC_Stop(*Sys.PWC)
  *Sys\Play = 0
EndProcedure

Procedure PWC_Close(*Sys.PWC)
  Protected S
  *Sys\Play = -1
  
  S = 0
  While IsThread(*Sys\Thread)
    S + 1
    If S > 5
      KillThread(*Sys\Thread)
      ;Debug "Kill Thread"
      Break
    EndIf
    Delay(1)
  Wend
  
  FreeImage(*Sys\Image)
  SetGadgetState(*Sys\Gadget, 0)
  FreeMemory(*Sys)
EndProcedure

Procedure PWC_SetColor(*Sys.PWC, Color = $dddddd, Color1 = $aaaaaa, Color2 = $bbbbbb, Color3 = $cccccc, BackColor = $eeeeee)
  With *Sys
    \BackColor = BackColor   ;Hintergrundfarbe
    \Color = Color   ;Standardfarbe
    \Color1 = Color1    ;1 Farbe
    \Color2 = Color2    ;2 Farbe
    \Color3 = Color3    ;3 Farbe
  EndWith
EndProcedure

Procedure PWC_Hide(*Sys.PWC, State)
  If State
    PWC_Stop(*Sys)
    SetGadgetState(*Sys\Gadget, 0)
  Else
    PWC_Play(*Sys)
    SetGadgetState(*Sys\Gadget, *Sys\Image)
  EndIf
EndProcedure

DisableExplicit   ;->>>DisableExplicit<<<

;-______________________________
;-EXAMPLE

Define *a.PWC
Define *b.PWC
Define *c.PWC
Define *d.PWC

OpenWindow(0, 0, 0, 512, 256, "PureWaitingCircle Test", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
If CreateGadgetList(WindowID(0))
  ImageGadget(0, 0, 0, 256, 256, 0)
  ImageGadget(1, 256, 0, 128, 128, 0)
  ImageGadget(2, 256, 128, 256, 128, 0)
  ButtonGadget(3, 385, 0, 128, 40, "Pause", #PB_Button_Toggle)
  ImageGadget(4, 385, 50, 64, 64, 0)
EndIf

*a = PWC_Create(0, 256, 256, 16, 0)
*b = PWC_Create(1, 128, 128, 16, 1, 50, $dd00dd, $aa00aa, $bb00bb, $cc00cc)
*c = PWC_Create(2, 256, 128, 16, 2, 75, $00dd00, $00aa00, $00bb00, $00cc00)
*d = PWC_Create(4, 64, 64, 5, 3, 100, $444444, $FFFFFF, $DDDDDD, $CCCCCC, 0)

PWC_Play(*a)
PWC_Play(*b)
PWC_Play(*c)
PWC_Play(*d)

Repeat
  Event = WaitWindowEvent(1)
  If Event = #PB_Event_CloseWindow
    Break
  ElseIf Event = #PB_Event_Gadget
    If EventGadget() = 3
      If GetGadgetState(3) = 0
        PWC_Play(*a)
        PWC_SetColor(*a, $444444, $FFFFFF, $DDDDDD, $CCCCCC, 0)
      Else
        PWC_Stop(*a)
      EndIf
    EndIf
  EndIf
ForEver

HideWindow(0, 1)
PWC_Close(*a)
PWC_Close(*b)
PWC_Close(*c)
PWC_Close(*d)
End
mfg coder

Verfasst: 18.05.2008 11:10
von STARGÅTE
Der Code ist sehr anfällig:
StopDrawing() must called before calling StartDrawing() again.
liegt vermutlich an den Threads die du verwendest.


EDIT: schon gut habe vergessen Thread-Sichere-Exe zu erstellen.

Verfasst: 18.05.2008 11:29
von marco2007
Sehr gut! :allright:

Ich bin schon am überlegen, ob ich´s bei meinem derzeitigen Programm verwenden soll/kann.

Danke!

Verfasst: 18.05.2008 12:26
von coder
STARGÅTE hat geschrieben:Der Code ist sehr anfällig:
StopDrawing() must called before calling StartDrawing() again.
liegt vermutlich an den Threads die du verwendest.


EDIT: schon gut habe vergessen Thread-Sichere-Exe zu erstellen.
Wer lesen kann ist klar im Vorteil! :lol: is nicht ernst gemeint


@marco2006
Danke!