update Graphics Modue

update Graphics Modue

Included  Drw_ManiacText()

#Rem monkeydoc Module maniac.maniacGraphics
	Graphics Module - Version 0.1.2 (alpha)  ~n
	Copyright (C) 2015  Stephan Duckerschein~n

	Here You can find some "ad-Hoc" Graphic-Elements to use for your App.
	They have to be managed by the Programmer.

	ToDo For v. 0.1.3:
		- Complete Colors: GELB,ORANGE,MAGENTA,BROWN,PURPLE +####
		- Make Primitives rotateable
		- Complete ManiacImage ImageEffects
		~n
	VERSION HISTORY: ~n
	0.1.2~n
		Added: some more Green , Blue & Yellow Colors~n
		Added ManiacImage
		Added Drw_ManiacText
	0.1.1~n
		Added Lighning,Maniac_Color~n
		~n

#End

Import mojo
Import maniacLowLevel
Import maniacDebug

#rem
	Included Functions:
		- Drawing outline Rect
		- Drawing an outlining Ellipsis
		- Drawing a Lighning Effect
		- Drawing a Grid
		- Set the Current Color to RenderMode with Maniac_Color using Maniac_Color Convention
		- ManiacImage Class

#end
#Rem monkeydoc
	### READY TO USE ###~n
	This Function Draws a Outlining Rectangle at the Position _X,_Y with the Dimensions _Witdth and _Height with the thickness _Thickness.
	You must call this within the OnRender() Method
#End
Function Drw_Rect:Int(_X:Float,_Y:Float,_Width:Float,_Height:Float,_Thickness:Int=1)
	'Maniac_Debug.addRenderedObject()
	If MANIAC_DEBUG = True
		Maniac_Debug.addTotDraws(4*_Thickness)
	endif
	'Maniac_Debug.
	'Maniac_Debug.
	For Local i:Int = 0 until _Thickness
		'Obere Kante
		DrawLine (_X-i,_Y-i,_X +_Width+i,_Y-i)

		'Untere Kante
		DrawLine (_X-i,_Y+_Height+i,_X+_Width+i,_Y+_Height+i)

		'Linke Seite
		DrawLine (_X-i,_Y-i,_X-i,_Y+_Height+i)

		'Recht Seite
		DrawLine (_X+_Width+i,_Y-i,_X+_Width+i,_Y+_Height+i)
	Next

End Function

#Rem monkeydoc
	### READY TO USE ###~n
	This Function Draws a outlining ellipsis at _X,_Y with the Dimensions _Witdth and _Height and the number of cells in x and y direction.
	You must call this within the OnRender() Method
#End
Function Drw_Ellipsis( posx:Float, posy:Float, width:Float, height:Float)

   	Local x:Float
   	Local y:Float
   	Local rx:Float = width / 2
   	Local ry:Float = height / 2

   	Local r:Int = Abs(rx) + Abs(ry)

   	x = 0
   	y = r

   	Local d:Int
   	Local ddf_x:Int
   	Local ddf_y:Int

   	d = 1 - r
   	ddf_x = 3
	ddf_y = -2 * r + 5

   	While y >= x And r
		If MANIAC_DEBUG = True
			Maniac_Debug.addTotDraws(8)
		endif
	    DrawPoint( posx + x * rx/r, posy + y * ry/r )
	    DrawPoint( posx + y * rx/r, posy + x * ry/r )
	    DrawPoint( posx + y * rx/r, posy - x * ry/r )
	    DrawPoint( posx + x * rx/r, posy - y * ry/r )
	    DrawPoint( posx - x * rx/r, posy - y * ry/r )
	    DrawPoint( posx - y * rx/r, posy - x * ry/r )
	    DrawPoint( posx - y * rx/r, posy + x * ry/r )
	    DrawPoint( posx - x * rx/r, posy + y * ry/r )

	    If d < 0
	       d= d + ddf_x
	       ddf_x= ddf_x+ 2
	       ddf_y=ddf_y+ 2
	       x=x + 1
	    Else
	       d= d+ ddf_y
	       ddf_x=ddf_x+ 2
	       ddf_y=ddf_y+ 4
	       x=x+ 1
	       y=y- 1
	    EndIf
	Wend
End Function

#Rem monkeydoc
	### READY TO USE ###~n
	This Function Draws a Grid at the Position _X,_Y with the Dimensions _Witdth and _Height and the number of cells in x and y direction
	You must call this within the OnRender() Method
#End
Function Drw_Grid:Void(_X:Float,_Y:Float,_Width:Float,_Height:Float,_CellsX:Int,_CellsY:Int)
	If MANIAC_DEBUG = True
		Maniac_Debug.addTotDraws(2*cntx*cnty)
	endif
	'zeichnet ein Gitter an Position posx,posy (links oben), w/h breite bzw. hÃƒÂ¶he (des gesamten Grids) und zieht dabei cntx/cnty striche in der horizontalen,bzw vertikalen
	'allerdings wird hierbei das Gitter automatisch angepasst

	'1. bestimmen der breite eines KÃƒÂ¤stchens anhand der Breite und der anzahl
	Local cell_w:Float = _Width/_CellsX
	Local cell_h:Float = _Height/_CellsY

	For Local x:Int = 1 To cntx-1
		For Local y:Int = 1 To cnty-1

			'Vertikale
			DrawLine(_X+x*cell_w,_Y,_X+x*cell_w,_Y+cnty*cell_h)

			'Horizontale
			DrawLine(_X,_Y+y*cell_h,_X+cntx*cell_w,_Y+y*cell_h)

		Next
	Next

End Function

#Rem monkeydoc
	### READY TO USE ###~n
	This Function Draws a "Star-Bar" @ _X,_Y with the Dimensions _Witdth and _Height and the number of _MaxStars.~n
	_FullStars is the number of Colored Stars from Left
	You must call this within the OnRender() Method
#End
Function Drw_Stars(_X:Float,_Y:Float,_Width:Float,_Height:Float,_MaxStars:Int = 5,_FullStars:Int = 3)
	Local starWidth:Float = ll_Width(_Width,_MaxStars,5)

	For Local i:Int = 0 Until _MaxStars
		If i < _FullStars
			SetColor 255,0,0
		Else
			SetColor 75,75,75
		Endif

		DrawImage MANIAC_IMG_STAR, _X + 5 + i*(starWidth+5), _Y+5, 0 , starWidth/MANIAC_IMG_STAR.Width(),_Height/MANIAC_IMG_STAR.Height()
	Next
End Function

Function Drw_LoadingBar(_X:Float,_Y:Float,_Width:Float,_Height:Float,_Caption:String,_Prozent:Float)
	If _Prozent >= 0.0 And _Prozent <= 1.0
		SetColor 75,75,75
		DrawRect(_X,_Y,_Width*_Prozent,_Height)

		SetColor 255,255,255
		Drw_Rect(_X,_Y,_Width,_Height,2)

		SetColor 255,0,0
		Local l:Int = MANIAC_FONT.getW(( Int(_Prozent*100))+ " %")
		MANIAC_FONT.Wrap((Int(_Prozent*100))+ " %",_X+_Width*0.5-l/2+1,_Y,_Width,_Height,15)
	Endif
End Function

#Rem monkeydoc
	### READY TO USE ###~n
	This Function Draws a Loading-Bar at the Position _X,_Y with the Dimensions _Witdth and _Height
	You must call this within the OnRender() Method
#End
Function Drw_LoadingBar(_X:Float,_Y:Float,_Width:Float,_Height:Float,_Caption:String,_CurrValue:Float,_MaxValue:Float)
	Local pr:Float = _CurrValue/_MaxValue

	SetColor 75,75,75
	DrawRect(_X,_Y,_Width*pr,_Height)

	SetColor 255,255,255
	Drw_Rect(_X,_Y,_Width,_Height,2)

	SetColor 255,0,0
	Local l:Int = MANIAC_FONT.getW(( Int(pr*100))+ " %")
	MANIAC_FONT.Wrap((Int(pr*100))+ " %",_X+_Width*0.5-l/2+1,_Y,_Width,_Height,15)
End Function

#Rem monkeydoc
	This Functions Draws an LoadingBar @ position ix,iy with w,h in Pixels
	istartTime is the Beginning Time, length is the max Time (both in ms)
#End
Function Drw_TimingBar(ix:Int,iy:Int,w:Int,h:Int,istartTime:Int,ilengthTime:Int,iStyle:Int = 0)

	Duke_Drw_Rect(ix,iy,w,h,2)
	Local lw:Int = ( ( Millisecs()-istartTime ) * w ) / ilengthTime
	If iStyle = 0
		DrawRect(ix,iy,w-lw,h)
	Elseif iStyle = 1
		DrawRect(ix,iy,w-lw,h)
	Endif

End Function

#Rem monkeydoc
	### READY TO USE ###~n
	Draw 2d Lightning.
	Pass the starting and ending points.  Depth parameters refers to recursion.  Don't want to blow the stack!

	You must call this within the OnRender() Method
	Example:

		'Within the On Render you jast call the Lightning
		Method OnRender:Int()
			Cls
			Drw_Lightning(0,0,DW*0.5,DH*0.5)
			Return 0
		End

	Credits:
	this Code is from http://www.blitzbasic.com/codearcs/codearcs.php?code=3119
	Matt Lloyd Lightning Implementation.
	and is translated into monkey by Stephan D
	Free To use as you wish. Play around with the parameters.
#End
Function Drw_Lightning(sx#,sy#,fx#,fy#,depth=4)

	'Local dx#,dy#,dist#,ox#,oy#,x#,y#,udx#,udy#
	Local i

	'play around with these numbers to see the effects
	Local shakiness#=-2.5 ;
	Local branchchance=6;
	Local wr1 = 16
	Local wr2 = 16
	Local hr1 = 4
	Local hr2 = 24

	If(depth<=0) Then Return ';;as said - don't want to go too deep in the stack...

	Local dx#=fx-sx
	Local dy#=fy-sy
	Local dist#=Sqrt(dx*dx+dy*dy)

	If(dist=0) Then Return ' ;no need To do any lightning If our start And ending points are on top of each other...And also avoid nasty division by zeroes...

	Local udx#=dx/dist'	;unit vectors in direction of lightning...
	Local udy#=dy/dist

	Local x#=sx
	Local y#=sy
	Local ox#=x
	Local oy#=y

	For i=1 To dist
		If MANIAC_DEBUG = True
			Maniac_Debug.addTotDraws(5)
		endif
		x=x+udx+Rnd(-shakiness,shakiness)
		y=y+udy+Rnd(-shakiness,shakiness)

		ll_ColorCentre()
		DrawLine x,y,ox,oy

		ll_ColorInnerEdge()
		DrawLine x-udy,y+udx, ox-udy,oy+udx
		DrawLine x+udy,y-udx,ox+udy,oy-udx

		ll_ColorOuterEdge()
		DrawLine x-udy*2.0,y+udx*2.0, ox-udy*2.0,oy+udx*2.0
		DrawLine x+udy*2.0,y-udx*2.0,ox+udy*2.0,oy-udx*2.0

		ox=x
		oy=y

		If(Rnd(1,100)<branchchance) Then
			If MANIAC_DEBUG = True
				Maniac_Debug.addTotDraws()
			endif
			Drw_Lightning(ox,oy,ox+Rnd(-wr1,wr2),oy+Rnd(-hr1,hr2),depth-1)
		EndIf

	Next
End Function

#Rem monkeydoc
	### READY TO USE ###~n
	Draws a wrapped Text (ManiacFontText) to the _X,_Y,_Width,_Height Container with the _AlignX & _AlignY Parameter.

	This Function returns the CursorPosition in Pxl for the X-Koordinate
	You must call this within the OnRender() Method
	Example:

		'Within the On Render you jast call the Lightning
		Method OnRender:Int()
			Cls
			Drw_ManiacText("Hallo",50,200,300,50,ALIGNMENT_MIDDLE)
			Return 0
		End

#End
Function Drw_ManiacText:Float(_Caption:String,_X:Float,_Y:Float,_Width:Float,_Height:Float,_AlignX:Int = ALIGNMENT_MIDDLE,_AlignY:Int = ALIGNMENT_MIDDLEY)
	Local lW:Float
	Local lH:Float = 0

	Select _AlignX
		Case ALIGNMENT_LEFT
			lW = 0

		Case ALIGNMENT_MIDDLE
			Local l:Int = MANIAC_FONT.getW(_Caption)
			lW = _Width/2-l/2

		Case ALIGNMENT_RIGHT
			Local l:Int = MANIAC_FONT.getW(_Caption)
			lW = _Width-l/2
		Default
			lW = 0
	End Select

	'### ToDo Include a Y Alignment System ...
	Select _AlignY
		Case ALIGNMENT_TOP
		Case ALIGNMENT_MIDDLEY
		Case ALIGNMENT_BOTTOM
	End Select

	MANIAC_FONT.Wrap(_Caption,_X+lW,_Y+lH,_Width,_Height,_Caption.Length())

	Local tW:Float = MANIAC_FONT.getW(_Caption)
	Return (_X+lW+tW)
End Function

Const COLOR_BLACK:Int 		= 	0
Const COLOR_GRAY:Int		=	4
Const COLOR_WHITE:Int		= 	9
Const COLOR_RED:Int			=	10
Const COLOR_GREEN:Int		=	20
Const COLOR_DARKGREEN:Int 	= 	27
Const COLOR_BLUE:Int		= 	30
Const COLOR_YELLOW:Int 		= 	40
Const COLOR_ORANGE:Int 		= 	50
Const COLOR_MAGENTA:Int		= 	60
Const COLOR_BROWN:Int		= 	70
Const COLOR_PURPLE:Int		= 	80

Const COLOR_PLAYER1:Int =  801
Const COLOR_PLAYER2:Int =  802
Const COLOR_PLAYER3:Int	=  803
Const COLOR_PLAYER4:Int =  804

#Rem monkeydoc
	### EXPERIMENTAL ### ~n
	This Function sets the Render-Color to a predefined color by The Maniac-Color-Consts.
	You can find the Colors in the Functions Section.~n
	Details:
	COLOR_BLACK = 0, COLOR_GRAY = 4, COLOR_WHITE = 9
	COLOR_RED = 10 To 19 ; 10 is 255,0,0, the part of Red decreases by higher ID
	So, every COlOR has 10 brightnes grades.
	You can use it like

	Duke_Color2(COLOR_GREEN + brightness), whereas brightness can be an int Value between 0 and 9
	so, COLOR_GREEN + 8 is a very dark green
#End
Function Maniac_Color(_Color:Int)
	'Maniac_Debug.addCall()
	Select _Color
		Case 0	'Schwarz
			SetColor 0,0,0
		Case 1
			SetColor 50,50,50
		Case 2
			SetColor 75,75,75
		Case 3
			SetColor 100,100,100
		Case 4
			SetColor 125,125,125
		Case 5
			SetColor 150,150,150
		Case 6
			SetColor 175,175,175
		Case 7
			SetColor 200,200,200
		Case 8
			SetColor 225,225,225
		Case 9	'Weiss
			SetColor 255,255,255

			'### ROT ### colors 10-19
		Case 10
			SetColor 255,0,0
		Case 11
			SetColor 230,0,0
		Case 12
			SetColor 210,0,0
		Case 13
			SetColor 190,0,0
		Case 14
			SetColor 170,0,0
		Case 14
			SetColor 150,0,0
		Case 15
			SetColor 130,0,0
		Case 16
			SetColor 110,0,0
		Case 17
			SetColor 90,0,0
		Case 18
			SetColor 70,0,0
		Case 19
			SetColor 50,0,0

			'### GRUEN ### 20-29
		Case 20
			SetColor 0,255,0
		Case 21
			SetColor 0,230,0
		Case 22
			SetColor 0,210,0
		Case 23
			SetColor 0,190,0
		Case 24
			SetColor 0,170,0
		Case 25
			SetColor 0,150,0
		Case 26
			SetColor 0,130,0
		Case 27
			SetColor 0,110,0
		Case 28
			SetColor 0,90,0
		Case 29
			SetColor 0,70,0

			'### BLAU ###
		Case 30
			SetColor 0,0,255
		Case 31
			SetColor 0,0,230
		Case 32
			SetColor 0,0,210
		Case 33
			SetColor 0,0,190
		Case 34
			SetColor 0,0,170
		Case 35
			SetColor 0,0,150
		Case 36
			SetColor 0,0,130
		Case 37
			SetColor 0,0,110
		Case 38
			SetColor 0,0,90
		Case 39
			SetColor 0,0,70

			'### GELB ###
		Case 40
			SetColor 255,255,0
		Case 41
			SetColor 255,255,120
		Case 42
			SetColor 255,255,50
		Case 43
			SetColor 215,215,0

		'###	ORANGE ###
		Case 50
			SetColor 255,140,0

		'### MAGENTA ###
		Case 60
			SetColor 255,0,255

		'### BROWN ###
		Case 70
			SetColor 165,42, 42

		'### PURPLE +####
		Case 80
			SetColor 75,0,130

		Case COLOR_PLAYER1
			SetColor 0,0,255

		Case COLOR_PLAYER2
			SetColor 0,255,0

		Case COLOR_PLAYER3
			SetColor 255,0,0

		Case COLOR_PLAYER4
			SetColor 255,255,255

	End Select
End Function

Const IMGEFFECT_MIRRORX:Int = 1
Const IMGEFFECT_MIRRORY:Int = 2

Const IMGEFFECT_ROTATE_SHEARX45:Int = 7

Const IMGANIMAGION_FADE_IN:Int = 3
Const IMGANIMATION_DROP_IN:Int = 4
Const IMGANIMATION_SPIRAL_IN:Int = 5
Const IMGANIMATION_WAVE_IN:Int = 6

Const IMGGLOW_STYLE_SIN:Int 	= 0

Const IMG_ALIGN_LEFT:Int		= 0
Const IMG_ALIGN_MIDDLE:Int		= 1
Const IMG_ALIGN_RIGHT:Int		= 2

Const IMG_ALIGN_ONTOP:Int		= 3
Const IMG_ALIGN_TOP:Int			= 4
Const IMG_ALIGN_BOTTOM:Int		= 5
Const IMG_ALIGN_UNDERBOTTOM:Int	= 6

#Rem monkeydoc
	This is kind of an extended mojo Image.~n
	It provides some additional features.

	-InstantEffects:
		- Glow
		- Shearing,rotation & stuff

	-Complex-Animations

	-MoveAnimation

	BUGLIST:
		The Caption is not rendered correctly with RenderMode - Done
#End
Class ManiacImage
	Field MidX:Float,MidY:Float,Width:Float,Height:Float
	Field Caption:String
	Field CaptionColor:Int		'Color of the Caption
	Field AlignX:Int
	Field AlignY:Int

	Field img:Image
	Field bFramed:Bool = False
	Field bBlink = True
	Field Color:Int = 9
	Field angle:Float =0.0
	Field mode:Int = 0

	'### Glow Effects ###
	Field bGlow:Bool  = False
	Field GlowAlpha:Float
	Field HertzAlpha:Float 		'
	Field AlphaFrom:Float		= 0.2
	Field AlphaTo:Float			= 0.95
	Field GlowStyle:Int		= 0	'0 - If Alpha reases max, it decreases from max ; 1 - if Alpha reaches max, it jumps to min
	Field bAlphaDirection:Bool = True		'if True, Alpha raises, if false, Alpha decreases
	Field HertzIncreaseeAlpha:Float	=0.4
	Field HertzDecreaseAlpha:Float	=1

	Field AddWidthByMO:Int 		= 0
	Field AddHeightByMO:Int		= 0
	Field Scale:Float = 1.0

	#Rem monkeydoc
		Creates a new ManiacImage.
		midX and midy are both the midhandled coordiantes of the image.
		String the is Sourcepath to the Image
		_Caption if wanted is will be shown withing the Image
	#End
	Method New(midx:Float,midy:Float,width:Float,height:Float,Path:String,_Caption:String="",_AlignX:Int = 0,_AlignY:Int = 3,_Hertz:Float = 1.0 )
		img = LoadImage(Path)
		MidX = midx
		MidY = midy
		Width = width
		Height = height
		Caption = _Caption
		CaptionColor = COLOR_BLUE
		AlignX = _AlignX
		AlignY = _AlignY
		HertzAlpha = _Hertz
		mode = 0
	End Method

	Method setCaption:Void(_Caption:String,_AlignX:Int,_AlignY:int)
		Caption = _Caption
	End Method

	Method setMode(_mode:Int)
		mode = _mode
	End Method

	Method getMode:Int()
		Return mode
	End Method

	Method setGlow(_isGlowing:Bool = True)
		bGlow = _isGlowing
	End Method

	Method setCostomMode(shearx:Int,sheary:Int,anglespeed:Float=4.0,scale:Float = 1.0)

	End Method

	Method setFrame(_isFramed:Bool = True,_FrameColor:Int = 0)
		bFramed = _isFramed
		FrameColor = _FrameColor
	End Method

	Method Draw()

		If bGlow = True
			If bAlphaDirection = True
				GlowAlpha += EqToFPS(HertzIncreaseeAlpha)
				If GlowAlpha >= AlphaTo
					If GlowStyle = 0
						bAlphaDirection = False
					Elseif GlowStyle = 1
						bAlphaDirection = True
						GlowAlpha = AlphaFrom
					Endif
				Endif
			Else
				GlowAlpha -= EqToFPS(HertzDecreaseAlpha)
				If GlowAlpha <= AlphaFrom
					If GlowStyle = 0
						bAlphaDirection = true
					Elseif GlowStyle = 1
						bAlphaDirection = false
						GlowAlpha = AlphaTo
					Endif
				Endif
			Endif
		Endif

		'
		'DrawText "mode: " +mode, 300,200
		Select mode
            Case IMGEFFECT_MIRRORX
                MirrorXAt(MidX, MidY)
            Case IMGEFFECT_MIRRORY
                MirrorYAt(MidX, MidY)

            Case 3
                angle += EqToFPS(45)
                ScaleAt(MidX, MidY, 0.6, 0.6)
                ShearXAt(MidX, MidY, Cos(angle))
                ShearYAt(MidX,MidY,	angle)
                RotateAt(MidX, MidY, angle)

            Case 4
                ShearXAt(MidX, MidY, Sin(angle))
            Case 5
                ShearYAt(MidX, MidY, -angle)
            Case 6
                ShearXAt(MidX, MidY, 30)
                ShearYAt(MidX, MidY, 30)

            Case IMGEFFECT_ROTATE_SHEARX45
                'ScaleAt(MidX, MidY, 1, 0.3)
                ShearXAt(MidX, MidY, 45)
                RotateAt(MidX, MidY, angle)
            Case 8
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 0.3)
                RotateAt(MidX, MidY, -angle)
                ShearXAt(MidX, MidY, 45)
                ShearYAt(MidX, MidY, 45)
                RotateAt(MidX, MidY, angle)
            Case 9
            	angle += EqToFPS(180)
                RotateAt(MidX, MidY, -angle)
                ShearXAt(MidX, MidY, 45)
                ShearYAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 10
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 0.1)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 11
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 0.2)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 12
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 0.4)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 13
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 0.8)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 14
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 1.6)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 15
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 3.2)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 16
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 6.4)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 17
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 3, 1)
                ShearYAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, -angle)
            Case 18
            	angle += EqToFPS(180)
                If angle=160 Then angle = 0
                ShearXAt(MidX, MidY, angle-80)
            Case 19
            	angle += EqToFPS(180)
                If angle=160 Then angle = 0
                ShearYAt(MidX, MidY, angle-80)
            Case 20
            	angle += EqToFPS(180)
                If angle=160 Then angle = 0
                ShearXAt(MidX, MidY,-angle+80)
                ShearYAt(MidX, MidY, angle-80)
            Case 21
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, Sin(angle))
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 22
            	angle += ATan(EqToFPS(180))
                ScaleAt(MidX, MidY, 1, Sin(angle))
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)

        End Select

        Maniac_Color(Color)
        '###### GLOW EFFECT STUFF #####
		If bGlow = true
			SetAlpha GlowAlpha
			DrawImage MANIAC_IMG_FRAME_BLUR, MidX,MidY,angle,Width*1.3/MANIAC_IMG_FRAME_BLUR.Width(),Height*1.3/MANIAC_IMG_FRAME_BLUR.Height()
		End If

        DrawImage img,MidX-Width*0.5,MidY-Height*0.5,0,Width/img.Width(),Height/img.Height()

        '###### BUTTON FRAME ########
		If bFramed = True
			'Maniac_Color(FrameColor)
			DrawImage MANIAC_IMG_FRAME_RAW , MidX,MidY,angle,(Width+AddWidthByMO)/MANIAC_IMG_FRAME_RAW.Width(),(Height+AddHeightByMO)/MANIAC_IMG_FRAME_RAW.Height()
		Endif

        '##### DRAWING THE CAPTION TO THE BUTTON #####
		SetAlpha 1
		Maniac_Color(CaptionColor)
		Select AlignX
			Case IMG_ALIGN_LEFT
				MANIAC_FONT.Wrap(Caption,MidX-Width/2,MidY-Height/5,Width,Height,Caption.Length())
				ResetMatrix()
			Case IMG_ALIGN_MIDDLE
				Local l:Int = MANIAC_FONT.getW(Caption)
				MANIAC_FONT.Wrap(Caption,MidX-l/2+1,MidY-Height/5,Width,Height,Caption.Length())
				ResetMatrix()
			Case IMG_ALIGN_RIGHT
				Local l:Int = MANIAC_FONT.getW(Caption)
				MANIAC_FONT.Wrap(Caption,MidX+Width/2-l,MidY-Height/5,Width,Height,Caption.Length())
				ResetMatrix()
		End Select

        ResetMatrix()

        SetAlpha 1
	End Method

End Class

#Rem monkeydoc Module maniac.maniacGraphics
	Graphics Module - Version 0.1.2 (alpha)  ~n
	Copyright (C) 2015  Stephan Duckerschein~n

	Here You can find some "ad-Hoc" Graphic-Elements to use for your App.
	They have to be managed by the Programmer.

	ToDo For v. 0.1.3:
		- Complete Colors: GELB,ORANGE,MAGENTA,BROWN,PURPLE +####
		- Make Primitives rotateable
		- Complete ManiacImage ImageEffects
		~n
	VERSION HISTORY: ~n
	0.1.2~n
		Added: some more Green , Blue & Yellow Colors~n
		Added ManiacImage
	0.1.1~n
		Added Lighning,Maniac_Color~n
		~n

#End

Import mojo
Import maniacLowLevel
Import maniacDebug

#rem
	Included Functions:
		- Drawing outline Rect
		- Drawing an outlining Ellipsis
		- Drawing a Lighning Effect
		- Drawing a Grid
		- Set the Current Color to RenderMode with Maniac_Color using Maniac_Color Convention
		- ManiacImage Class

#end
#Rem monkeydoc
	### READY TO USE ###~n
	This Function Draws a Outlining Rectangle at the Position _X,_Y with the Dimensions _Witdth and _Height with the thickness _Thickness.
	You must call this within the OnRender() Method
#End
Function Drw_Rect:Int(_X:Float,_Y:Float,_Width:Float,_Height:Float,_Thickness:Int=1)
	'Maniac_Debug.addRenderedObject()
	If MANIAC_DEBUG = True
		Maniac_Debug.addTotDraws(4*_Thickness)
	endif
	'Maniac_Debug.
	'Maniac_Debug.
	For Local i:Int = 0 until _Thickness
		'Obere Kante
		DrawLine (_X-i,_Y-i,_X +_Width+i,_Y-i)

		'Untere Kante
		DrawLine (_X-i,_Y+_Height+i,_X+_Width+i,_Y+_Height+i)

		'Linke Seite
		DrawLine (_X-i,_Y-i,_X-i,_Y+_Height+i)

		'Recht Seite
		DrawLine (_X+_Width+i,_Y-i,_X+_Width+i,_Y+_Height+i)
	Next

End Function

#Rem monkeydoc
	### READY TO USE ###~n
	This Function Draws a outlining ellipsis at _X,_Y with the Dimensions _Witdth and _Height and the number of cells in x and y direction.
	You must call this within the OnRender() Method
#End
Function Drw_Ellipsis( posx:Float, posy:Float, width:Float, height:Float)

   	Local x:Float
   	Local y:Float
   	Local rx:Float = width / 2
   	Local ry:Float = height / 2

   	Local r:Int = Abs(rx) + Abs(ry)

   	x = 0
   	y = r

   	Local d:Int
   	Local ddf_x:Int
   	Local ddf_y:Int

   	d = 1 - r
   	ddf_x = 3
	ddf_y = -2 * r + 5

   	While y >= x And r
		If MANIAC_DEBUG = True
			Maniac_Debug.addTotDraws(8)
		endif
	    DrawPoint( posx + x * rx/r, posy + y * ry/r )
	    DrawPoint( posx + y * rx/r, posy + x * ry/r )
	    DrawPoint( posx + y * rx/r, posy - x * ry/r )
	    DrawPoint( posx + x * rx/r, posy - y * ry/r )
	    DrawPoint( posx - x * rx/r, posy - y * ry/r )
	    DrawPoint( posx - y * rx/r, posy - x * ry/r )
	    DrawPoint( posx - y * rx/r, posy + x * ry/r )
	    DrawPoint( posx - x * rx/r, posy + y * ry/r )

	    If d < 0
	       d= d + ddf_x
	       ddf_x= ddf_x+ 2
	       ddf_y=ddf_y+ 2
	       x=x + 1
	    Else
	       d= d+ ddf_y
	       ddf_x=ddf_x+ 2
	       ddf_y=ddf_y+ 4
	       x=x+ 1
	       y=y- 1
	    EndIf
	Wend
End Function

#Rem monkeydoc
	### READY TO USE ###~n
	This Function Draws a Grid at the Position _X,_Y with the Dimensions _Witdth and _Height and the number of cells in x and y direction
	You must call this within the OnRender() Method
#End
Function Drw_Grid:Void(_X:Float,_Y:Float,_Width:Float,_Height:Float,_CellsX:Int,_CellsY:Int)
	If MANIAC_DEBUG = True
		Maniac_Debug.addTotDraws(2*cntx*cnty)
	endif
	'zeichnet ein Gitter an Position posx,posy (links oben), w/h breite bzw. hÃƒÂ¶he (des gesamten Grids) und zieht dabei cntx/cnty striche in der horizontalen,bzw vertikalen
	'allerdings wird hierbei das Gitter automatisch angepasst

	'1. bestimmen der breite eines KÃƒÂ¤stchens anhand der Breite und der anzahl
	Local cell_w:Float = _Width/_CellsX
	Local cell_h:Float = _Height/_CellsY

	For Local x:Int = 1 To cntx-1
		For Local y:Int = 1 To cnty-1

			'Vertikale
			DrawLine(_X+x*cell_w,_Y,_X+x*cell_w,_Y+cnty*cell_h)

			'Horizontale
			DrawLine(_X,_Y+y*cell_h,_X+cntx*cell_w,_Y+y*cell_h)

		Next
	Next

End Function

#Rem monkeydoc
	### READY TO USE ###~n
	This Function Draws a "Star-Bar" @ _X,_Y with the Dimensions _Witdth and _Height and the number of _MaxStars.~n
	_FullStars is the number of Colored Stars from Left
	You must call this within the OnRender() Method
#End
Function Drw_Stars(_X:Float,_Y:Float,_Width:Float,_Height:Float,_MaxStars:Int = 5,_FullStars:Int = 3)
	Local starWidth:Float = ll_Width(_Width,_MaxStars,5)

	For Local i:Int = 0 Until _MaxStars
		If i < _FullStars
			SetColor 255,0,0
		Else
			SetColor 75,75,75
		Endif

		DrawImage MANIAC_IMG_STAR, _X + 5 + i*(starWidth+5), _Y+5, 0 , starWidth/MANIAC_IMG_STAR.Width(),_Height/MANIAC_IMG_STAR.Height()
	Next
End Function

Function Drw_LoadingBar(_X:Float,_Y:Float,_Width:Float,_Height:Float,_Caption:String,_Prozent:Float)
	If _Prozent >= 0.0 And _Prozent <= 1.0
		SetColor 75,75,75
		DrawRect(_X,_Y,_Width*_Prozent,_Height)

		SetColor 255,255,255
		Drw_Rect(_X,_Y,_Width,_Height,2)

		SetColor 255,0,0
		Local l:Int = MANIAC_FONT.getW(( Int(_Prozent*100))+ " %")
		MANIAC_FONT.Wrap((Int(_Prozent*100))+ " %",_X+_Width*0.5-l/2+1,_Y,_Width,_Height,15)
	Endif
End Function

#Rem monkeydoc
	### READY TO USE ###~n
	This Function Draws a Loading-Bar at the Position _X,_Y with the Dimensions _Witdth and _Height
	You must call this within the OnRender() Method
#End
Function Drw_LoadingBar(_X:Float,_Y:Float,_Width:Float,_Height:Float,_Caption:String,_CurrValue:Float,_MaxValue:Float)
	Local pr:Float = _CurrValue/_MaxValue

	SetColor 75,75,75
	DrawRect(_X,_Y,_Width*pr,_Height)

	SetColor 255,255,255
	Drw_Rect(_X,_Y,_Width,_Height,2)

	SetColor 255,0,0
	Local l:Int = MANIAC_FONT.getW(( Int(pr*100))+ " %")
	MANIAC_FONT.Wrap((Int(pr*100))+ " %",_X+_Width*0.5-l/2+1,_Y,_Width,_Height,15)
End Function

#Rem monkeydoc
	This Functions Draws an LoadingBar @ position ix,iy with w,h in Pixels
	istartTime is the Beginning Time, length is the max Time (both in ms)
#End
Function Drw_TimingBar(ix:Int,iy:Int,w:Int,h:Int,istartTime:Int,ilengthTime:Int,iStyle:Int = 0)

	Duke_Drw_Rect(ix,iy,w,h,2)
	Local lw:Int = ( ( Millisecs()-istartTime ) * w ) / ilengthTime
	If iStyle = 0
		DrawRect(ix,iy,w-lw,h)
	Elseif iStyle = 1
		DrawRect(ix,iy,w-lw,h)
	Endif

End Function

#Rem monkeydoc
	### READY TO USE ###~n
	Draw 2d Lightning.
	Pass the starting and ending points.  Depth parameters refers to recursion.  Don't want to blow the stack!

	You must call this within the OnRender() Method
	Example:
	<pre>
		'Within the On Render you jast call the Lightning
		Method OnRender:Int()
			Cls
			Drw_Lightning(0,0,DW*0.5,DH*0.5)
			Return 0
		End
	</pre>

	Credits:
	this Code is from http://www.blitzbasic.com/codearcs/codearcs.php?code=3119
	Matt Lloyd Lightning Implementation.
	and is translated into monkey by Stephan D
	Free To use as you wish. Play around with the parameters.
#End
Function Drw_Lightning(sx#,sy#,fx#,fy#,depth=4)

	'Local dx#,dy#,dist#,ox#,oy#,x#,y#,udx#,udy#
	Local i

	'play around with these numbers to see the effects
	Local shakiness#=-2.5 ;
	Local branchchance=6;
	Local wr1 = 16
	Local wr2 = 16
	Local hr1 = 4
	Local hr2 = 24

	If(depth<=0) Then Return ';;as said - don't want to go too deep in the stack...

	Local dx#=fx-sx
	Local dy#=fy-sy
	Local dist#=Sqrt(dx*dx+dy*dy)

	If(dist=0) Then Return ' ;no need To do any lightning If our start And ending points are on top of each other...And also avoid nasty division by zeroes...

	Local udx#=dx/dist'	;unit vectors in direction of lightning...
	Local udy#=dy/dist

	Local x#=sx
	Local y#=sy
	Local ox#=x
	Local oy#=y

	For i=1 To dist
		If MANIAC_DEBUG = True
			Maniac_Debug.addTotDraws(5)
		endif
		x=x+udx+Rnd(-shakiness,shakiness)
		y=y+udy+Rnd(-shakiness,shakiness)

		ll_ColorCentre()
		DrawLine x,y,ox,oy

		ll_ColorInnerEdge()
		DrawLine x-udy,y+udx, ox-udy,oy+udx
		DrawLine x+udy,y-udx,ox+udy,oy-udx

		ll_ColorOuterEdge()
		DrawLine x-udy*2.0,y+udx*2.0, ox-udy*2.0,oy+udx*2.0
		DrawLine x+udy*2.0,y-udx*2.0,ox+udy*2.0,oy-udx*2.0

		ox=x
		oy=y

		If(Rnd(1,100)<branchchance) Then
			If MANIAC_DEBUG = True
				Maniac_Debug.addTotDraws()
			endif
			Drw_Lightning(ox,oy,ox+Rnd(-wr1,wr2),oy+Rnd(-hr1,hr2),depth-1)
		EndIf

	Next
End Function

Const COLOR_BLACK:Int 		= 	0
Const COLOR_GRAY:Int		=	4
Const COLOR_WHITE:Int		= 	9
Const COLOR_RED:Int			=	10
Const COLOR_GREEN:Int		=	20
Const COLOR_DARKGREEN:Int 	= 	27
Const COLOR_BLUE:Int		= 	30
Const COLOR_YELLOW:Int 		= 	40
Const COLOR_ORANGE:Int 		= 	50
Const COLOR_MAGENTA:Int		= 	60
Const COLOR_BROWN:Int		= 	70
Const COLOR_PURPLE:Int		= 	80

Const COLOR_PLAYER1:Int =  801
Const COLOR_PLAYER2:Int =  802
Const COLOR_PLAYER3:Int	=  803
Const COLOR_PLAYER4:Int =  804

#Rem monkeydoc
	### EXPERIMENTAL ### ~n
	This Function sets the Render-Color to a predefined color by The Maniac-Color-Consts.
	You can find the Colors in the Functions Section.~n
	Details:
	COLOR_BLACK = 0, COLOR_GRAY = 4, COLOR_WHITE = 9
	COLOR_RED = 10 To 19 ; 10 is 255,0,0, the part of Red decreases by higher ID
	So, every COlOR has 10 brightnes grades.
	You can use it like

	Duke_Color2(COLOR_GREEN + brightness), whereas brightness can be an int Value between 0 and 9
	so, COLOR_GREEN + 8 is a very dark green
#End
Function Maniac_Color(_Color:Int)
	'Maniac_Debug.addCall()
	Select _Color
		Case 0	'Schwarz
			SetColor 0,0,0
		Case 1
			SetColor 50,50,50
		Case 2
			SetColor 75,75,75
		Case 3
			SetColor 100,100,100
		Case 4
			SetColor 125,125,125
		Case 5
			SetColor 150,150,150
		Case 6
			SetColor 175,175,175
		Case 7
			SetColor 200,200,200
		Case 8
			SetColor 225,225,225
		Case 9	'Weiss
			SetColor 255,255,255

			'### ROT ### colors 10-19
		Case 10
			SetColor 255,0,0
		Case 11
			SetColor 230,0,0
		Case 12
			SetColor 210,0,0
		Case 13
			SetColor 190,0,0
		Case 14
			SetColor 170,0,0
		Case 14
			SetColor 150,0,0
		Case 15
			SetColor 130,0,0
		Case 16
			SetColor 110,0,0
		Case 17
			SetColor 90,0,0
		Case 18
			SetColor 70,0,0
		Case 19
			SetColor 50,0,0

			'### GRUEN ### 20-29
		Case 20
			SetColor 0,255,0
		Case 21
			SetColor 0,230,0
		Case 22
			SetColor 0,210,0
		Case 23
			SetColor 0,190,0
		Case 24
			SetColor 0,170,0
		Case 25
			SetColor 0,150,0
		Case 26
			SetColor 0,130,0
		Case 27
			SetColor 0,110,0
		Case 28
			SetColor 0,90,0
		Case 29
			SetColor 0,70,0

			'### BLAU ###
		Case 30
			SetColor 0,0,255
		Case 31
			SetColor 0,0,230
		Case 32
			SetColor 0,0,210
		Case 33
			SetColor 0,0,190
		Case 34
			SetColor 0,0,170
		Case 35
			SetColor 0,0,150
		Case 36
			SetColor 0,0,130
		Case 37
			SetColor 0,0,110
		Case 38
			SetColor 0,0,90
		Case 39
			SetColor 0,0,70

			'### GELB ###
		Case 40
			SetColor 255,255,0
		Case 41
			SetColor 255,255,120
		Case 42
			SetColor 255,255,50
		Case 43
			SetColor 215,215,0

		'###	ORANGE ###
		Case 50
			SetColor 255,140,0

		'### MAGENTA ###
		Case 60
			SetColor 255,0,255

		'### BROWN ###
		Case 70
			SetColor 165,42, 42

		'### PURPLE +####
		Case 80
			SetColor 75,0,130

		Case COLOR_PLAYER1
			SetColor 0,0,255

		Case COLOR_PLAYER2
			SetColor 0,255,0

		Case COLOR_PLAYER3
			SetColor 255,0,0

		Case COLOR_PLAYER4
			SetColor 255,255,255

	End Select
End Function

Const IMGEFFECT_MIRRORX:Int = 1
Const IMGEFFECT_MIRRORY:Int = 2

Const IMGEFFECT_ROTATE_SHEARX45:Int = 7

Const IMGANIMAGION_FADE_IN:Int = 3
Const IMGANIMATION_DROP_IN:Int = 4
Const IMGANIMATION_SPIRAL_IN:Int = 5
Const IMGANIMATION_WAVE_IN:Int = 6

Const IMGGLOW_STYLE_SIN:Int 	= 0

Const IMG_ALIGN_LEFT:Int		= 0
Const IMG_ALIGN_MIDDLE:Int		= 1
Const IMG_ALIGN_RIGHT:Int		= 2

Const IMG_ALIGN_ONTOP:Int		= 3
Const IMG_ALIGN_TOP:Int			= 4
Const IMG_ALIGN_BOTTOM:Int		= 5
Const IMG_ALIGN_UNDERBOTTOM:Int	= 6

#Rem monkeydoc
	This is kind of an extended mojo Image.~n
	It provides some additional features.

	-InstantEffects:
		- Glow
		- Shearing,rotation & stuff

	-Complex-Animations

	-MoveAnimation

	BUGLIST:
		The Caption is not rendered correctly with RenderMode - Done
#End
Class ManiacImage
	Field MidX:Float,MidY:Float,Width:Float,Height:Float
	Field Caption:String
	Field CaptionColor:Int		'Color of the Caption
	Field AlignX:Int
	Field AlignY:Int

	Field img:Image
	Field bFramed:Bool = False
	Field bBlink = True
	Field Color:Int = 9
	Field angle:Float =0.0
	Field mode:Int = 0

	'### Glow Effects ###
	Field bGlow:Bool  = False
	Field GlowAlpha:Float
	Field HertzAlpha:Float 		'
	Field AlphaFrom:Float		= 0.2
	Field AlphaTo:Float			= 0.95
	Field GlowStyle:Int		= 0	'0 - If Alpha reases max, it decreases from max ; 1 - if Alpha reaches max, it jumps to min
	Field bAlphaDirection:Bool = True		'if True, Alpha raises, if false, Alpha decreases
	Field HertzIncreaseeAlpha:Float	=0.4
	Field HertzDecreaseAlpha:Float	=1

	Field AddWidthByMO:Int 		= 0
	Field AddHeightByMO:Int		= 0
	Field Scale:Float = 1.0

	#Rem monkeydoc
		Creates a new ManiacImage.
		midX and midy are both the midhandled coordiantes of the image.
		String the is Sourcepath to the Image
		_Caption if wanted is will be shown withing the Image
	#End
	Method New(midx:Float,midy:Float,width:Float,height:Float,Path:String,_Caption:String="",_AlignX:Int = 0,_AlignY:Int = 3,_Hertz:Float = 1.0 )
		img = LoadImage(Path)
		MidX = midx
		MidY = midy
		Width = width
		Height = height
		Caption = _Caption
		CaptionColor = COLOR_BLUE
		AlignX = _AlignX
		AlignY = _AlignY
		HertzAlpha = _Hertz
		mode = 0
	End Method

	Method setCaption:Void(_Caption:String,_AlignX:Int,_AlignY:int)
		Caption = _Caption
	End Method

	Method setMode(_mode:Int)
		mode = _mode
	End Method

	Method getMode:Int()
		Return mode
	End Method

	Method setGlow(_isGlowing:Bool = True)
		bGlow = _isGlowing
	End Method

	Method setCostomMode(shearx:Int,sheary:Int,anglespeed:Float=4.0,scale:Float = 1.0)

	End Method

	Method setFrame(_isFramed:Bool = True,_FrameColor:Int = 0)
		bFramed = _isFramed
		FrameColor = _FrameColor
	End Method

	Method Draw()

		If bGlow = True
			If bAlphaDirection = True
				GlowAlpha += EqToFPS(HertzIncreaseeAlpha)
				If GlowAlpha >= AlphaTo
					If GlowStyle = 0
						bAlphaDirection = False
					Elseif GlowStyle = 1
						bAlphaDirection = True
						GlowAlpha = AlphaFrom
					Endif
				Endif
			Else
				GlowAlpha -= EqToFPS(HertzDecreaseAlpha)
				If GlowAlpha <= AlphaFrom
					If GlowStyle = 0
						bAlphaDirection = true
					Elseif GlowStyle = 1
						bAlphaDirection = false
						GlowAlpha = AlphaTo
					Endif
				Endif
			Endif
		Endif

		'
		'DrawText "mode: " +mode, 300,200
		Select mode
            Case IMGEFFECT_MIRRORX
                MirrorXAt(MidX, MidY)
            Case IMGEFFECT_MIRRORY
                MirrorYAt(MidX, MidY)

            Case 3
                angle += EqToFPS(45)
                ScaleAt(MidX, MidY, 0.6, 0.6)
                ShearXAt(MidX, MidY, Cos(angle))
                ShearYAt(MidX,MidY,	angle)
                RotateAt(MidX, MidY, angle)

            Case 4
                ShearXAt(MidX, MidY, Sin(angle))
            Case 5
                ShearYAt(MidX, MidY, -angle)
            Case 6
                ShearXAt(MidX, MidY, 30)
                ShearYAt(MidX, MidY, 30)

            Case IMGEFFECT_ROTATE_SHEARX45
                'ScaleAt(MidX, MidY, 1, 0.3)
                ShearXAt(MidX, MidY, 45)
                RotateAt(MidX, MidY, angle)
            Case 8
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 0.3)
                RotateAt(MidX, MidY, -angle)
                ShearXAt(MidX, MidY, 45)
                ShearYAt(MidX, MidY, 45)
                RotateAt(MidX, MidY, angle)
            Case 9
            	angle += EqToFPS(180)
                RotateAt(MidX, MidY, -angle)
                ShearXAt(MidX, MidY, 45)
                ShearYAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 10
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 0.1)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 11
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 0.2)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 12
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 0.4)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 13
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 0.8)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 14
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 1.6)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 15
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 3.2)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 16
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 6.4)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 17
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 3, 1)
                ShearYAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, -angle)
            Case 18
            	angle += EqToFPS(180)
                If angle=160 Then angle = 0
                ShearXAt(MidX, MidY, angle-80)
            Case 19
            	angle += EqToFPS(180)
                If angle=160 Then angle = 0
                ShearYAt(MidX, MidY, angle-80)
            Case 20
            	angle += EqToFPS(180)
                If angle=160 Then angle = 0
                ShearXAt(MidX, MidY,-angle+80)
                ShearYAt(MidX, MidY, angle-80)
            Case 21
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, Sin(angle))
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 22
            	angle += ATan(EqToFPS(180))
                ScaleAt(MidX, MidY, 1, Sin(angle))
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)

        End Select

        Maniac_Color(Color)
        '###### GLOW EFFECT STUFF #####
		If bGlow = true
			SetAlpha GlowAlpha
			DrawImage MANIAC_IMG_FRAME_BLUR, MidX,MidY,angle,Width*1.3/MANIAC_IMG_FRAME_BLUR.Width(),Height*1.3/MANIAC_IMG_FRAME_BLUR.Height()
		End If

        DrawImage img,MidX-Width*0.5,MidY-Height*0.5,0,Width/img.Width(),Height/img.Height()

        '###### BUTTON FRAME ########
		If bFramed = True
			'Maniac_Color(FrameColor)
			DrawImage MANIAC_IMG_FRAME_RAW , MidX,MidY,angle,(Width+AddWidthByMO)/MANIAC_IMG_FRAME_RAW.Width(),(Height+AddHeightByMO)/MANIAC_IMG_FRAME_RAW.Height()
		Endif

        '##### DRAWING THE CAPTION TO THE BUTTON #####
		SetAlpha 1
		Maniac_Color(CaptionColor)
		Select AlignX
			Case IMG_ALIGN_LEFT
				MANIAC_FONT.Wrap(Caption,MidX-Width/2,MidY-Height/5,Width,Height,Caption.Length())
				ResetMatrix()
			Case IMG_ALIGN_MIDDLE
				Local l:Int = MANIAC_FONT.getW(Caption)
				MANIAC_FONT.Wrap(Caption,MidX-l/2+1,MidY-Height/5,Width,Height,Caption.Length())
				ResetMatrix()
			Case IMG_ALIGN_RIGHT
				Local l:Int = MANIAC_FONT.getW(Caption)
				MANIAC_FONT.Wrap(Caption,MidX+Width/2-l,MidY-Height/5,Width,Height,Caption.Length())
				ResetMatrix()
		End Select

        ResetMatrix()

        SetAlpha 1
	End Method

End Class


SetScissor XNA bug fixed native in Monkey v58

Strict

Import flxextern
Import flxpoint
Import flxrect
Import flxbasic
Import flxobject
Import flxg

Import system.flxcolor

Class FlxCamera Extends FlxBasic

	Global ClassObject:FlxClass = New FlxCameraClass()

	Const STYLE_LOCKON:Int = 0

	Const STYLE_PLATFORMER:Int = 1

	Const STYLE_TOPDOWN:Int = 2

	Const STYLE_TOPDOWN_TIGHT:Int = 3

	Const SHAKE_BOTH_AXES:Int = 0

	Const SHAKE_HORIZONTAL_ONLY:Int = 1

	Const SHAKE_VERTICAL_ONLY:Int  = 2

	Global DefaultZoom:Float

	Field target:FlxObject

	Field deadzone:FlxRect

	Field bounds:FlxRect

	Field scroll:FlxPoint

	Field _color:FlxColor

Private
	Const _MIN_FLOAT_VALUE:Float = .0000001

	Field _x:Float

	Field _y:Float

	Field _realX:Float

	Field _realY:Float

	Field _width:Float

	Field _height:Float

	Field _realWidth:Float

	Field _realHeight:Float

	Field _zoom:Float

	Field _point:FlxPoint

	Field _alpha:Float

	Field _scaleX:Float

	Field _scaleY:Float

	Field _angle:Float

	Field _clipped:Bool

	Field _bgColor:FlxColor

	Field _fxFlashColor:Int

	Field _fxFlashDuration:Float

	Field _fxFlashComplete:FlxCameraFlashListener

	Field _fxFlashAlpha:Float

	Field _fxFadeColor:Int

	Field _fxFadeDuration:Float

	Field _fxFadeComplete:FlxCameraFadeListener

	Field _fxFadeAlpha:Float

	Field _fxShakeIntensity:Float

	Field _fxShakeDuration:Float

	Field _fxShakeComplete:FlxCameraShakeListener

	Field _fxShakeOffset:FlxPoint

	Field _fxShakeDirection:Int

	Field _fill:FlxColor

	Field _id:Int

	Global _Inkrement:Int

Public
	Method New(x:Int, y:Int, width:Int, height:Int, zoom:Float = 0)
		Zoom = zoom 'must be first for init
		X = x
		Y = y
		Width = width
		Height = height
		target = Null
		deadzone = Null
		scroll = New FlxPoint()
		_point = New FlxPoint()
		bounds = Null
		_bgColor = New FlxColor(FlxG.BgColor())
		_color = New FlxColor()
		_alpha = 1

		_fxFlashColor = 0
		_fxFlashDuration = 0
		_fxFlashComplete = null
		_fxFlashAlpha = 0

		_fxFadeColor = 0
		_fxFadeDuration = 0
		_fxFadeComplete = Null
		_fxFadeAlpha = 0

		_fxShakeIntensity = 0
		_fxShakeDuration = 0
		_fxShakeComplete = Null
		_fxShakeOffset = New FlxPoint()
		_fxShakeDirection = 0

		active = True

		_fill = New FlxColor(0)

		_id = _Inkrement
		_Inkrement += 1
	End Method

	Method Destroy:Void()
		target = Null
		scroll = Null
		deadzone = Null
		bounds = Null
		_color = Null
		_bgColor = Null
		_fxFlashComplete = Null
		_fxFadeComplete = Null
		_fxShakeComplete = Null
		_fxShakeOffset = Null
		_fill = Null
	End Method

	Method Lock:Void()
		If (_clipped) Then
			If (_fxShakeOffset.x <> 0 Or _fxShakeOffset.y <> 0) Then
				SetScissor(_realX + _fxShakeOffset.x * FlxG._DeviceScaleFactorX, _realY + _fxShakeOffset.y * FlxG._DeviceScaleFactorY, _realWidth, _realHeight)
			Else
				SetScissor(_realX, _realY, _realWidth, _realHeight)
			End If
		End If

		PushMatrix()

		Translate(_x + _fxShakeOffset.x, _y + _fxShakeOffset.y)
		Scale(_scaleX, _scaleY)

		If (_clipped Or _bgColor.argb <> FlxG._BgColor.argb)
			SetColor(_bgColor.r, _bgColor.g, _bgColor.b)
			DrawRect(0, 0, _width, _height)
			FlxG._LastDrawingColor = _bgColor.argb
		End If
	End Method

	Method Unlock:Void()
		If (_fill.argb <> 0) Then
			If (_fill.argb <> FlxG._LastDrawingColor) Then
				SetColor(_fill.r, _fill.g, _fill.b)
				FlxG._LastDrawingColor = _fill.argb
			End if

			If (FlxG._LastDrawingAlpha <> _fill.a) Then
				SetAlpha(_fill.a)
				FlxG._LastDrawingAlpha = _fill.a
			End If

			DrawRect(0, 0, _width, _height)
		End If

		PopMatrix()
		_fill.SetARGB(0)

		If (_clipped) Then
			SetScissor(0, 0, FlxG.DeviceWidth, FlxG.DeviceHeight)
		End If
	End Method

	Method Update:Void()
		If (target <> Null) Then
			If (deadzone = Null) Then
				FocusOn(target.GetMidpoint(_point))
			Else
				Local edge:Float
				Local targetX:Float
				Local targetY:Float

				If (target.x > 0) Then
					targetX = target.x + 0.0000001
				Else
					targetX = target.x - 0.0000001
				End If

				If (target.y > 0) Then
					targetY = target.y + 0.0000001
				Else
					targetY = target.y - 0.0000001
				End If

				edge = targetX - deadzone.x
				If (scroll.x > edge) scroll.x = edge
				edge = targetX + target.width - deadzone.x - deadzone.width
				If (scroll.x < edge) scroll.x = edge

				edge  = targetY - deadzone.y
				If (scroll.y > edge) scroll.y = edge
				edge = targetY + target.height - deadzone.y - deadzone.height
				If (scroll.y < edge) scroll.y = edge
			End If
		End If

		If (bounds <> Null) Then
			If (scroll.x < bounds.Left) scroll.x = bounds.Left
			If (scroll.x > bounds.Right - _width) scroll.x = bounds.Right - _width
			If (scroll.y < bounds.Top) scroll.y = bounds.Top
			If (scroll.y > bounds.Bottom - _height) scroll.y = bounds.Bottom - _height
		End If

		If (_fxFlashAlpha > 0) Then
			_fxFlashAlpha -= FlxG.Elapsed / _fxFlashDuration

			If (_fxFlashAlpha <= 0 And _fxFlashComplete <> Null) Then
				_fxFlashComplete.OnFlashComplete()
				_fxFlashComplete = Null
			End If
		End If

		If (_fxFadeAlpha > 0 And _fxFadeAlpha < 1) Then
			_fxFadeAlpha += FlxG.Elapsed / _fxFadeDuration

			If (_fxFadeAlpha >= 1) Then
				_fxFadeAlpha = 1
				If (_fxFadeComplete <> Null) Then
					_fxFadeComplete.OnFadeComplete()
					_fxFadeComplete = Null
				End If
			End If
		End If

		If (_fxShakeDuration > 0) Then
			_fxShakeDuration -= FlxG.Elapsed
			If (_fxShakeDuration <= 0) Then
				_fxShakeOffset.Make()

				If (_fxShakeComplete <> Null) Then
					_fxShakeComplete.OnShakeComplete()
					_fxShakeComplete = Null
				End If
			Else
				If (_fxShakeDirection = SHAKE_BOTH_AXES Or _fxShakeDirection = SHAKE_HORIZONTAL_ONLY) Then
					_fxShakeOffset.x = (FlxG.Random() * _fxShakeIntensity * _width * 2 - _fxShakeIntensity * _width) * _zoom
				End If

				If (_fxShakeDirection = SHAKE_BOTH_AXES Or _fxShakeDirection = SHAKE_VERTICAL_ONLY) Then
					_fxShakeOffset.y = (FlxG.Random() * _fxShakeIntensity * _height * 2 - _fxShakeIntensity * _height) * _zoom
				End If
			End If
		End If
	End Method

	Method Follow:Void(target:FlxObject, style:Int = STYLE_LOCKON)
		Self.target = target
		Local helper:Float

		Select (style)
			Case STYLE_PLATFORMER
				Local w:Float = _width / 8
				Local h:Float = _height / 3
				deadzone = New FlxRect((_width - w) / 2, (_height - h) / 2 - h * .25, w, h)

			Case STYLE_TOPDOWN
				helper = Max(_width, _height) / 4
				deadzone = New FlxRect((_width - helper) / 2, (_height - helper) / 2, helper, helper)

			Case STYLE_TOPDOWN_TIGHT
				helper = Max(_width, _height) / 8
				deadzone = New FlxRect((_width - helper) / 2, (_height - helper) / 2, helper, helper)

			Case STYLE_LOCKON
				deadzone = Null

			Default
				deadzone = Null
		End Select
	End Method

	Method FocusOn:Void(point:FlxPoint)
		If (point.x > 0) Then
			point.x += 0.0000001
		Else
			point.x -= 0.0000001
		End If

		If (point.y > 0) Then
			point.y += 0.0000001
		Else
			point.y -= 0.0000001
		End If

		scroll.Make(point.x - _width * .5, point.y - _height * .5)
	End Method

	Method SetBounds:Void(x:Float = 0, y:Float = 0, width:Float = 0, height:Float = 0, updateWorld:Bool = False)
		If (bounds = Null) bounds = New FlxRect()
		bounds.Make(x, y, width, height)
		If (updateWorld) FlxG.WorldBounds.CopyFrom(bounds)
		Update()
	End Method

	Method Flash:Void(color:Int = FlxG.WHITE, duration:Float = 1, onComplete:FlxCameraFlashListener = Null, force:Bool = False)
		If (Not force And _fxFlashAlpha > 0) Return

		_fxFlashColor = color
		If (duration <= 0) duration = _MIN_FLOAT_VALUE
		_fxFlashDuration = duration
		_fxFlashComplete = onComplete
		_fxFlashAlpha = 1
	End Method

	Method Fade:Void(color:Int = FlxG.BLACK, duration:Float = 1, onComplete:FlxCameraFadeListener = Null, force:Bool = False)
		If (Not force And _fxFadeAlpha > 0)	Return

		_fxFadeColor = color
		If (duration <= 0) duration = _MIN_FLOAT_VALUE
		_fxFadeDuration = duration
		_fxFadeComplete = onComplete
		_fxFadeAlpha = _MIN_FLOAT_VALUE
	End Method

	Method Shake:Void(intensity:Float = 0.05, duration:Float = 0.5, onComplete:FlxCameraShakeListener = Null, force:Bool = True, direction:Int = SHAKE_BOTH_AXES)
		If (Not force And (_fxShakeOffset.x <> 0 Or _fxShakeOffset.y <> 0)) Return

		_fxShakeIntensity = intensity
		_fxShakeDuration = duration
		_fxShakeComplete = onComplete
		_fxShakeDirection = direction
		_fxShakeOffset.Make()
	End Method

	Method StopFX:Void()
		_fxFlashAlpha = 0
		_fxFadeAlpha = 0
		_fxShakeDuration = 0
		_fxShakeOffset.x = 0
		_fxShakeOffset.y = 0
	End Method

	Method CopyFrom:FlxCamera(camera:FlxCamera)
		If (camera.bounds = Null) Then
			bounds = camera.bounds
		Else
			If (bounds = Null) bounds = New FlxRect()
			bounds.CopyFrom(camera.bounds)
		End If

		target = camera.target
		If (target <> Null) Then
			If (camera.deadzone = Null) Then
				deadzone = Null
			Else
				If (deadzone = Null) deadzone = New FlxRect()
				deadzone.CopyFrom(camera.deadzone)
			End If
		End If

		Return Self
	End Method

	Method X:Float() Property
		Return _x
	End Method

	Method X:Void(x:Float) Property
		_x = x
		_realX = _x * FlxG._DeviceScaleFactorX

		_clipped = _IsClipped()
	End Method

	Method Y:Float() Property
		Return _y
	End Method

	Method Y:Void(y:Float) Property
		_y = y
		_realY = _y * FlxG._DeviceScaleFactorY

		_clipped = _IsClipped()
	End Method

	Method Width:Float() Property
		Return _width
	End Method

	Method Width:Void(width:Float) Property
		_width = width
		_realWidth = Min(Float(FlxG.DeviceWidth), Floor(_width * _scaleX * FlxG._DeviceScaleFactorX))

		_clipped = _IsClipped()
	End Method

	Method Height:Float() Property
		Return _height
	End Method

	Method Height:Void(height:Float) Property
		_height = height
		_realHeight = Min(Float(FlxG.DeviceHeight), Floor(_height * _scaleY * FlxG._DeviceScaleFactorY))

		_clipped = _IsClipped()
	End Method

	Method Zoom:Float() Property
		Return _zoom
	End Method

	Method Zoom:Void(zoom:Float) Property
		If (zoom = 0) Then
			_zoom = FlxCamera.DefaultZoom
		Else
			_zoom = zoom
		End If

		SetScale(_zoom, _zoom)
	End Method

	Method Alpha:Float() Property
		Return _alpha
	End Method

	Method Alpha:Void(alpha:Float) Property
		_alpha = alpha
	End Method

	Method Angle:Float() Property
		Return _angle
	End Method

	Method Angle:Void(angle:Float) Property
		_angle = angle
	End Method

	Method Color:Int() Property
		Return _color.argb
	End Method

	Method Color:Void(color:Int) Property
		_color.SetRGB(color)
	End Method

	Method BgColor:Int() Property
		Return _bgColor.argb
	End Method

	Method BgColor:Void(color:Int) Property
		_bgColor.SetARGB(color)
	End Method

	Method GetScale:FlxPoint()
		Return _point.Make(_scaleX, _scaleY)
	End Method

	Method SetScale:Void(x:Float, y:Float)
		_scaleX = x
		_scaleY = y
		_realWidth = Min(Float(FlxG.DeviceWidth), Floor(_width * _scaleX * FlxG._DeviceScaleFactorX))
		_realHeight = Min(Float(FlxG.DeviceHeight), Floor(_height * _scaleY * FlxG._DeviceScaleFactorY))
	End Method

	Method Fill:Void(color:Int, blendAlpha:Bool = True)
		If (blendAlpha) Then
			_fill.SetARGB(color)
		Else
			_fill.SetRGB(color)
		End If
	End Method

	Method DrawFX:Void()
		If (_fxFlashAlpha > 0) Then
			Local alphaComponent:Float

			alphaComponent = _fxFlashColor Shr 24
			If (alphaComponent <= 0) alphaComponent = $FF
			Fill(((alphaComponent * _fxFlashAlpha) Shl 24) + (_fxFlashColor & $00FFFFFF))
		End If

		If (_fxFadeAlpha > 0) Then
			Local alphaComponent:Float

			alphaComponent = _fxFadeColor Shr 24
			If (alphaComponent <= 0) alphaComponent = $FF
			Fill(((alphaComponent * _fxFadeAlpha) Shl 24) + (_fxFadeColor & $00FFFFFF))
		End If
	End Method

	Method ID:Int() Property
		Return _id
	End Method

	Method ToString:String()
		Return "FlxCamera"
	End Method

Private
	Method _IsClipped:Bool()
		Return _realX <> 0 Or _realY <> 0 Or _realWidth <> FlxG.DeviceWidth Or _realHeight <> FlxG.DeviceHeight
	End Method

End Class

Interface FlxCameraFlashListener

	Method OnFlashComplete:Void()

End Interface

Interface FlxCameraFadeListener

	Method OnFadeComplete:Void()

End Interface

Interface FlxCameraShakeListener

	Method OnShakeComplete:Void()

End Interface

Private
Class FlxCameraClass Implements FlxClass

	Method CreateInstance:Object()
		Return New FlxCamera()
	End Method

	Method InstanceOf:Bool(object:Object)
		Return FlxCamera(object) <> Null
	End Method

End Class

Strict

Import flxextern
Import flxpoint
Import flxrect
Import flxbasic
Import flxobject
Import flxg

Import system.flxcolor

Class FlxCamera Extends FlxBasic

	Global ClassObject:FlxClass = New FlxCameraClass()

	Const STYLE_LOCKON:Int = 0

	Const STYLE_PLATFORMER:Int = 1

	Const STYLE_TOPDOWN:Int = 2

	Const STYLE_TOPDOWN_TIGHT:Int = 3

	Const SHAKE_BOTH_AXES:Int = 0

	Const SHAKE_HORIZONTAL_ONLY:Int = 1

	Const SHAKE_VERTICAL_ONLY:Int  = 2

	Global DefaultZoom:Float

	Field target:FlxObject

	Field deadzone:FlxRect

	Field bounds:FlxRect

	Field scroll:FlxPoint

	Field _color:FlxColor

Private
	Const _MIN_FLOAT_VALUE:Float = .0000001

	Field _x:Float

	Field _y:Float

	Field _realX:Float

	Field _realY:Float

	Field _width:Float

	Field _height:Float

	Field _realWidth:Float

	Field _realHeight:Float

	Field _zoom:Float

	Field _point:FlxPoint

	Field _alpha:Float

	Field _scaleX:Float

	Field _scaleY:Float

	Field _angle:Float

	Field _clipped:Bool

	Field _bgColor:FlxColor

	Field _fxFlashColor:Int

	Field _fxFlashDuration:Float

	Field _fxFlashComplete:FlxCameraFlashListener

	Field _fxFlashAlpha:Float

	Field _fxFadeColor:Int

	Field _fxFadeDuration:Float

	Field _fxFadeComplete:FlxCameraFadeListener

	Field _fxFadeAlpha:Float

	Field _fxShakeIntensity:Float

	Field _fxShakeDuration:Float

	Field _fxShakeComplete:FlxCameraShakeListener

	Field _fxShakeOffset:FlxPoint

	Field _fxShakeDirection:Int

	Field _fill:FlxColor

	Field _id:Int

#If TARGET = "xna"
	Field _xnaRectHelper:FlxRect
#End

	Global _Inkrement:Int

Public
	Method New(x:Int, y:Int, width:Int, height:Int, zoom:Float = 0)
		Zoom = zoom 'must be first for init
		X = x
		Y = y
		Width = width
		Height = height
		target = Null
		deadzone = Null
		scroll = New FlxPoint()
		_point = New FlxPoint()
		bounds = Null
		_bgColor = New FlxColor(FlxG.BgColor())
		_color = New FlxColor()
		_alpha = 1

		_fxFlashColor = 0
		_fxFlashDuration = 0
		_fxFlashComplete = null
		_fxFlashAlpha = 0

		_fxFadeColor = 0
		_fxFadeDuration = 0
		_fxFadeComplete = Null
		_fxFadeAlpha = 0

		_fxShakeIntensity = 0
		_fxShakeDuration = 0
		_fxShakeComplete = Null
		_fxShakeOffset = New FlxPoint()
		_fxShakeDirection = 0

		active = True

		_fill = New FlxColor(0)

		_id = _Inkrement
		_Inkrement += 1

		#If TARGET = "xna"
			_xnaRectHelper = New FlxRect()
		#End
	End Method

	Method Destroy:Void()
		target = Null
		scroll = Null
		deadzone = Null
		bounds = Null
		_color = Null
		_bgColor = Null
		_fxFlashComplete = Null
		_fxFadeComplete = Null
		_fxShakeComplete = Null
		_fxShakeOffset = Null
		_fill = Null

	#If TARGET = "xna"
		_xnaRectHelper = Null
	#End
	End Method

	Method Lock:Void()
		If (_clipped) Then
		#If TARGET = "xna"
			_xnaRectHelper.Make(_realX, _realY, _realWidth, _realHeight)

			If (_fxShakeOffset.x <> 0) Then
				_xnaRectHelper.x += _fxShakeOffset.x * FlxG._DeviceScaleFactorX
			End If

			If (_fxShakeOffset.y <> 0) Then
				_xnaRectHelper.y += _fxShakeOffset.y * FlxG._DeviceScaleFactorY
			End If

			If (_xnaRectHelper.x < 0) Then
				_xnaRectHelper.width += _xnaRectHelper.x
				_xnaRectHelper.x = 0
			End If

			If (_xnaRectHelper.y < 0) Then
				_xnaRectHelper.height += _xnaRectHelper.y
				_xnaRectHelper.y = 0
			End If

			If (_xnaRectHelper.Right > FlxG.DeviceWidth) Then
				_xnaRectHelper.width -= _xnaRectHelper.Right - FlxG.DeviceWidth
			End If

			If (_xnaRectHelper.Bottom > FlxG.DeviceHeight) Then
				_xnaRectHelper.height -= _xnaRectHelper.Bottom - FlxG.DeviceHeight
			End If

			If (_xnaRectHelper.width > 0 And _xnaRectHelper.height > 0) Then
				SetScissor(_xnaRectHelper.x, _xnaRectHelper.y, _xnaRectHelper.width, _xnaRectHelper.height)
			End If
		#Else
			If (_fxShakeOffset.x <> 0 Or _fxShakeOffset.y <> 0) Then
				SetScissor(_realX + _fxShakeOffset.x * FlxG._DeviceScaleFactorX, _realY + _fxShakeOffset.y * FlxG._DeviceScaleFactorY, _realWidth, _realHeight)
			Else
				SetScissor(_realX, _realY, _realWidth, _realHeight)
			End If
		#End
		End If

		PushMatrix()

		Translate(_x + _fxShakeOffset.x, _y + _fxShakeOffset.y)
		Scale(_scaleX, _scaleY)

		If (_clipped Or _bgColor.argb <> FlxG._BgColor.argb)
			SetColor(_bgColor.r, _bgColor.g, _bgColor.b)
			DrawRect(0, 0, _width, _height)
			FlxG._LastDrawingColor = _bgColor.argb
		End If
	End Method

	Method Unlock:Void()
		If (_fill.argb <> 0) Then
			If (_fill.argb <> FlxG._LastDrawingColor) Then
				SetColor(_fill.r, _fill.g, _fill.b)
				FlxG._LastDrawingColor = _fill.argb
			End if

			If (FlxG._LastDrawingAlpha <> _fill.a) Then
				SetAlpha(_fill.a)
				FlxG._LastDrawingAlpha = _fill.a
			End If

			DrawRect(0, 0, _width, _height)
		End If

		PopMatrix()
		_fill.SetARGB(0)

		If (_clipped) Then
			SetScissor(0, 0, FlxG.DeviceWidth, FlxG.DeviceHeight)
		End If
	End Method

	Method Update:Void()
		If (target <> Null) Then
			If (deadzone = Null) Then
				FocusOn(target.GetMidpoint(_point))
			Else
				Local edge:Float
				Local targetX:Float
				Local targetY:Float

				If (target.x > 0) Then
					targetX = target.x + 0.0000001
				Else
					targetX = target.x - 0.0000001
				End If

				If (target.y > 0) Then
					targetY = target.y + 0.0000001
				Else
					targetY = target.y - 0.0000001
				End If

				edge = targetX - deadzone.x
				If (scroll.x > edge) scroll.x = edge
				edge = targetX + target.width - deadzone.x - deadzone.width
				If (scroll.x < edge) scroll.x = edge

				edge  = targetY - deadzone.y
				If (scroll.y > edge) scroll.y = edge
				edge = targetY + target.height - deadzone.y - deadzone.height
				If (scroll.y < edge) scroll.y = edge
			End If
		End If

		If (bounds <> Null) Then
			If (scroll.x < bounds.Left) scroll.x = bounds.Left
			If (scroll.x > bounds.Right - _width) scroll.x = bounds.Right - _width
			If (scroll.y < bounds.Top) scroll.y = bounds.Top
			If (scroll.y > bounds.Bottom - _height) scroll.y = bounds.Bottom - _height
		End If

		If (_fxFlashAlpha > 0) Then
			_fxFlashAlpha -= FlxG.Elapsed / _fxFlashDuration

			If (_fxFlashAlpha <= 0 And _fxFlashComplete <> Null) Then
				_fxFlashComplete.OnFlashComplete()
				_fxFlashComplete = Null
			End If
		End If

		If (_fxFadeAlpha > 0 And _fxFadeAlpha < 1) Then
			_fxFadeAlpha += FlxG.Elapsed / _fxFadeDuration

			If (_fxFadeAlpha >= 1) Then
				_fxFadeAlpha = 1
				If (_fxFadeComplete <> Null) Then
					_fxFadeComplete.OnFadeComplete()
					_fxFadeComplete = Null
				End If
			End If
		End If

		If (_fxShakeDuration > 0) Then
			_fxShakeDuration -= FlxG.Elapsed
			If (_fxShakeDuration <= 0) Then
				_fxShakeOffset.Make()

				If (_fxShakeComplete <> Null) Then
					_fxShakeComplete.OnShakeComplete()
					_fxShakeComplete = Null
				End If
			Else
				If (_fxShakeDirection = SHAKE_BOTH_AXES Or _fxShakeDirection = SHAKE_HORIZONTAL_ONLY) Then
					_fxShakeOffset.x = (FlxG.Random() * _fxShakeIntensity * _width * 2 - _fxShakeIntensity * _width) * _zoom
				End If

				If (_fxShakeDirection = SHAKE_BOTH_AXES Or _fxShakeDirection = SHAKE_VERTICAL_ONLY) Then
					_fxShakeOffset.y = (FlxG.Random() * _fxShakeIntensity * _height * 2 - _fxShakeIntensity * _height) * _zoom
				End If
			End If
		End If
	End Method

	Method Follow:Void(target:FlxObject, style:Int = STYLE_LOCKON)
		Self.target = target
		Local helper:Float

		Select (style)
			Case STYLE_PLATFORMER
				Local w:Float = _width / 8
				Local h:Float = _height / 3
				deadzone = New FlxRect((_width - w) / 2, (_height - h) / 2 - h * .25, w, h)

			Case STYLE_TOPDOWN
				helper = Max(_width, _height) / 4
				deadzone = New FlxRect((_width - helper) / 2, (_height - helper) / 2, helper, helper)

			Case STYLE_TOPDOWN_TIGHT
				helper = Max(_width, _height) / 8
				deadzone = New FlxRect((_width - helper) / 2, (_height - helper) / 2, helper, helper)

			Case STYLE_LOCKON
				deadzone = Null

			Default
				deadzone = Null
		End Select
	End Method

	Method FocusOn:Void(point:FlxPoint)
		If (point.x > 0) Then
			point.x += 0.0000001
		Else
			point.x -= 0.0000001
		End If

		If (point.y > 0) Then
			point.y += 0.0000001
		Else
			point.y -= 0.0000001
		End If

		scroll.Make(point.x - _width * .5, point.y - _height * .5)
	End Method

	Method SetBounds:Void(x:Float = 0, y:Float = 0, width:Float = 0, height:Float = 0, updateWorld:Bool = False)
		If (bounds = Null) bounds = New FlxRect()
		bounds.Make(x, y, width, height)
		If (updateWorld) FlxG.WorldBounds.CopyFrom(bounds)
		Update()
	End Method

	Method Flash:Void(color:Int = FlxG.WHITE, duration:Float = 1, onComplete:FlxCameraFlashListener = Null, force:Bool = False)
		If (Not force And _fxFlashAlpha > 0) Return

		_fxFlashColor = color
		If (duration <= 0) duration = _MIN_FLOAT_VALUE
		_fxFlashDuration = duration
		_fxFlashComplete = onComplete
		_fxFlashAlpha = 1
	End Method

	Method Fade:Void(color:Int = FlxG.BLACK, duration:Float = 1, onComplete:FlxCameraFadeListener = Null, force:Bool = False)
		If (Not force And _fxFadeAlpha > 0)	Return

		_fxFadeColor = color
		If (duration <= 0) duration = _MIN_FLOAT_VALUE
		_fxFadeDuration = duration
		_fxFadeComplete = onComplete
		_fxFadeAlpha = _MIN_FLOAT_VALUE
	End Method

	Method Shake:Void(intensity:Float = 0.05, duration:Float = 0.5, onComplete:FlxCameraShakeListener = Null, force:Bool = True, direction:Int = SHAKE_BOTH_AXES)
		If (Not force And (_fxShakeOffset.x <> 0 Or _fxShakeOffset.y <> 0)) Return

		_fxShakeIntensity = intensity
		_fxShakeDuration = duration
		_fxShakeComplete = onComplete
		_fxShakeDirection = direction
		_fxShakeOffset.Make()
	End Method

	Method StopFX:Void()
		_fxFlashAlpha = 0
		_fxFadeAlpha = 0
		_fxShakeDuration = 0
		_fxShakeOffset.x = 0
		_fxShakeOffset.y = 0
	End Method

	Method CopyFrom:FlxCamera(camera:FlxCamera)
		If (camera.bounds = Null) Then
			bounds = camera.bounds
		Else
			If (bounds = Null) bounds = New FlxRect()
			bounds.CopyFrom(camera.bounds)
		End If

		target = camera.target
		If (target <> Null) Then
			If (camera.deadzone = Null) Then
				deadzone = Null
			Else
				If (deadzone = Null) deadzone = New FlxRect()
				deadzone.CopyFrom(camera.deadzone)
			End If
		End If

		Return Self
	End Method

	Method X:Float() Property
		Return _x
	End Method

	Method X:Void(x:Float) Property
		_x = x
		_realX = _x * FlxG._DeviceScaleFactorX

		_clipped = _IsClipped()
	End Method

	Method Y:Float() Property
		Return _y
	End Method

	Method Y:Void(y:Float) Property
		_y = y
		_realY = _y * FlxG._DeviceScaleFactorY

		_clipped = _IsClipped()
	End Method

	Method Width:Float() Property
		Return _width
	End Method

	Method Width:Void(width:Float) Property
		_width = width
		_realWidth = Min(Float(FlxG.DeviceWidth), Floor(_width * _scaleX * FlxG._DeviceScaleFactorX))

		_clipped = _IsClipped()
	End Method

	Method Height:Float() Property
		Return _height
	End Method

	Method Height:Void(height:Float) Property
		_height = height
		_realHeight = Min(Float(FlxG.DeviceHeight), Floor(_height * _scaleY * FlxG._DeviceScaleFactorY))

		_clipped = _IsClipped()
	End Method

	Method Zoom:Float() Property
		Return _zoom
	End Method

	Method Zoom:Void(zoom:Float) Property
		If (zoom = 0) Then
			_zoom = FlxCamera.DefaultZoom
		Else
			_zoom = zoom
		End If

		SetScale(_zoom, _zoom)
	End Method

	Method Alpha:Float() Property
		Return _alpha
	End Method

	Method Alpha:Void(alpha:Float) Property
		_alpha = alpha
	End Method

	Method Angle:Float() Property
		Return _angle
	End Method

	Method Angle:Void(angle:Float) Property
		_angle = angle
	End Method

	Method Color:Int() Property
		Return _color.argb
	End Method

	Method Color:Void(color:Int) Property
		_color.SetRGB(color)
	End Method

	Method BgColor:Int() Property
		Return _bgColor.argb
	End Method

	Method BgColor:Void(color:Int) Property
		_bgColor.SetARGB(color)
	End Method

	Method GetScale:FlxPoint()
		Return _point.Make(_scaleX, _scaleY)
	End Method

	Method SetScale:Void(x:Float, y:Float)
		_scaleX = x
		_scaleY = y
		_realWidth = Min(Float(FlxG.DeviceWidth), Floor(_width * _scaleX * FlxG._DeviceScaleFactorX))
		_realHeight = Min(Float(FlxG.DeviceHeight), Floor(_height * _scaleY * FlxG._DeviceScaleFactorY))
	End Method

	Method Fill:Void(color:Int, blendAlpha:Bool = True)
		If (blendAlpha) Then
			_fill.SetARGB(color)
		Else
			_fill.SetRGB(color)
		End If
	End Method

	Method DrawFX:Void()
		If (_fxFlashAlpha > 0) Then
			Local alphaComponent:Float

			alphaComponent = _fxFlashColor Shr 24
			If (alphaComponent <= 0) alphaComponent = $FF
			Fill(((alphaComponent * _fxFlashAlpha) Shl 24) + (_fxFlashColor & $00FFFFFF))
		End If

		If (_fxFadeAlpha > 0) Then
			Local alphaComponent:Float

			alphaComponent = _fxFadeColor Shr 24
			If (alphaComponent <= 0) alphaComponent = $FF
			Fill(((alphaComponent * _fxFadeAlpha) Shl 24) + (_fxFadeColor & $00FFFFFF))
		End If
	End Method

	Method ID:Int() Property
		Return _id
	End Method

	Method ToString:String()
		Return "FlxCamera"
	End Method

Private
	Method _IsClipped:Bool()
		Return _realX <> 0 Or _realY <> 0 Or _realWidth <> FlxG.DeviceWidth Or _realHeight <> FlxG.DeviceHeight
	End Method

End Class

Interface FlxCameraFlashListener

	Method OnFlashComplete:Void()

End Interface

Interface FlxCameraFadeListener

	Method OnFadeComplete:Void()

End Interface

Interface FlxCameraShakeListener

	Method OnShakeComplete:Void()

End Interface

Private
Class FlxCameraClass Implements FlxClass

	Method CreateInstance:Object()
		Return New FlxCamera()
	End Method

	Method InstanceOf:Bool(object:Object)
		Return FlxCamera(object) <> Null
	End Method

End Class


framerecord fixed

framerecord fixed

Strict

Import keyrecord
Import xyrecord
Import xyzrecord

Class FrameRecord

	Field frame:Int

	Field keys:Stack<KeyRecord>

	Field mouse:XYRecord

	Field joystick:Stack<XYZRecord[]>

	Field touch:Stack<XYRecord>

	Field accel:XYZRecord

	Method New()
		frame = 0
		keys = Null
		mouse = Null
	End Method

	Method Create:FrameRecord(frame:Int, keys:Stack<KeyRecord> = Null, mouse:XYRecord = Null, joystick:Stack<XYZRecord[]> = Null, touch:Stack<XYRecord> = Null, accel:XYZRecord = Null)
		Self.frame = frame
		Self.keys = keys
		Self.mouse = mouse
		Self.joystick = joystick
		Self.touch = touch
		Self.accel = accel

		Return Self
	End Method

	Method Destroy:Void()
		keys = Null
		mouse = Null
		joystick = Null
		touch = Null
		accel = Null
	End Method

	Method Save:String()
		Return Save(New StringStack()).Join("")
	End Method

	Method Save:StringStack(output:StringStack)
		output.Push(frame + "k")

		If (keys <> Null) Then
			Local key:KeyRecord
			Local i:Int = 0
			Local l:Int = keys.Length()

			While (i < l)
				If (i > 0) output.Push(",")

				key = keys.Get(i)

				output.Push(key.code + ":" + key.value)

				i += 1
			Wend
		End If

		output.Push("m")

		If (mouse <> Null) Then
			output.Push(mouse.x + "," + mouse.y)
		End If

		output.Push("j")

		If (joystick <> Null) Then
			Local i:Int = 0
			Local l:Int = joystick.Length()
			Local xyzArray:XYZRecord[]

			While (i < l)
				If (i > 0) output.Push(",")
				output.Push(i)

				xyzArray = joystick.Get(i)
				For Local index:Int = 0 Until xyzArray.Length()
					If (xyzArray[index] = Null) xyzArray[index] = New XYZRecord(0, 0, 0)

					output.Push(":" + xyzArray[index].x + ":" + xyzArray[index].y + ":" + xyzArray[index].z)
				Next

				i += 1
			Wend
		End If

		output.Push("t")

		If (touch <> Null) Then
			Local i:Int = 0
			Local l:Int = touch.Length()
			Local xy:XYRecord

			While (i < l)
				xy = touch.Get(i)
				If (xy = Null) Exit

				If (i > 0) output.Push(",")
				output.Push(xy.x + ":" + xy.y)

				i += 1
			Wend
		End If

		output.Push("a")

		If (accel <> Null) Then
			output.Push(accel.x + "," + accel.y + "," + accel.z)
		End If

		Return output
	End Method

	Method Load:FrameRecord(data:String)
		Local i:Int
		Local l:Int

		Local tmpArray:String[] = data.Split("k")

		frame = Int(tmpArray[0])

		tmpArray = tmpArray[1].Split("m")

		Local keyData:String = tmpArray[0]

		tmpArray = tmpArray[1].Split("j")

		Local mouseData:String = tmpArray[0]

		tmpArray = tmpArray[1].Split("t")

		Local joystickData:String = tmpArray[0]

		tmpArray = tmpArray[1].Split("a")

		Local touchData:String = tmpArray[0]

		Local accelData:String = tmpArray[1]

		If (keyData.Length() > 0) Then
			tmpArray = keyData.Split(",")

			Local keyPair:String[]
			i = 0
			l = tmpArray.Length()

			While (i < l)
				keyPair = tmpArray[i].Split(":")

				If (keyPair.Length() = 2) Then
					If (keys = Null) keys = New Stack<KeyRecord>()

					keys.Push(New KeyRecord(Int(keyPair[0]), Int(keyPair[1])))
				End If

				i += 1
			Wend
		End If

		If (mouseData.Length() > 0) Then
			tmpArray = mouseData.Split(",")

			If (tmpArray.Length() = 2) Then
				mouse = New XYRecord(Int(tmpArray[0]), Int(tmpArray[1]))
			End If
		End If

		If (joystickData.Length() > 0) Then
			tmpArray = joystickData.Split(",")

			Local joyData:String[]
			i = 0
			l = tmpArray.Length()

			While (i < l)
				joyData = tmpArray[i].Split(":")

				If (joyData.Length() > 3) Then
					If (joystick = Null) joystick = New Stack<XYZRecord[]>()

					Local jl:Int = joyData.Length()
					Local joyXYZRecord:XYZRecord[] = New XYZRecord[(jl - 1) / 3]
					Local index:Int = 0

					For Local ji:Int = 1 Until jl Step 3
						joyXYZRecord[index] = New XYZRecord(Float(joyData[ji]), Float(joyData[ji + 1]), Float(joyData[ji + 2]))
						index += 1
					Next

					joystick.Insert(Int(joyData[0]), joyXYZRecord)
				End If

				i += 1
			Wend

		End If

		If (touchData.Length() > 0) Then
			tmpArray = touchData.Split(",")

			Local touchXY:String[]
			i = 0
			l = tmpArray.Length()

			While (i < l)
				touchXY = tmpArray[i].Split(":")

				If (touchXY.Length() = 2) Then
					If (touch = Null) touch = New Stack<XYRecord>()

					touch.Push(New XYRecord(Int(touchXY[0]), Int(touchXY[1])))
				End If

				i += 1
			Wend
		End If

		If (accelData.Length() > 0) Then
			tmpArray = accelData.Split(",")

			If (tmpArray.Length() = 3) Then
				accel = New XYZRecord(Float(tmpArray[0]), Float(tmpArray[1]), Float(tmpArray[2]))
			End If
		End If

		Return Self
	End Method
End Class

Strict

Import keyrecord
Import xyrecord
Import xyzrecord

Class FrameRecord

	Field frame:Int

	Field keys:Stack<KeyRecord>

	Field mouse:XYRecord

	Field joystick:Stack<XYZRecord[]>

	Field touch:Stack<XYRecord>

	Field accel:XYZRecord

	Method New()
		frame = 0
		keys = Null
		mouse = Null
	End Method

	Method Create:FrameRecord(frame:Int, keys:Stack<KeyRecord> = Null, mouse:XYRecord = Null, joystick:Stack<XYZRecord[]> = Null, touch:Stack<XYRecord> = Null, accel:XYZRecord = Null)
		Self.frame = frame
		Self.keys = keys
		Self.mouse = mouse
		Self.joystick = joystick
		Self.touch = touch
		Self.accel = accel

		Return Self
	End Method

	Method Destroy:Void()
		keys = Null
		mouse = Null
		joystick = Null
		touch = Null
		accel = Null
	End Method

	Method Save:String()
		Return Save(New StringStack()).Join("")
	End Method

	Method Save:StringStack(output:StringStack)
		output.Push(frame + ":" + "k")

		If (keys <> Null) Then
			Local key:KeyRecord
			Local i:Int = 0
			Local l:Int = keys.Length()

			While (i < l)
				If (i > 0) output.Push(",")

				key = keys.Get(i)

				output.Push(key.code + ":" + key.value)

				i += 1
			Wend
		End If

		output.Push("m")

		If (mouse <> Null) Then
			output.Push(mouse.x + "," + mouse.y)
		End If

		output.Push("j")

		If (joystick <> Null) Then
			Local i:Int = 0
			Local l:Int = joystick.Length()
			Local xyzArray:XYZRecord[]

			While (i < l)
				If (i > 0) output.Push(",")
				output.Push(i)

				xyzArray = joystick.Get(i)
				For Local index:Int = 0 Until xyzArray.Length()
					If (xyzArray[index] = Null) xyzArray[index] = New XYZRecord(0, 0, 0)

					output.Push(":" + xyzArray[index].x + ":" + xyzArray[index].y + ":" + xyzArray[index].z)
				Next

				i += 1
			Wend
		End If

		output.Push("t")

		If (touch <> Null) Then
			Local i:Int = 0
			Local l:Int = touch.Length()
			Local xy:XYRecord

			While (i < l)
				xy = touch.Get(i)
				If (xy = Null) Exit

				If (i > 0) output.Push(",")
				output.Push(xy.x + ":" + xy.y)

				i += 1
			Wend
		End If

		output.Push("a")

		If (accel <> Null) Then
			output.Push(accel.x + "," + accel.y + "," + accel.z)
		End If

		Return output
	End Method

	Method Load:FrameRecord(data:String)
		Local i:Int
		Local l:Int

		Local tmpArray:String[] = data.Split("k")

		frame = Int(tmpArray[0])

		tmpArray = tmpArray[1].Split("m")

		Local keyData:String = tmpArray[0]

		tmpArray = tmpArray[1].Split("j")

		Local mouseData:String = tmpArray[0]

		tmpArray = tmpArray[1].Split("t")

		Local joystickData:String = tmpArray[0]

		tmpArray = tmpArray[1].Split("a")

		Local touchData:String = tmpArray[0]

		Local accelData:String = tmpArray[1]

		If (keyData.Length() > 0) Then
			tmpArray = keyData.Split(",")

			Local keyPair:String[]
			i = 0
			l = tmpArray.Length()

			While (i < l)
				keyPair = tmpArray[i].Split(":")

				If (keyPair.Length() = 2) Then
					If (keys = Null) keys = New Stack<KeyRecord>()

					keys.Push(New KeyRecord(Int(keyPair[0]), Int(keyPair[1])))
				End If

				i += 1
			Wend
		End If

		If (mouseData.Length() > 0) Then
			tmpArray = mouseData.Split(",")

			If (tmpArray.Length() = 2) Then
				mouse = New XYRecord(Int(tmpArray[0]), Int(tmpArray[1]))
			End If
		End If

		If (joystickData.Length() > 0) Then
			tmpArray = joystickData.Split(",")

			Local joyData:String[]
			i = 0
			l = tmpArray.Length()

			While (i < l)
				joyData = tmpArray[i].Split(":")

				If (joyData.Length() > 3) Then
					If (joystick = Null) joystick = New Stack<XYZRecord[]>()

					Local jl:Int = joyData.Length()
					Local joyXYZRecord:XYZRecord[] = New XYZRecord[(jl - 1) / 3]
					Local index:Int = 0

					For Local ji:Int = 1 Until jl Step 3
						joyXYZRecord[index] = New XYZRecord(Float(joyData[ji]), Float(joyData[ji + 1]), Float(joyData[ji + 2]))
						index += 1
					Next

					joystick.Insert(Int(joyData[0]), joyXYZRecord)
				End If

				i += 1
			Wend

		End If

		If (touchData.Length() > 0) Then
			tmpArray = touchData.Split(",")

			Local touchXY:String[]
			i = 0
			l = tmpArray.Length()

			While (i < l)
				touchXY = tmpArray[i].Split(":")

				If (touchXY.Length() = 2) Then
					If (touch = Null) touch = New Stack<XYRecord>()

					touch.Push(New XYRecord(Int(touchXY[0]), Int(touchXY[1])))
				End If

				i += 1
			Wend
		End If

		If (accelData.Length() > 0) Then
			tmpArray = accelData.Split(",")

			If (tmpArray.Length() = 3) Then
				accel = New XYZRecord(Float(tmpArray[0]), Float(tmpArray[1]), Float(tmpArray[2]))
			End If
		End If

		Return Self
	End Method
End Class


MonkeyMax - Changed mojo.monkey to allow mojo to try to compile for all targets but STDCPP (saves changing this file in the future)

' Module mojo.mojo
'
' Copyright 2011 Mark Sibly, all rights reserved.
' No warranty implied; use at your own risk.

'#If TARGET<>"html5" And TARGET<>"flash" And TARGET<>"glfw" And TARGET<>"xna" And TARGET<>"ios" And TARGET<>"android" And TARGET<>"pss" And TARGET<>"bmax"
'#Error "Mojo is not currently available for target '${TARGET}'."
'#End

#If TARGET="stdcpp"
#Error "Mojo is not currently available for target '${TARGET}'."
#End

Import app
Import audio
Import graphics
Import input

' Module mojo.mojo
'
' Copyright 2011 Mark Sibly, all rights reserved.
' No warranty implied; use at your own risk.

#If TARGET<>"html5" And TARGET<>"flash" And TARGET<>"glfw" And TARGET<>"xna" And TARGET<>"ios" And TARGET<>"android" And TARGET<>"bmax"
#Error "Mojo is not currently available for target '${TARGET}'."
#End

Import app
Import audio
Import graphics
Import input


remove DeltaTimer spike in the first OnUpdate

Strict

Private

Import bono
Import brl.asyncevent
Import mojo.app
Import mojo.graphics

Public

Class App Extends app.App Abstract
    Private

    Field timer:DeltaTimer
    Field contentScaler:ContentScaler

    Public

    Const DEFAULT_FPS:Int = 60
    Field renderable:Renderable
    Field suspendable:Suspendable
    Field updateable:Updateable

    Method Run:Void() Abstract

    Method TranslateSpace:Vector2D(vec:Vector2D)
        If Not contentScaler Then Return vec.Copy()
        Return contentScaler.TranslateSpace(Self, vec)
    End

    Method GetDirector:Director()
        Return Director.Shared()
    End

    Method SetHandler:Void(obj:Object)
        renderable = Renderable(obj)
        suspendable = Suspendable(obj)
        updateable = Updateable(obj)
    End

    ' --- CONFIG

    Method GetTargetFps:Int()
        Return DEFAULT_FPS
    End

    Method GetContentScaler:ContentScaler()
        Return Null
    End

    Method GetVirtualSize:Vector2D()
        Return Device.GetSize()
    End

    ' --- MONKEY APP

    Method OnCreate:Int()
        Try
            SetUpdateRate(GetTargetFps())
            contentScaler = GetContentScaler()

            Director.Shared().SetApp(Self)
            Run()
        Catch ex:Exception
            Error ex
        End
        Return 0
    End

    Method OnRender:Int()
        Try
            Cls(0, 0, 0)
            UpdateAsyncEvents()
            If contentScaler Then contentScaler.OnRenderPre(Self)
            If renderable Then renderable.OnRender()
            If contentScaler Then contentScaler.OnRenderPost(Self)
        Catch ex:Exception
            Error ex
        End
        Return 0
    End

    Method OnUpdate:Int()
        If Not timer Then timer = New DeltaTimer(GetTargetFps())

        Try
            timer.OnUpdate()
            If updateable Then updateable.OnUpdate(timer)
        Catch ex:Exception
            Error ex
        End
        Return 0
    End

    Method OnResume:Int()
        Try
            timer.Play()
            If suspendable Then suspendable.OnResume()
        Catch ex:Exception
            Error ex
        End
        Return 0
    End

    Method OnSuspend:Int()
        Try
            timer.Pause()
            If suspendable Then suspendable.OnSuspend()
        Catch ex:Exception
            Error ex
        End
        Return 0
    End
End

Strict

Private

Import bono
Import brl.asyncevent
Import mojo.app
Import mojo.graphics

Public

Class App Extends app.App Abstract
    Private

    Field timer:DeltaTimer
    Field contentScaler:ContentScaler

    Public

    Const DEFAULT_FPS:Int = 60
    Field renderable:Renderable
    Field suspendable:Suspendable
    Field updateable:Updateable

    Method Run:Void() Abstract

    Method TranslateSpace:Vector2D(vec:Vector2D)
        If Not contentScaler Then Return vec.Copy()
        Return contentScaler.TranslateSpace(Self, vec)
    End

    Method GetDirector:Director()
        Return Director.Shared()
    End

    Method SetHandler:Void(obj:Object)
        renderable = Renderable(obj)
        suspendable = Suspendable(obj)
        updateable = Updateable(obj)
    End

    ' --- CONFIG

    Method GetTargetFps:Int()
        Return DEFAULT_FPS
    End

    Method GetContentScaler:ContentScaler()
        Return Null
    End

    Method GetVirtualSize:Vector2D()
        Return Device.GetSize()
    End

    ' --- MONKEY APP

    Method OnCreate:Int()
        Try
            SetUpdateRate(GetTargetFps())
            timer = New DeltaTimer(GetTargetFps())
            contentScaler = GetContentScaler()

            Director.Shared().SetApp(Self)
            Run()
        Catch ex:Exception
            Error ex
        End
        Return 0
    End

    Method OnRender:Int()
        Try
            Cls(0, 0, 0)
            UpdateAsyncEvents()
            If contentScaler Then contentScaler.OnRenderPre(Self)
            If renderable Then renderable.OnRender()
            If contentScaler Then contentScaler.OnRenderPost(Self)
        Catch ex:Exception
            Error ex
        End
        Return 0
    End

    Method OnUpdate:Int()
        Try
            timer.OnUpdate()
            If updateable Then updateable.OnUpdate(timer)
        Catch ex:Exception
            Error ex
        End
        Return 0
    End

    Method OnResume:Int()
        Try
            timer.Play()
            If suspendable Then suspendable.OnResume()
        Catch ex:Exception
            Error ex
        End
        Return 0
    End

    Method OnSuspend:Int()
        Try
            timer.Pause()
            If suspendable Then suspendable.OnSuspend()
        Catch ex:Exception
            Error ex
        End
        Return 0
    End
End


Fixed camerafx test

Fixed camerafx test

Strict

Import flixel
Import flixel.flxtext.driver.angelfont

Function Main:Int()
	New CameraFX()
	Return 0
End Function

Class CameraFX Extends FlxGame

	Method New()
		Super.New(640, 480, CameraFXState.ClassObject)
	End Method

	Method OnContentInit:Void()
		Local minSize:Int = FlxAssetsManager.GetFont(FlxText.SYSTEM_FONT).MinSize
		Local maxSize:Int = FlxAssetsManager.GetFont(FlxText.SYSTEM_FONT).MaxSize

		FlxTextAngelFontDriver.Init()
		FlxText.SetDefaultDriver(AngelfontTextDriver)
	End Method

End Class

Class CameraFXStateClass Implements FlxClass

	Method CreateInstance:Object()
		Return New CameraFXState()
	End Method

	Method InstanceOf:Bool(object:Object)
		Return (CameraFXState(object) <> Null)
	End Method

End Class

Class CameraFXState Extends FlxState

	Global ClassObject:FlxClass = new CameraFXStateClass()

	Method Create:Void()
		Local manual:FlxText = New FlxText(10, 10, 620, "- Press S to shake")
		manual.SetFormat(FlxText.SYSTEM_FONT, 16, FlxG.WHITE, FlxText.ALIGN_LEFT)
		Add(manual)

		manual = New FlxText(10, 40, 620, "- Press L to flash")
		manual.SetFormat(FlxText.SYSTEM_FONT, 16, FlxG.WHITE, FlxText.ALIGN_LEFT)
		Add(manual)

		manual = New FlxText(10, 70, 620, "- Press F to fade")
		manual.SetFormat(FlxText.SYSTEM_FONT, 16, FlxG.WHITE, FlxText.ALIGN_LEFT)
		Add(manual)

		manual = New FlxText(10, 100, 620, "- Press SPACE to stopFX")
		manual.SetFormat(FlxText.SYSTEM_FONT, 16, FlxG.WHITE, FlxText.ALIGN_LEFT)
		Add(manual)
	End Method

	Method Update:Void()
		If (FlxG.Keys.JustPressed(KEY_S)) Then
			FlxG.Shake()
		End If

		If (FlxG.Keys.JustPressed(KEY_L)) Then
			FlxG.Flash()
		End If

		If (FlxG.Keys.JustPressed(KEY_F)) Then
			FlxG.Fade()
		End If

		If (FlxG.Keys.JustPressed(KEY_SPACE)) Then
			FlxG.Camera.StopFX()
		End If

		Super.Update()
	End Method

End Class

Strict

Import flixel
Import flixel.flxtext.driver.angelfont

Function Main:Int()
	New CameraFX()
	Return 0
End Function

Class CameraFX Extends FlxGame

	Method New()
		Super.New(640, 480, CameraFXState.ClassObject)
	End Method

	Method OnContentInit:Void()
		Local minSize:Int = FlxAssetsManager.GetFont(FlxText.SYSTEM_FONT).MinSize
		Local maxSize:Int = FlxAssetsManager.GetFont(FlxText.SYSTEM_FONT).MaxSize

		Local angelSystemFont:FlxFont = FlxAssetsManager.AddFont("system", FlxText.DRIVER_ANGELFONT)

		For Local i:Int = minSize To maxSize
			angelSystemFont.SetPath(i, "fonts/"+FlxText.SYSTEM_FONT+"/angelfont/"+i+".txt")
		Next
	End Method

End Class

Class CameraFXStateClass Implements FlxClass

	Method CreateInstance:FlxBasic()
		Return New CameraFXState()
	End Method

	Method InstanceOf:Bool(object:FlxBasic)
		Return (CameraFXState(object) <> Null)
	End Method

End Class

Class CameraFXState Extends FlxState

	Global ClassObject:FlxClass = new CameraFXStateClass()

	Method Create:Void()
		Local manual:FlxText = New FlxText(10, 10, 620, "- Press S to shake", New FlxTextAngelFontDriver())
		manual.SetFormat(FlxText.SYSTEM_FONT, 16, FlxG.WHITE, FlxText.ALIGN_LEFT)
		Add(manual)

		manual = New FlxText(10, 40, 620, "- Press L to flash", New FlxTextAngelFontDriver())
		manual.SetFormat(FlxText.SYSTEM_FONT, 16, FlxG.WHITE, FlxText.ALIGN_LEFT)
		Add(manual)

		manual = New FlxText(10, 70, 620, "- Press F to fade", New FlxTextAngelFontDriver())
		manual.SetFormat(FlxText.SYSTEM_FONT, 16, FlxG.WHITE, FlxText.ALIGN_LEFT)
		Add(manual)

		manual = New FlxText(10, 100, 620, "- Press SPACE to stopFX", New FlxTextAngelFontDriver())
		manual.SetFormat(FlxText.SYSTEM_FONT, 16, FlxG.WHITE, FlxText.ALIGN_LEFT)
		Add(manual)
	End Method

	Method Update:Void()
		If (KeyHit(KEY_S)) Then
			FlxG.Shake()
		End If

		If (KeyHit(KEY_L)) Then
			FlxG.Flash()
		End If

		If (KeyHit(KEY_F)) Then
			FlxG.Fade()
		End If

		If (KeyHit(KEY_SPACE)) Then
			FlxG.Camera.StopFX()
		End If

		Super.Update()
	End Method

End Class