Fixed issues with the standard object-containers for the 'primitive' types. Issues are still present, but they're only an issue with types which implement 'ToInsertTypeHere'. But, that's only if 'IsObject' is used within 'GenericUtilities', so it's not a big deal.

Strict

Public

' Preprocessor related:
#Rem
#If TARGET = "glfw" Or TARGET = "sexy"
	#GLFW_TARGET = True
#End
#End

#UTIL_IMPLEMENTED = True

#If IOELEMENT_IMPLEMENTED
	#UTIL_SUPPORT_IOELEMENTS = True
#Else
	#UTIL_SUPPORT_IOELEMENTS = False
#End

#If CONFIG = "debug"
	#DEBUG_PRINT = True
#Else
	#DEBUG_PRINT = False
#End

#If CONFIG = "release"
	#DEBUG_PRINT_ON_ERROR = True
#Else
	#DEBUG_PRINT_ON_ERROR = False
#End

#DEBUG_PRINT_QUOTES = False

#READ_LINE_QUICKLY = True

#If HOST = "winnt"
	#WRITE_LINE_ENDTYPE = "CRLF"
#Else
	#WRITE_LINE_ENDTYPE = "LF"
#End

' Imports (Public):
Import autostream

Import byteorder
Import imagedimensions
Import retrostrings
Import stringutil
Import vector

#If CONSOLE_IMPLEMENTED
	Import console
#End

Import sizeof
Import time

#If Not BRL_GAMETARGET_IMPLEMENTED
	Import mojoemulator
#End

' Imports (Private):
Private

' Unofficial:
#If UTIL_SUPPORT_IOELEMENTS
	Import ioelement
#End

' Official:

' BRL:
Import brl.databuffer
Import brl.stream
Import brl.filepath

Public

' Constant variable(s):

' Type codes (Mainly used for generic classes):
Const TYPE_OBJECT:Int			= 0
Const TYPE_INT:Int				= 1
Const TYPE_BOOL:Int				= 2
Const TYPE_FLOAT:Int			= 3
Const TYPE_STRING:Int			= 4

' Ascii codes:
Const ASCII_CARRIAGE_RETURN:Int = 13
Const ASCII_LINE_FEED:Int = 10

' Used mainly for external code where '-9999...' isn't ever going to be valid.
' You should stick to 'Null' in most cases; try not to use this.
Const NOVAR:Int = -999999

' This acts as a general "automatic-value".
' Basically, you can check against this for things like manually defined array-lengths.
Const UTIL_AUTO:Int = -1

' This is for situations where the length of something can be optional.
Const AUTOMATIC_LENGTH:Int = -1

Const ErrorTemplate:String = "[ERROR] {Debug}: " ' + Space
Const LogTemplate:String = "[Info] {Debug}: " ' + Space

' Global variable(s) (Public):
#If CONSOLE_IMPLEMENTED
	Global DebugConsole:Console = Null
#End

' A global stack logging randomization seeds.
' This is commonly accessed by the 'PushSeed' and 'PopSeed' functions.
Global SeedStack:Stack<Int> = Null

' Global variable(s) (Private):
Private

' Nothing so far.

Public

' Functions:
Function FLAG:Int(ID:Int)
	Return Pow(2, ID)
End

' This command is little-endian only:
Function AsByte:Int(I:Int)
	Return ((I Shl 24) Shr 24)
End

' This command treats data as 8-bit (Turns something like $F7, into $FFFFFFF7)
' This is only applied on little-endian systems,
' please use this command for hex values (Monkey converts hex on compile-time).
Function PaddedHex:Int(I:Int)
	If (Not BigEndian()) Then
		Return AsByte(I)
	Endif

	Return I
End

Function Transfer:Bool(InputStream:Stream, OutputStream:Stream, DataSize:Int)
	' Check for errors:
	If (DataSize = 0) Then Return False
	If (InputStream = Null Or InputStream.Eof()) Then Return False
	If (OutputStream = Null) Then Return False

	' Local variable(s):
	#If FLAG_TEMP_BUFFERS
		Local Data:DataBuffer = New DataBuffer(DataSize)
		Local DataLength:= DataSize ' Data.Length()

		' Read from the input-stream, then write to the output-stream:
		InputStream.Read(Data, 0, DataLength)
		OutputStream.Write(Data, 0, DataLength)

		Data.Discard()
	#Else
		'Local Data:Int[DataSize]

		For Local I:Int = 1 To DataSize ' Data.Length()
			OutputStream.WriteByte(InputStream.ReadByte())
		Next
	#End

	' Return the default response.
	Return True
End

Function Sq:Float(Input:Float)
	Return Pow(Input, 2.0) ' Input * Input
End

Function Sq:Int(Input:Int)
	Return Pow(Input, 2)
End

Function WrapAngle:Float(A:Float)
	While (A < 0.0)
		A += 360.0
	Wend

	While (A > 360.0)
		A -= 360.0
	Wend

	Return A
End

Function WrapColor:Float(C:Float)
	#Rem
	While (C < 0.0)
		C += 255.0
	Wend

	While (C > 255.0)
		C -= 255.0
	Wend
	#End

	Return C Mod 256.0
End

' This command is a helper function for
Function ProcessColorLocation:Int(Point:Int)
	' Check for errors:
	If (Point < 0) Then
		Return 0
	Endif

	Return (SizeOf_Integer_InBits-(SizeOf_Octet_InBits*(Point+1))) ' ((SizeOf_Integer_InBits-SizeOf_Octet_InBits)-(SizeOf_Octet_InBits*Point))
End

' NOTE: This command will produce incorrect color values without all characters present in the encode-string.
Function ColorToString:String(Pixel:Int, Encoding:String="ARGB")
	' Ensure the encoding is always described as uppercase.
	Encoding = Encoding.ToUpper()

	' Return the encoded color-string.
	Return ("R: " + ((Pixel Shr ProcessColorLocation(Encoding.Find("R"))) & $000000FF) +
			", G: " + ((Pixel Shr ProcessColorLocation(Encoding.Find("G"))) & $000000FF) +
			", B: " + ((Pixel Shr ProcessColorLocation(Encoding.Find("B"))) & $000000FF) +
			", A: " + ((Pixel Shr ProcessColorLocation(Encoding.Find("A"))) & $000000FF))
End

Function PrintColor:Void(Pixel:Int, Encoding:String="ARGB")
	Print(ColorToString(Pixel, Encoding))

	Return
End

' This is just a wrapper for the main implementation:
Function PushSeed:Bool()
	Return PushSeed(Seed)
End

' The return value of this function specifies if the seed-stack already existed.
Function PushSeed:Bool(Seed:Int)
	' Local variable(s):
	Local Response:Bool = (SeedStack <> Null)

	If (Not Response) Then
		SeedStack = New IntStack()
	Endif

	SeedStack.Push(Seed)

	' Return the calculated response.
	Return Response
End

' This command retrieves a seed from the seed-stack,
' if no seed exists, the current randomization seed is returned.
Function PopSeed:Int()
	If (SeedStack <> Null) Then
		If (Not SeedStack.IsEmpty()) Then
			Return SeedStack.Pop()
		Endif
	Endif

	' Return the default response.
	Return Seed
End

' This command writes a standard line to a 'Stream'.
' This supports both 'LF', and 'CRLF' line endings currently, and this can be configured with 'WRITE_LINE_ENDTYPE'.
' Though character encoding is supported with this, only ASCII is supported by 'ReadLine'.
Function WriteLine:Bool(S:Stream, Line:String, CharacterEncoding:String="ascii")
	' Check for errors:
	If (S = Null) Then
		Return False
	Endif

	S.WriteString(Line, CharacterEncoding)

	#If WRITE_LINE_ENDTYPE = "CRLF"
		S.WriteByte(ASCII_CARRIAGE_RETURN)
	#End

	S.WriteByte(ASCII_LINE_FEED)

	' Return the default response.
	Return True
End

' This command reads a standard line from a 'Stream'. (This supports both 'LF', and 'CRLF' line endings currently)
' In addition, only 'ASCII' is currently supported.
Function ReadLine:String(S:Stream)
	' Local variable(s):
	Local Position:= S.Position()
	Local Padding:Int = 0 ' * SizeOf_Char
	Local Str:String

	#If Not READ_LINE_QUICKLY
		Local Size:Int = 0
	#End

	While (Not S.Eof())
		Local Char:= S.ReadByte()

		If (Char <> ASCII_LINE_FEED) Then
			If (Char <> ASCII_CARRIAGE_RETURN) Then
				#If READ_LINE_QUICKLY
					Str += String.FromChar(Char)
				#Else
					Size += 1
				#End
			Else
				Padding = 2*SizeOf_Char
			Endif
		Else
			#Rem
				If (Padding = 0) Then
					Padding = 1
				Endif
			#End

			Padding = Max(Padding, 1*SizeOf_Char)

			Exit
		Endif
	Wend

	#If Not READ_LINE_QUICKLY
		S.Seek(Position)

		Str = S.ReadString(Size, "ascii")

		S.Seek(S.Position()+Padding)
	#End

	' Return the string we read from the stream.
	Return Str
End

Function ResizeBuffer:DataBuffer(Buffer:DataBuffer, Size:Int=AUTOMATIC_LENGTH, CopyData:Bool=True, DiscardOldBuffer:Bool=False, OnlyWhenDifferentSizes:Bool=False)
	Local BufferAvailable:Bool = (Buffer <> Null)

	If (BufferAvailable And OnlyWhenDifferentSizes) Then
		If (Size <> AUTOMATIC_LENGTH And Buffer.Length() = Size) Then
			Return Buffer
		Endif
	Endif

	If (Size = AUTOMATIC_LENGTH) Then
		Size = Buffer.Length()
	Endif

	' Allocate a new data-buffer.
	Local B:= New DataBuffer(Size)

	' Copy the buffer's bytes over to 'B'.
	If (BufferAvailable) Then
		If (CopyData) Then
			' Copy the contents of 'Buffer' to the newly generated buffer-object.
			Buffer.CopyBytes(0, B, 0, Buffer.Length())
		Endif

		If (DiscardOldBuffer) Then
			' Discard the old buffer.
			Buffer.Discard()
		Endif
	Endif

	' Return the newly generated buffer.
	Return B
End

#If CONSOLE_IMPLEMENTED
	Function DebugBind:Bool(C:Console)
		If (C = Null) Then Return False

		DebugConsole = C

		' Return the default response.
		Return True
	End
#End

Function DebugError:Void(E:Throwable, StopExecution:Bool=True)
	#If CONFIG = "debug"
		DebugStop()
	#Else
		DebugPrint("Unknown exception has been thrown; continuing anyway.")
	#End

	Return
End

Function DebugError:Void(Msg:String, StopExecution:Bool=True)
	#If DEBUG_PRINT
		' Local variable(s):
		Local TempMsg:String

		If (StopExecution) Then
			TempMsg = ErrorTemplate
		Else
			TempMsg = LogTemplate
		Endif

		#If DEBUG_PRINT_QUOTES
			Msg = Tempmsg + Quote + Msg + Quote
		#Else
			Msg = TempMsg + Msg
		#End

		#If CONSOLE_IMPLEMENTED
			If (DebugConsole <> Null) Then
				DebugConsole.WriteLine(Msg, True)
			Else
		#End

		Print(Msg)

		#If CONSOLE_IMPLEMENTED
			Endif
		#End
	#Else
		' This may change later:
		If (StopExecution) Then
			Msg = ErrorTemplate + Msg
		Endif
	#End

	If (StopExecution) Then
		#If CONFIG = "debug"
			#If DEBUG_PRINT_ON_ERROR
				DebugStop()
			#Else
				Error(Msg)
			#End
		#Else
			#If DEBUG_PRINT
				Local FinalStr:String = (ErrorTemplate + Quote + "Attempt to stop execution failed. (Reason: Release-mode)" + Quote)

				#If CONSOLE_IMPLEMENTED
					If (DebugConsole <> Null) Then
						DebugConsole.WriteLine(FinalStr, True)
					Else
				#End

				Print(FinalStr)

				#If CONSOLE_IMPLEMENTED
					Endif
				#End
			#Else
				Error(Msg)
			#End
		#End
	Endif

	#If CONFIG = "debug"
		' Nothing so far.
	#Else
		' Nothing so far.
	#End

	Return
End

Function DebugPrint:Void(Str:String, StopExecution:Bool=False)
	DebugError(Str, StopExecution)

	Return
End

' The following functions are designed to be used with generic classes:
Function TypeIsObject:Bool(O:Object)
	Return True
End

Function TypeIsObject:Bool(IO:IntObject)
	Return False
End

Function TypeIsObject:Bool(BO:BoolObject)
	Return False
End

Function TypeIsObject:Bool(FO:FloatObject)
	Return False
End

Function TypeIsObject:Bool(SO:StringObject)
	Return False
End

Function TypeIsObject:Bool(I:Int)
	Return False
End

Function TypeIsObject:Bool(B:Bool)
	Return False
End

Function TypeIsObject:Bool(F:Float)
	Return False
End

Function TypeIsObject:Bool(S:String)
	Return False
End

Function TypeOf:Int(O:Object)
	Return TYPE_OBJECT
End

Function TypeOf:Int(I:Int)
	Return TYPE_INT
End

Function TypeOf:Int(B:Bool)
	Return TYPE_BOOL
End

Function TypeOf:Int(F:Float)
	Return TYPE_FLOAT
End

Function TypeOf:Int(S:String)
	Return TYPE_STRING
End

' Classes:
Class GenericUtilities<T>
	' Constant variable(s):

	' Comparison response codes (Positive numbers are for error-reporting):
	Const COMPARE_RESPONSE_IDENTICAL:Int			= -1
	Const COMPARE_RESPONSE_WRONG_LENGTH:Int			= -2

	' Other:
	Const AUTO:= UTIL_AUTO

	' Global variable(s):

	' For internal and extern use. That being said, please do not modify this value.
	Global NIL:T

	' Functions:

	' This command gives the user the type-code of 'T'.
	Function Type:Int()
		' Return the type code of 'NIL'.
		Return TypeOf(NIL)
	End

	' This command specifies if 'T' is an object.
	Function IsObject:Bool()
		Return TypeIsObject(NIL)
	End

	' This command wraps the standard 'BoolToString' conversion command.
	Function AsString:String(Input:Bool)
		Return BoolToString(Input)
	End

	' This command reads a string from a standard 'Stream' object.
	Function AsString:String(S:Stream, Length:Int=AUTO, Encoding:String="utf8")
		If (Length = AUTO) Then
			Length = S.Length()
		Endif

		Return S.ReadString(Length, Encoding)
	End

	Function AsString:String(Input:T[], Offset:Int=0, Length:Int=AUTO, AddSpaces:Bool=True)
		' Local variable(s):
		Local Output:String = LeftBracket

		' If no length was specified, use the array's length.
		If (Length = AUTO) Then
			Length = Input.Length()
		Endif

		Local VirtualLength:= Length+Offset

		For Local Index:Int = Offset Until VirtualLength
			Output += Input[Index]

			If (Index+1 < VirtualLength) Then
				Output += Comma

				If (AddSpaces) Then
					Output += Space
				Endif
			Endif
		Next

		Return Output + RightBracket
	End

	Function CopyStringToArray:T[](S:String, Input:T[], Offset:Int=0, Length:Int=AUTO)
		If (Length = AUTO) Then
			Length = Min(S.Length(), Input.Length())
		Endif

		For Local I:Int = Offset Until Length
			Input[I] = S[I]
		Next

		' Just for the sake of convenience, return the 'Input' array.
		Return Input
	End

	Function IndexOfList:T(L:List<T>, Index:Int=0)
		' Local variable(s):
		Local Data:list.Node<T> = L.FirstNode()

		For Local I:= 0 Until Index
			Data = Data.NextNode()

			' Not my favorite method, but it works:
			If (Data = Null) Then
				Return NIL
			Endif
		Next

		' Return the value of the assessed node.
		Return Data.Value()
	End

	Function Zero:T[](Input:T[])
		Return Nil(Input)
	End

	Function Nil:T[](Input:T[])
		For Local Index:= 0 Until Input.Length()
			Input[Index] = NIL
		Next

		Return Input
	End

	Function PrintArray:Void(Input:T[])
		Print(AsString(Input))

		Return
	End

	#Rem
		NOTES:
			* In the event of an error, an empty array will be produced.

			* The 'CopyArray' command's 'FitSource' argument should only be enabled with the
			knowledge that the original destination may have been discarded.

			Your code must reflect this by disregarding the original array,
			and simply assigning the old array to the retrun value.

			EXAMPLE:
				' Local variable(s):
				Local A:T[10], A2:T[3]

				' This will likely produce a new 'T' array, based on the area-delta.
				A2 = CopyArray(A, A2, True)
	#End

	Function CopyArray:T[](Source:T[], Destination:T[], FitSource:Bool)
		Return CopyArray(Source, Destination, 0, 0, AUTO, AUTO, FitSource)
	End

	Function CopyArray:T[](Source:T[], Destination:T[], Source_Offset:Int=0, Destination_Offset:Int=0, Source_Length:Int=AUTO, Destination_Length:Int=AUTO, FitSource:Bool=False)
		If (Source_Length = AUTO) Then
			Source_Length = Source.Length()
		Endif

		If (Destination_Length = AUTO) Then
			Destination_Length = Destination.Length()
		Endif

		' Local variable(s):

		' These two are used as caches for the real lengths of the arrays:
		Local Destination_RealLength:= Destination.Length()
		Local Source_RealLength:= Source.Length()

		' Calculate the source and destination areas:
		Local Source_Area:Int = (Source_Length-Source_Offset)

		' Make sure we have a source to work with:
		If (Source_Area <= 0) Then
			' The source-area is too small for use, return an empty array.
			Return []
		Endif

		Local Destination_Area:Int = (Destination_Length-Destination_Offset)

		' For the sake of safety, we'll also check the destination area:
		If (Destination_Area <= 0) Then
			' The destination-area is too small for use, return an empty array.
			Return []
		Endif

		Local Operation_Area:Int

		If (FitSource And Destination_Area < Source_Area) Then
			Local AreaDelta:Int = (Source_Area-Destination_Area)
			Local NewArea:Int = (Destination_RealLength+AreaDelta)

			If (NewArea > Destination_RealLength) Then
				Destination = Destination.Resize(NewArea)
			Else
				Destination = Destination.Resize(Destination_Length+AreaDelta)
			Endif

			Destination_Area = Source_Area
			Operation_Area = Destination_Area
		Else
			Operation_Area = Min(Source_Area, Destination_Area)
		Endif

		' Copy the contents of the source-array into the destination-array:
		For Local Index:= 0 Until Operation_Area
			Destination[Index+Destination_Offset] = Source[Index+Source_Offset]
		Next

		' Return the destination-array.
		Return Destination
	End

	Function CopyArray:T[](Source:T[])
		Return CloneArray(Source)
	End

	Function CloneArray:T[](Source:T[])
		Return CopyArray(Source, New T[Source.Length()])
	End

	' This command returns a positive number upon an error,
	' otherwise a 'response code' will be given (See the "Contant variable(s)" section for details).
	Function Compare:Int(A1:T[], A2:T[], CheckLength:Bool=True)
		' Local variable(s):
		Local A1_Length:= A1.Length
		Local A2_Length:= A2.Length

		' Check for errors:
		If (CheckLength) Then
			' Make sure they're both the same length.
			If (A1_Length <> A2_Length) Then
				Return COMPARE_RESPONSE_WRONG_LENGTH
			Endif
		Endif

		For Local I:= 0 Until Min(A1_Length, A2_Length)
			If (A1[I] <> A2[I]) Then
				' Not the best of escape methods, but it works.
				Return I
			Endif
		Next

		' Return the default response.
		Return COMPARE_RESPONSE_IDENTICAL
	End

	' This function returns positive if both arrays are identical.
	Function SimpleCompare:Bool(A1:T[], A2:T[], CheckLength:Bool=True)
		Return (Compare(A1, A2, CheckLength) = COMPARE_RESPONSE_IDENTICAL)
	End

	Function Read:T(S:Stream)
		Return Read(S, NIL)
	End

	Function Read:T[](S:Stream, DataArray:T[], Size:Int=AUTO)
		If (Size = AUTO) Then Size = S.ReadInt()

		If (Size > 0) Then
			If (DataArray.Length() = 0) Then
				DataArray = New T[Size]
			Endif
		Endif

		' Local variable(s):
		Local DLength:Int = Min(DataArray.Length, Size)

		For Local Index:= 0 Until DLength
			DataArray[Index] = Read(S, NIL)
		Next

		Return DataArray
	End

	Function Write:Void(S:Stream, DataArray:T[], WriteLength:Bool=True)
		' Local variable(s):
		Local DLength:= DataArray.Length()

		If (WriteLength) Then S.WriteInt(DLength)

		For Local Index:= 0 Until DLength
			Write(S, DataArray[Index])
		Next

		Return
	End

	Function Read:Int(S:Stream, Indentifier:Int, Size:Int=4)
		' Local variable(s):
		Local Data:Int = 0

		If (Size > 1) Then
			If (Size < 4) Then
				Data = S.ReadShort()
			Else
				If (Size > 4) Then
					S.ReadInt()
				Endif

				Data = S.ReadInt()
			Endif
		Else
			Data = S.ReadByte()
		Endif

		Return Data
	End

	Function Write:Void(S:Stream, Data:Int, Size:Int=4)
		Size = IntSize(Size)

		If (Size > 1) Then
			If (Size < 4) Then
				S.WriteShort(Data)
			Else
				If (Size > 4) Then
					S.WriteInt(0)
				Endif

				S.WriteInt(Data)
			Endif
		Else
			S.WriteByte(Data)
		Endif

		Return
	End

	#Rem
	Function Read:Bool(S:Stream, Identifier:Bool)
		Return Read(S, Int(Identifier), 1)
	End

	Function Write:Void(S:Stream, B:Bool)
		Write(S, Int(B), 1)

		Return
	End
	#End

	Function Read:Float(S:Stream, Identifier:Float)
		Return S.ReadFloat()
	End

	Function Write:Void(S:Stream, Data:Float)
		S.WriteFloat(Data)

		Return
	End

	Function Read:String(S:Stream, Data:String, Encoding:String="utf8", Size:Int=AUTO)
		If (Size = AUTO) Then
			Size = S.ReadInt()
		Endif

		Data = S.ReadString(Size, Encoding)

		' Return the newly read string.
		Return Data
	End

	Function Write:Void(S:Stream, Data:String, Encoding:String="utf8", WriteSize:Bool=True)
		If (WriteSize) Then
			S.WriteInt(Data.Length())
		Endif

		S.WriteString(Data, Encoding)

		Return
	End

	#If UTIL_SUPPORT_IOELEMENTS
		Function Read:Void(S:Stream, Data:InputChildElement)
			If (Data = Null) Then
				Return
			Endif

			Data.Load(S)

			Return
		End

		Function Write:Void(S:Stream, Data:OutputChildElement)
			If (Data = Null) Then
				Return
			Endif

			Data.Save(S)
		End
	#End

	' Constructor(s):

	' DO NOT CREATE NEW INSTANCES OF THIS CLASS.
	Method New()
		DebugError("This class should not be used in this was.")
	End
End

Strict

Public

' Preprocessor related:
#Rem
#If TARGET = "glfw" Or TARGET = "sexy"
	#GLFW_TARGET = True
#End
#End

#UTIL_IMPLEMENTED = True

#If IOELEMENT_IMPLEMENTED
	#UTIL_SUPPORT_IOELEMENTS = True
#Else
	#UTIL_SUPPORT_IOELEMENTS = False
#End

#If CONFIG = "debug"
	#DEBUG_PRINT = True
#Else
	#DEBUG_PRINT = False
#End

#If CONFIG = "release"
	#DEBUG_PRINT_ON_ERROR = True
#Else
	#DEBUG_PRINT_ON_ERROR = False
#End

#DEBUG_PRINT_QUOTES = False

#READ_LINE_QUICKLY = True

#If HOST = "winnt"
	#WRITE_LINE_ENDTYPE = "CRLF"
#Else
	#WRITE_LINE_ENDTYPE = "LF"
#End

' Imports (Public):
Import autostream

Import byteorder
Import imagedimensions
Import retrostrings
Import stringutil
Import vector

#If CONSOLE_IMPLEMENTED
	Import console
#End

Import sizeof
Import time

#If Not BRL_GAMETARGET_IMPLEMENTED
	Import mojoemulator
#End

' Imports (Private):
Private

' Unofficial:
#If UTIL_SUPPORT_IOELEMENTS
	Import ioelement
#End

' Official:

' BRL:
Import brl.databuffer
Import brl.stream
Import brl.filepath

Public

' Constant variable(s):

' Type codes (Mainly used for generic classes):
Const TYPE_OBJECT:Int			= 0
Const TYPE_INT:Int				= 1
Const TYPE_BOOL:Int				= 2
Const TYPE_FLOAT:Int			= 3
Const TYPE_STRING:Int			= 4

' Ascii codes:
Const ASCII_CARRIAGE_RETURN:Int = 13
Const ASCII_LINE_FEED:Int = 10

' Used mainly for external code where '-9999...' isn't ever going to be valid.
' You should stick to 'Null' in most cases; try not to use this.
Const NOVAR:Int = -999999

' This acts as a general "automatic-value".
' Basically, you can check against this for things like manually defined array-lengths.
Const UTIL_AUTO:Int = -1

' This is for situations where the length of something can be optional.
Const AUTOMATIC_LENGTH:Int = -1

Const ErrorTemplate:String = "[ERROR] {Debug}: " ' + Space
Const LogTemplate:String = "[Info] {Debug}: " ' + Space

' Global variable(s) (Public):
#If CONSOLE_IMPLEMENTED
	Global DebugConsole:Console = Null
#End

' A global stack logging randomization seeds.
' This is commonly accessed by the 'PushSeed' and 'PopSeed' functions.
Global SeedStack:Stack<Int> = Null

' Global variable(s) (Private):
Private

' Nothing so far.

Public

' Functions:
Function FLAG:Int(ID:Int)
	Return Pow(2, ID)
End

' This command is little-endian only:
Function AsByte:Int(I:Int)
	Return ((I Shl 24) Shr 24)
End

' This command treats data as 8-bit (Turns something like $F7, into $FFFFFFF7)
' This is only applied on little-endian systems,
' please use this command for hex values (Monkey converts hex on compile-time).
Function PaddedHex:Int(I:Int)
	If (Not BigEndian()) Then
		Return AsByte(I)
	Endif

	Return I
End

Function Transfer:Bool(InputStream:Stream, OutputStream:Stream, DataSize:Int)
	' Check for errors:
	If (DataSize = 0) Then Return False
	If (InputStream = Null Or InputStream.Eof()) Then Return False
	If (OutputStream = Null) Then Return False

	' Local variable(s):
	#If FLAG_TEMP_BUFFERS
		Local Data:DataBuffer = New DataBuffer(DataSize)
		Local DataLength:= DataSize ' Data.Length()

		' Read from the input-stream, then write to the output-stream:
		InputStream.Read(Data, 0, DataLength)
		OutputStream.Write(Data, 0, DataLength)

		Data.Discard()
	#Else
		'Local Data:Int[DataSize]

		For Local I:Int = 1 To DataSize ' Data.Length()
			OutputStream.WriteByte(InputStream.ReadByte())
		Next
	#End

	' Return the default response.
	Return True
End

Function Sq:Float(Input:Float)
	Return Pow(Input, 2.0) ' Input * Input
End

Function Sq:Int(Input:Int)
	Return Pow(Input, 2)
End

Function WrapAngle:Float(A:Float)
	While (A < 0.0)
		A += 360.0
	Wend

	While (A > 360.0)
		A -= 360.0
	Wend

	Return A
End

Function WrapColor:Float(C:Float)
	#Rem
	While (C < 0.0)
		C += 255.0
	Wend

	While (C > 255.0)
		C -= 255.0
	Wend
	#End

	Return C Mod 256.0
End

' This command is a helper function for
Function ProcessColorLocation:Int(Point:Int)
	' Check for errors:
	If (Point < 0) Then
		Return 0
	Endif

	Return (SizeOf_Integer_InBits-(SizeOf_Octet_InBits*(Point+1))) ' ((SizeOf_Integer_InBits-SizeOf_Octet_InBits)-(SizeOf_Octet_InBits*Point))
End

' NOTE: This command will produce incorrect color values without all characters present in the encode-string.
Function ColorToString:String(Pixel:Int, Encoding:String="ARGB")
	' Ensure the encoding is always described as uppercase.
	Encoding = Encoding.ToUpper()

	' Return the encoded color-string.
	Return ("R: " + ((Pixel Shr ProcessColorLocation(Encoding.Find("R"))) & $000000FF) +
			", G: " + ((Pixel Shr ProcessColorLocation(Encoding.Find("G"))) & $000000FF) +
			", B: " + ((Pixel Shr ProcessColorLocation(Encoding.Find("B"))) & $000000FF) +
			", A: " + ((Pixel Shr ProcessColorLocation(Encoding.Find("A"))) & $000000FF))
End

Function PrintColor:Void(Pixel:Int, Encoding:String="ARGB")
	Print(ColorToString(Pixel, Encoding))

	Return
End

' This is just a wrapper for the main implementation:
Function PushSeed:Bool()
	Return PushSeed(Seed)
End

' The return value of this function specifies if the seed-stack already existed.
Function PushSeed:Bool(Seed:Int)
	' Local variable(s):
	Local Response:Bool = (SeedStack <> Null)

	If (Not Response) Then
		SeedStack = New IntStack()
	Endif

	SeedStack.Push(Seed)

	' Return the calculated response.
	Return Response
End

' This command retrieves a seed from the seed-stack,
' if no seed exists, the current randomization seed is returned.
Function PopSeed:Int()
	If (SeedStack <> Null) Then
		If (Not SeedStack.IsEmpty()) Then
			Return SeedStack.Pop()
		Endif
	Endif

	' Return the default response.
	Return Seed
End

' This command writes a standard line to a 'Stream'.
' This supports both 'LF', and 'CRLF' line endings currently, and this can be configured with 'WRITE_LINE_ENDTYPE'.
' Though character encoding is supported with this, only ASCII is supported by 'ReadLine'.
Function WriteLine:Bool(S:Stream, Line:String, CharacterEncoding:String="ascii")
	' Check for errors:
	If (S = Null) Then
		Return False
	Endif

	S.WriteString(Line, CharacterEncoding)

	#If WRITE_LINE_ENDTYPE = "CRLF"
		S.WriteByte(ASCII_CARRIAGE_RETURN)
	#End

	S.WriteByte(ASCII_LINE_FEED)

	' Return the default response.
	Return True
End

' This command reads a standard line from a 'Stream'. (This supports both 'LF', and 'CRLF' line endings currently)
' In addition, only 'ASCII' is currently supported.
Function ReadLine:String(S:Stream)
	' Local variable(s):
	Local Position:= S.Position()
	Local Padding:Int = 0 ' * SizeOf_Char
	Local Str:String

	#If Not READ_LINE_QUICKLY
		Local Size:Int = 0
	#End

	While (Not S.Eof())
		Local Char:= S.ReadByte()

		If (Char <> ASCII_LINE_FEED) Then
			If (Char <> ASCII_CARRIAGE_RETURN) Then
				#If READ_LINE_QUICKLY
					Str += String.FromChar(Char)
				#Else
					Size += 1
				#End
			Else
				Padding = 2*SizeOf_Char
			Endif
		Else
			#Rem
				If (Padding = 0) Then
					Padding = 1
				Endif
			#End

			Padding = Max(Padding, 1*SizeOf_Char)

			Exit
		Endif
	Wend

	#If Not READ_LINE_QUICKLY
		S.Seek(Position)

		Str = S.ReadString(Size, "ascii")

		S.Seek(S.Position()+Padding)
	#End

	' Return the string we read from the stream.
	Return Str
End

Function ResizeBuffer:DataBuffer(Buffer:DataBuffer, Size:Int=AUTOMATIC_LENGTH, CopyData:Bool=True, DiscardOldBuffer:Bool=False, OnlyWhenDifferentSizes:Bool=False)
	Local BufferAvailable:Bool = (Buffer <> Null)

	If (BufferAvailable And OnlyWhenDifferentSizes) Then
		If (Size <> AUTOMATIC_LENGTH And Buffer.Length() = Size) Then
			Return Buffer
		Endif
	Endif

	If (Size = AUTOMATIC_LENGTH) Then
		Size = Buffer.Length()
	Endif

	' Allocate a new data-buffer.
	Local B:= New DataBuffer(Size)

	' Copy the buffer's bytes over to 'B'.
	If (BufferAvailable) Then
		If (CopyData) Then
			' Copy the contents of 'Buffer' to the newly generated buffer-object.
			Buffer.CopyBytes(0, B, 0, Buffer.Length())
		Endif

		If (DiscardOldBuffer) Then
			' Discard the old buffer.
			Buffer.Discard()
		Endif
	Endif

	' Return the newly generated buffer.
	Return B
End

#If CONSOLE_IMPLEMENTED
	Function DebugBind:Bool(C:Console)
		If (C = Null) Then Return False

		DebugConsole = C

		' Return the default response.
		Return True
	End
#End

Function DebugError:Void(E:Throwable, StopExecution:Bool=True)
	#If CONFIG = "debug"
		DebugStop()
	#Else
		DebugPrint("Unknown exception has been thrown; continuing anyway.")
	#End

	Return
End

Function DebugError:Void(Msg:String, StopExecution:Bool=True)
	#If DEBUG_PRINT
		' Local variable(s):
		Local TempMsg:String

		If (StopExecution) Then
			TempMsg = ErrorTemplate
		Else
			TempMsg = LogTemplate
		Endif

		#If DEBUG_PRINT_QUOTES
			Msg = Tempmsg + Quote + Msg + Quote
		#Else
			Msg = TempMsg + Msg
		#End

		#If CONSOLE_IMPLEMENTED
			If (DebugConsole <> Null) Then
				DebugConsole.WriteLine(Msg, True)
			Else
		#End

		Print(Msg)

		#If CONSOLE_IMPLEMENTED
			Endif
		#End
	#Else
		' This may change later:
		If (StopExecution) Then
			Msg = ErrorTemplate + Msg
		Endif
	#End

	If (StopExecution) Then
		#If CONFIG = "debug"
			#If DEBUG_PRINT_ON_ERROR
				DebugStop()
			#Else
				Error(Msg)
			#End
		#Else
			#If DEBUG_PRINT
				Local FinalStr:String = (ErrorTemplate + Quote + "Attempt to stop execution failed. (Reason: Release-mode)" + Quote)

				#If CONSOLE_IMPLEMENTED
					If (DebugConsole <> Null) Then
						DebugConsole.WriteLine(FinalStr, True)
					Else
				#End

				Print(FinalStr)

				#If CONSOLE_IMPLEMENTED
					Endif
				#End
			#Else
				Error(Msg)
			#End
		#End
	Endif

	#If CONFIG = "debug"
		' Nothing so far.
	#Else
		' Nothing so far.
	#End

	Return
End

Function DebugPrint:Void(Str:String, StopExecution:Bool=False)
	DebugError(Str, StopExecution)

	Return
End

' The following functions are designed to be used with generic classes:
Function TypeIsObject:Bool(O:Object)
	Return True
End

Function TypeIsObject:Bool(I:Int)
	Return False
End

Function TypeIsObject:Bool(B:Bool)
	Return False
End

Function TypeIsObject:Bool(F:Float)
	Return False
End

Function TypeIsObject:Bool(S:String)
	Return False
End

Function TypeOf:Int(O:Object)
	Return TYPE_OBJECT
End

Function TypeOf:Int(I:Int)
	Return TYPE_INT
End

Function TypeOf:Int(B:Bool)
	Return TYPE_BOOL
End

Function TypeOf:Int(F:Float)
	Return TYPE_FLOAT
End

Function TypeOf:Int(S:String)
	Return TYPE_STRING
End

' Classes:
Class GenericUtilities<T>
	' Constant variable(s):

	' Comparison response codes (Positive numbers are for error-reporting):
	Const COMPARE_RESPONSE_IDENTICAL:Int			= -1
	Const COMPARE_RESPONSE_WRONG_LENGTH:Int			= -2

	' Other:
	Const AUTO:= UTIL_AUTO

	' Global variable(s):

	' For internal and extern use. That being said, please do not modify this value.
	Global NIL:T

	' Functions:

	' This command gives the user the type-code of 'T'.
	Function Type:Int()
		' Return the type code of 'NIL'.
		Return TypeOf(NIL)
	End

	' This command specifies if 'T' is an object.
	Function IsObject:Bool()
		Return TypeIsObject(NIL)
	End

	' This command wraps the standard 'BoolToString' conversion command.
	Function AsString:String(Input:Bool)
		Return BoolToString(Input)
	End

	' This command reads a string from a standard 'Stream' object.
	Function AsString:String(S:Stream, Length:Int=AUTO, Encoding:String="utf8")
		If (Length = AUTO) Then
			Length = S.Length()
		Endif

		Return S.ReadString(Length, Encoding)
	End

	Function AsString:String(Input:T[], Offset:Int=0, Length:Int=AUTO, AddSpaces:Bool=True)
		' Local variable(s):
		Local Output:String = LeftBracket

		' If no length was specified, use the array's length.
		If (Length = AUTO) Then
			Length = Input.Length()
		Endif

		Local VirtualLength:= Length+Offset

		For Local Index:Int = Offset Until VirtualLength
			Output += Input[Index]

			If (Index+1 < VirtualLength) Then
				Output += Comma

				If (AddSpaces) Then
					Output += Space
				Endif
			Endif
		Next

		Return Output + RightBracket
	End

	Function CopyStringToArray:T[](S:String, Input:T[], Offset:Int=0, Length:Int=AUTO)
		If (Length = AUTO) Then
			Length = Min(S.Length(), Input.Length())
		Endif

		For Local I:Int = Offset Until Length
			Input[I] = S[I]
		Next

		' Just for the sake of convenience, return the 'Input' array.
		Return Input
	End

	Function IndexOfList:T(L:List<T>, Index:Int=0)
		' Local variable(s):
		Local Data:list.Node<T> = L.FirstNode()

		For Local I:= 0 Until Index
			Data = Data.NextNode()

			' Not my favorite method, but it works:
			If (Data = Null) Then
				Return NIL
			Endif
		Next

		' Return the value of the assessed node.
		Return Data.Value()
	End

	Function Zero:T[](Input:T[])
		Return Nil(Input)
	End

	Function Nil:T[](Input:T[])
		For Local Index:= 0 Until Input.Length()
			Input[Index] = NIL
		Next

		Return Input
	End

	Function PrintArray:Void(Input:T[])
		Print(AsString(Input))

		Return
	End

	#Rem
		NOTES:
			* In the event of an error, an empty array will be produced.

			* The 'CopyArray' command's 'FitSource' argument should only be enabled with the
			knowledge that the original destination may have been discarded.

			Your code must reflect this by disregarding the original array,
			and simply assigning the old array to the retrun value.

			EXAMPLE:
				' Local variable(s):
				Local A:T[10], A2:T[3]

				' This will likely produce a new 'T' array, based on the area-delta.
				A2 = CopyArray(A, A2, True)
	#End

	Function CopyArray:T[](Source:T[], Destination:T[], FitSource:Bool)
		Return CopyArray(Source, Destination, 0, 0, AUTO, AUTO, FitSource)
	End

	Function CopyArray:T[](Source:T[], Destination:T[], Source_Offset:Int=0, Destination_Offset:Int=0, Source_Length:Int=AUTO, Destination_Length:Int=AUTO, FitSource:Bool=False)
		If (Source_Length = AUTO) Then
			Source_Length = Source.Length()
		Endif

		If (Destination_Length = AUTO) Then
			Destination_Length = Destination.Length()
		Endif

		' Local variable(s):

		' These two are used as caches for the real lengths of the arrays:
		Local Destination_RealLength:= Destination.Length()
		Local Source_RealLength:= Source.Length()

		' Calculate the source and destination areas:
		Local Source_Area:Int = (Source_Length-Source_Offset)

		' Make sure we have a source to work with:
		If (Source_Area <= 0) Then
			' The source-area is too small for use, return an empty array.
			Return []
		Endif

		Local Destination_Area:Int = (Destination_Length-Destination_Offset)

		' For the sake of safety, we'll also check the destination area:
		If (Destination_Area <= 0) Then
			' The destination-area is too small for use, return an empty array.
			Return []
		Endif

		Local Operation_Area:Int

		If (FitSource And Destination_Area < Source_Area) Then
			Local AreaDelta:Int = (Source_Area-Destination_Area)
			Local NewArea:Int = (Destination_RealLength+AreaDelta)

			If (NewArea > Destination_RealLength) Then
				Destination = Destination.Resize(NewArea)
			Else
				Destination = Destination.Resize(Destination_Length+AreaDelta)
			Endif

			Destination_Area = Source_Area
			Operation_Area = Destination_Area
		Else
			Operation_Area = Min(Source_Area, Destination_Area)
		Endif

		' Copy the contents of the source-array into the destination-array:
		For Local Index:= 0 Until Operation_Area
			Destination[Index+Destination_Offset] = Source[Index+Source_Offset]
		Next

		' Return the destination-array.
		Return Destination
	End

	Function CopyArray:T[](Source:T[])
		Return CloneArray(Source)
	End

	Function CloneArray:T[](Source:T[])
		Return CopyArray(Source, New T[Source.Length()])
	End

	' This command returns a positive number upon an error,
	' otherwise a 'response code' will be given (See the "Contant variable(s)" section for details).
	Function Compare:Int(A1:T[], A2:T[], CheckLength:Bool=True)
		' Local variable(s):
		Local A1_Length:= A1.Length
		Local A2_Length:= A2.Length

		' Check for errors:
		If (CheckLength) Then
			' Make sure they're both the same length.
			If (A1_Length <> A2_Length) Then
				Return COMPARE_RESPONSE_WRONG_LENGTH
			Endif
		Endif

		For Local I:= 0 Until Min(A1_Length, A2_Length)
			If (A1[I] <> A2[I]) Then
				' Not the best of escape methods, but it works.
				Return I
			Endif
		Next

		' Return the default response.
		Return COMPARE_RESPONSE_IDENTICAL
	End

	' This function returns positive if both arrays are identical.
	Function SimpleCompare:Bool(A1:T[], A2:T[], CheckLength:Bool=True)
		Return (Compare(A1, A2, CheckLength) = COMPARE_RESPONSE_IDENTICAL)
	End

	Function Read:T(S:Stream)
		Return Read(S, NIL)
	End

	Function Read:T[](S:Stream, DataArray:T[], Size:Int=AUTO)
		If (Size = AUTO) Then Size = S.ReadInt()

		If (Size > 0) Then
			If (DataArray.Length() = 0) Then
				DataArray = New T[Size]
			Endif
		Endif

		' Local variable(s):
		Local DLength:Int = Min(DataArray.Length, Size)

		For Local Index:= 0 Until DLength
			DataArray[Index] = Read(S, NIL)
		Next

		Return DataArray
	End

	Function Write:Void(S:Stream, DataArray:T[], WriteLength:Bool=True)
		' Local variable(s):
		Local DLength:= DataArray.Length()

		If (WriteLength) Then S.WriteInt(DLength)

		For Local Index:= 0 Until DLength
			Write(S, DataArray[Index])
		Next

		Return
	End

	Function Read:Int(S:Stream, Indentifier:Int, Size:Int=4)
		' Local variable(s):
		Local Data:Int = 0

		If (Size > 1) Then
			If (Size < 4) Then
				Data = S.ReadShort()
			Else
				If (Size > 4) Then
					S.ReadInt()
				Endif

				Data = S.ReadInt()
			Endif
		Else
			Data = S.ReadByte()
		Endif

		Return Data
	End

	Function Write:Void(S:Stream, Data:Int, Size:Int=4)
		Size = IntSize(Size)

		If (Size > 1) Then
			If (Size < 4) Then
				S.WriteShort(Data)
			Else
				If (Size > 4) Then
					S.WriteInt(0)
				Endif

				S.WriteInt(Data)
			Endif
		Else
			S.WriteByte(Data)
		Endif

		Return
	End

	#Rem
	Function Read:Bool(S:Stream, Identifier:Bool)
		Return Read(S, Int(Identifier), 1)
	End

	Function Write:Void(S:Stream, B:Bool)
		Write(S, Int(B), 1)

		Return
	End
	#End

	Function Read:Float(S:Stream, Identifier:Float)
		Return S.ReadFloat()
	End

	Function Write:Void(S:Stream, Data:Float)
		S.WriteFloat(Data)

		Return
	End

	Function Read:String(S:Stream, Data:String, Encoding:String="utf8", Size:Int=AUTO)
		If (Size = AUTO) Then
			Size = S.ReadInt()
		Endif

		Data = S.ReadString(Size, Encoding)

		' Return the newly read string.
		Return Data
	End

	Function Write:Void(S:Stream, Data:String, Encoding:String="utf8", WriteSize:Bool=True)
		If (WriteSize) Then
			S.WriteInt(Data.Length())
		Endif

		S.WriteString(Data, Encoding)

		Return
	End

	#If UTIL_SUPPORT_IOELEMENTS
		Function Read:Void(S:Stream, Data:InputChildElement)
			If (Data = Null) Then
				Return
			Endif

			Data.Load(S)

			Return
		End

		Function Write:Void(S:Stream, Data:OutputChildElement)
			If (Data = Null) Then
				Return
			Endif

			Data.Save(S)
		End
	#End

	' Constructor(s):

	' DO NOT CREATE NEW INSTANCES OF THIS CLASS.
	Method New()
		DebugError("This class should not be used in this was.")
	End
End


one more fun test for postfix operator being correct!

let reduce = fn(arr, initial, f) {
    let iter = fn(arr, result) {
        if (len(arr) == 0) {
            result
        } else {
            iter(tail(arr) , f(result , first (arr)))
        }
    };
    iter(arr, initial);
};

let sum = fn(arr) {
    reduce(arr, 0, fn(initial, el) {
        initial + el
    });
};

let array = [1, 2, 3, 4, 5];
let sum = sum(array);
putln("Sum: " + sum);
putln(push(array, 6));

let addNums = fn(x, y) {
    return x + y;
}

let a = 3;
if(true) {
    let a = a + 2;
    putln(a);
}
putln(a);
putln();

let fizz = fn(num) { num % 3 == 0 };
let buzz = fn(num) { num % 5 == 0 };
let num = 1;
while(num <= 100) {
    if(fizz(num)) {
        put("fizz");
    }
    if (buzz(num)) {
        put("buzz");
    }
    if(!fizz(num) && !buzz(num)) {
        put(num);
    }
    putln();
    num++;
}

let a = "hello";
putln(substr(a, 0, 3) * 3);

let num = 2;
putln("Should print 3: " + ++num)
putln("Should print 3: " + num++)
putln("Should print 4: " + num)

let test_arr = [1, 2, 3, 4, 5];
let index = 0;
while(index < len(test_arr)) {
    putln(test_arr[index++]);
}


Reset internal renderPos cache in Sprite after scale change

Strict

Private

Import align
Import basedisplayobject
Import bono.kernel
Import bono.utils
Import mojo.graphics

Public

Class Sprite Extends BaseDisplayObject
    Private

    Field currentFrame:Int
    Field frameCount:Int
    Field frameSize:Vector2D
    Field frameTimer:Int
    Field image:Image
    Field imageName:String
    Field _scale:Vector2D = New Vector2D(1, 1)
    Field _halign:Int = Align.LEFT
    Field _valign:Int = Align.TOP
    Field renderPos:Vector2D

    Public

    Field frameSpeed:Int
    Field loopAnimation:Bool
    Field rotation:Float

    Method New(imageName:String, pos:Vector2D=Null)
        Self.imageName = imageName

        LoadImage()
        If pos Then SetPosition(pos)
    End

    Method New(imageName:String, frameSize:Vector2D, frameCount:Int, frameSpeed:Int, pos:Vector2D=Null)
        Self.imageName = imageName
        Self.frameSize = frameSize
        Self.frameCount = frameCount
        Self.frameSpeed = frameSpeed

        LoadImage()
        If pos Then SetPosition(pos)
    End

    Method OnRender:Void()
        If Not renderPos Then CalculateRenderPos()
        GetColor().Activate()
        DrawImage(image, renderPos.x, renderPos.y, rotation, scale.x, scale.y, currentFrame)
        GetColor().Deactivate()
    End

    Method OnUpdate:Void(deltaTimer:DeltaTimer)
        If frameCount <= 0 Then Return
        If animationIsDone Then Return

        If frameTimer < frameSpeed
            frameTimer += deltaTimer.frameTime
            Return
        End

        If (currentFrame + 1) = frameCount
            If loopAnimation
                currentFrame = 1
            End
        Else
            currentFrame += 1
        End
        frameTimer = 0
    End

    Method Restart:Void()
        currentFrame = 0
    End

    Method animationIsDone:Bool() Property
        If loopAnimation Then Return False
        Return (currentFrame = frameCount)
    End

    Method scale:Vector2D() Property
        Return _scale
    End

    Method scale:Void(newScale:Vector2D) Property
        If image Then GetSize().Div(_scale).Mul(newScale)
        _scale = newScale
        renderPos = Null
    End

    Method filepath:String() Property
        Return imageName
    End

    Method halign:Int() Property
        Return _halign
    End

    Method halign:Void(newAlign:Int) Property
        _halign = newAlign
        renderPos = Null
    End

    Method valign:Int() Property
        Return _valign
    End

    Method valign:Void(newAlign:Int) Property
        _valign = newAlign
        renderPos = Null
    End

    Method SetPosition:Void(newPos:Vector2D)
        Super.SetPosition(newPos)
        renderPos = Null
    End

    Method Collide:Bool(checkPos:Vector2D)
        Local offset:Vector2D = New Vector2D()
        Align.AdjustHorizontal(offset, Self, halign)
        Align.AdjustVertical(offset, Self, valign)

        Return Super.Collide(checkPos.Copy().Sub(offset))
    End

    Private

    Method CalculateRenderPos:Void()
        renderPos = GetPosition().Copy()
        Align.AdjustHorizontal(renderPos, Self, halign)
        Align.AdjustVertical(renderPos, Self, valign)
    End

    Method LoadImage:Void()
        If frameSize
            image = graphics.LoadImage(imageName, frameSize.x, frameSize.y, frameCount)
            SetSize(frameSize.Copy())
        Else
            image = graphics.LoadImage(imageName)
            SetSize(New Vector2D(image.Width(), image.Height()))
        End

        If Not image Then Error("Unable to load: " + imageName)
        GetSize().Mul(scale)
    End
End

Strict

Private

Import align
Import basedisplayobject
Import bono.kernel
Import bono.utils
Import mojo.graphics

Public

Class Sprite Extends BaseDisplayObject
    Private

    Field currentFrame:Int
    Field frameCount:Int
    Field frameSize:Vector2D
    Field frameTimer:Int
    Field image:Image
    Field imageName:String
    Field _scale:Vector2D = New Vector2D(1, 1)
    Field _halign:Int = Align.LEFT
    Field _valign:Int = Align.TOP
    Field renderPos:Vector2D

    Public

    Field frameSpeed:Int
    Field loopAnimation:Bool
    Field rotation:Float

    Method New(imageName:String, pos:Vector2D=Null)
        Self.imageName = imageName

        LoadImage()
        If pos Then SetPosition(pos)
    End

    Method New(imageName:String, frameSize:Vector2D, frameCount:Int, frameSpeed:Int, pos:Vector2D=Null)
        Self.imageName = imageName
        Self.frameSize = frameSize
        Self.frameCount = frameCount
        Self.frameSpeed = frameSpeed

        LoadImage()
        If pos Then SetPosition(pos)
    End

    Method OnRender:Void()
        If Not renderPos Then CalculateRenderPos()
        GetColor().Activate()
        DrawImage(image, renderPos.x, renderPos.y, rotation, scale.x, scale.y, currentFrame)
        GetColor().Deactivate()
    End

    Method OnUpdate:Void(deltaTimer:DeltaTimer)
        If frameCount <= 0 Then Return
        If animationIsDone Then Return

        If frameTimer < frameSpeed
            frameTimer += deltaTimer.frameTime
            Return
        End

        If (currentFrame + 1) = frameCount
            If loopAnimation
                currentFrame = 1
            End
        Else
            currentFrame += 1
        End
        frameTimer = 0
    End

    Method Restart:Void()
        currentFrame = 0
    End

    Method animationIsDone:Bool() Property
        If loopAnimation Then Return False
        Return (currentFrame = frameCount)
    End

    Method scale:Vector2D() Property
        Return _scale
    End

    Method scale:Void(newScale:Vector2D) Property
        If image Then GetSize().Div(_scale).Mul(newScale)
        _scale = newScale
    End

    Method filepath:String() Property
        Return imageName
    End

    Method halign:Int() Property
        Return _halign
    End

    Method halign:Void(newAlign:Int) Property
        _halign = newAlign
        renderPos = Null
    End

    Method valign:Int() Property
        Return _valign
    End

    Method valign:Void(newAlign:Int) Property
        _valign = newAlign
        renderPos = Null
    End

    Method SetPosition:Void(newPos:Vector2D)
        Super.SetPosition(newPos)
        renderPos = Null
    End

    Method Collide:Bool(checkPos:Vector2D)
        Local offset:Vector2D = New Vector2D()
        Align.AdjustHorizontal(offset, Self, halign)
        Align.AdjustVertical(offset, Self, valign)

        Return Super.Collide(checkPos.Copy().Sub(offset))
    End

    Private

    Method CalculateRenderPos:Void()
        renderPos = GetPosition().Copy()
        Align.AdjustHorizontal(renderPos, Self, halign)
        Align.AdjustVertical(renderPos, Self, valign)
    End

    Method LoadImage:Void()
        If frameSize
            image = graphics.LoadImage(imageName, frameSize.x, frameSize.y, frameCount)
            SetSize(frameSize.Copy())
        Else
            image = graphics.LoadImage(imageName)
            SetSize(New Vector2D(image.Width(), image.Height()))
        End

        If Not image Then Error("Unable to load: " + imageName)
        GetSize().Mul(scale)
    End
End


Added SelectedImage for buttons

Added SelectedImage for buttons

--HG--
extra : convert_revision : svn%3Ae934d3cd-0d57-f34a-94d0-9e8d31ae1c29/trunk%40465

Import diddy

Const VERTICAL:Int = 0
Const HORIZONTAL:Int = 1

Class SimpleMenu Extends List<SimpleButton>
	Field x:Float, y:Float
	Field buttonGap:Int = 0
	Field mouseOverName:String = ""
	Field clickedName:String = ""
	Field clearClickedName:Int = 1
	Field nextX:Int = 0
	Field nextY:Int = 0
	Field w:Int, h:Int
	Field addGap:Int = 0
	Field soundMouseOver:GameSound
	Field soundClick:GameSound
	Field useVirtualRes:Bool = False
	Field orientation:Int = VERTICAL

	Method New()
		Error "Please use a different constructor"
	End

	Method New(soundMouseOverFile$, soundClickFile$, x:Int, y:Int, gap:Int, useVirtualRes:Bool, orientation:Int = VERTICAL)
		Init(soundMouseOverFile, soundClickFile, x, y, gap, useVirtualRes, orientation)
	End

	Method Init:Void(soundMouseOverFile:String="", soundClickFile:String="", x:Float, y:Float, gap:Int, useVirtualRes:Bool, orientation:Int)
		Self.Clear()
		Self.useVirtualRes = useVirtualRes
		Self.orientation = orientation
		Self.x = x
		Self.y = y
		nextX = x
		nextY = y
		Self.buttonGap = gap
		w = 0
		h = 0
		mouseOverName = ""
		clickedName = ""
		addGap = 0
		If soundMouseOverFile<>"" Then
			soundMouseOver = New GameSound
			soundMouseOver.Load(soundMouseOverFile)
		End
		If soundClickFile<>"" Then
			soundClick = New GameSound
			soundClick.Load(soundClickFile)
		End
	End

	Method CalcWidth:Int()
		Local left:Int=10000
		Local right:Int=-10000
		Local b:SimpleButton
		For b = EachIn Self
			If b.x < left Then left = b.x
			If b.x+b.image.w > right Then right = b.x + b.image.w
		Next
		w = right - left
		Return w
	End

	Method CalcHeight:Int()
		Local top:Int=10000
		Local bot:Int=-10000
		Local b:SimpleButton
		For b = EachIn Self
			If b.y < top Then top = b.y
			If b.y+b.image.h > bot Then bot = b.y + b.image.h
		Next
		h = bot - top
		Return h
	End

	Method SetX:Void(thex#)
		CalcLeft()
		Local oldx# = x
		x = thex
		Local diff# = x - oldx
		Local b:SimpleButton
		For b = EachIn Self
			b.MoveBy(diff,0)
		Next
	End

	Method SetY:Void(they#)
		CalcTop()
		Local oldy# = y
		y = they
		Local diff# = y-oldy
		Local b:SimpleButton
		For b = EachIn Self
			b.MoveBy(0,diff)
		Next
	End

	Method CalcLeft:Void()
		x = 10000
		Local b:SimpleButton
		For b = EachIn Self
			If b.x <x Then x = b.x
		Next
	End

	Method CalcTop:Void()
		y = 10000
		Local b:SimpleButton
		For b = EachIn Self
			If b.y < y Then y = b.y
		Next
	End

	Method CentreHoriz:Void()
		CalcWidth()
		if useVirtualRes
			SetX((SCREEN_WIDTH-w)/2)
		Else
			SetX((DEVICE_WIDTH-w)/2)
		End
	End

	Method CentreVert:Void()
		CalcHeight()
		if useVirtualRes
			SetY((SCREEN_HEIGHT-h)/2)
		Else
			SetY((DEVICE_HEIGHT-h)/2)
		End
	End

	Method Centre:Void()
		CentreHoriz()
		CentreVert()
	End

	Method SetMenuAlpha:Void(alpha:Float)
		Local b:SimpleButton
		For b = EachIn Self
			b.alpha = alpha
		Next
	End

	Method AddButton:SimpleButton(buttonImageFile:String, mouseOverFile:String, name:String="")
		Local b:SimpleButton = ProcessAddButton(buttonImageFile, mouseOverFile, name)
		If orientation = VERTICAL
			IncreaseHeight(b)
		Else
			IncreaseWidth(b)
		End
		Return b
	End

	Method IncreaseHeight:Void(b:SimpleButton)
		nextY = nextY + b.image.h + buttonGap

		h = h + b.image.h
		If addGap Then
			h = h + buttonGap
		Else
			addGap = 1
		End
	End

	Method IncreaseWidth:Void(b:SimpleButton)
		nextX = nextX + b.image.w + buttonGap

		w = w + b.image.w
		If addGap Then
			w = w + buttonGap
		Else
			addGap = 1
		End
	End

	Method ProcessAddButton:SimpleButton(buttonImageFile:String, mouseOverFile:String, name:String)
		Local b:SimpleButton = New SimpleButton
		b.Load(buttonImageFile, mouseOverFile)
		b.useVirtualRes = Self.useVirtualRes
		b.orientation = Self.orientation
		If name <> "" Then b.name = name.ToUpper()
		If orientation = VERTICAL
			b.CentreX(nextY)
		Else
			b.MoveTo(nextX, nextY)
		End

		b.soundMouseOver = soundMouseOver
		b.soundClick = soundClick
		AddLast(b)
		Return b
	End

	Method FindButton:SimpleButton(name:String)
		name = name.ToUpper()
		Local b:SimpleButton
		For b = EachIn Self
			If b.name = name Then Return b
		Next
		Return Null
	End

	Method Clicked:Int(name:String)
		name = name.ToUpper()
		If name = clickedName
			If clearClickedName Then clickedName = ""
			Return 1
		Else
			Return 0
		End
	End

	Method Update:Int()
		If game.screenFade.active
			Return 0
		EndIf
		clickedName = ""
		Local b:SimpleButton
		For b = EachIn Self
			b.Update()
			If b.mouseOver Then mouseOverName = b.name
			If b.clicked Then clickedName = b.name
		Next
		Return 1
	End

	Method Precache:Void()
		For Local b:SimpleButton = EachIn Self
			b.Precache()
		Next
	End

	Method Draw:Void()
		For Local b:SimpleButton = EachIn Self
			b.Draw()
		Next
	End
End

Class SimpleButton Extends Sprite
	Field active:Int = 1
	Field clicked:Int = 0
	Field selected:Int = 0
	Field mouseOver:Int = 0
	Field disabled:Bool = False
	Field soundMouseOver:GameSound
	Field soundClick:GameSound
	Field imageMouseOver:GameImage
	Field imageSelected:GameImage
	Field useVirtualRes:Bool = False
	Field orientation:Int = VERTICAL

	Method Precache:Void()
		If image<>null
			Super.Precache()
		End
	End

	Method Draw:Void()
		If active = 0 Then Return
		SetAlpha Self.alpha
		if mouseOver
			DrawImage Self.imageMouseOver.image, x, y
		ElseIf selected And imageSelected <> null Then
			DrawImage Self.imageSelected.image, x, y
		Else
			DrawImage Self.image.image, x, y
		EndIf
		SetAlpha 1
	End

	Method Click:Void()
		If clicked = 0
			clicked = 1
			If soundClick <> null
				soundClick.Play()
			End
		End
	End

	Method CentreX:Void(yCoord:Int)
		if useVirtualRes
			MoveTo((SCREEN_WIDTH-image.w)/2, yCoord)
		Else
			MoveTo((DEVICE_WIDTH-image.w)/2, yCoord)
		End

	End

	Method CentreY:Void(xCoord:Int)
		If useVirtualRes
			MoveTo((SCREEN_HEIGHT-image.h)/2, xCoord)
		Else
			MoveTo((DEVICE_HEIGHT-image.h)/2, xCoord)
		End
	End

	Method MoveBy:Void(dx:Float,dy:Float)
		x+=dx
		y+=dy
	End Method

	Method MoveTo:Void(dx:Float,dy:Float)
		x=dx
		y=dy
	End Method

	Method Load:Void(buttonImage:String, mouseOverImage:String = "", soundMouseOverFile:String="", soundClickFile:String="")
		Self.image = New GameImage
		image.Load(game.images.path + buttonImage, False)

		if  mouseOverImage <> ""
			imageMouseOver = New GameImage
			imageMouseOver.Load(game.images.path + mouseOverImage, False)
		End

		name = StripAll(buttonImage.ToUpper())

		If soundMouseOverFile<>"" Then
			soundMouseOver = New GameSound
			soundMouseOver.Load(soundMouseOverFile)
		End
		If soundClickFile<>"" Then
			soundClick = New GameSound
			soundClick.Load(soundClickFile)
		End
	End

	Method SetSelectedImage:Void(buttonImage:String)
		imageSelected = New GameImage
		imageSelected.Load(game.images.path + buttonImage, False)
	End

	Method Update:Void()
		If active = 0 or disabled Then Return
		Local mx:Int = game.mouseX
		Local my:Int = game.mouseY
		if not useVirtualRes
			mx = MouseX()
			my = MouseY()
		End
		If mx >= x And mx < x+image.w And my >= y And my < y+image.h Then
			If mouseOver = 0
				if soundMouseOver <> null
					soundMouseOver.Play()
				End
			End
			mouseOver = 1
			If MouseHit() Then
				Click()
			Else
				clicked = 0
			End
		Else
			mouseOver = 0
			clicked = 0
		End
	End
End

Class SimpleSlider Extends Sprite
	Field active:Int
	Field dotImage:GameImage
	Field dotX:Int, dotY:Int
	Field value:Int
	Field border:Int=0
	Field borderY:Int=5
	Field useVirtualRes:Bool = False

	Method New(barFile:String, dotFile:String, x:Int, y:int, border:int = 0, name:String="", borderY:int=5, useVirtualRes:Bool = True)
		Self.image = New GameImage
		Self.useVirtualRes = useVirtualRes

		image.Load(game.images.path + barFile, False)
		name = StripAll(barFile.ToUpper())

		dotImage = New GameImage
		dotImage.Load(game.images.path + dotFile, False)
		dotImage.name = StripAll(dotFile.ToUpper())

		Self.x = x
		Self.y = y
		Self.border = border
		Self.borderY = borderY

		Self.SetValue(50)
		Self.dotY = y-3
		Self.active = 1
	End

	Method SetValue:Void(toSet:int)
		value = toSet
		If toSet < 0 Then value = 0
		If toSet > 100 Then value = 100
		Local percent:Float = value/100.0
		dotX = x + border + (percent * (image.w - (border * 2))) - dotImage.w2
	End Method

	Method Update:Int()
		Local change:Int=0
		If active
			Local buffer:int = 10
			Local mx:Int = game.mouseX
			Local my:Int = game.mouseY
			if not useVirtualRes
				mx = MouseX()
				my = MouseY()
			End
			If mx >= x-buffer And mx < x + image.w + buffer And my >= y-borderY And my < y+image.h+borderY
				If MouseDown(MOUSE_LEFT)
					If mx <= x+border
						SetValue(0)
						change = 1
					ElseIf mx >= x+image.w-border
						SetValue(100)
						change = 1
					Else
						Local d:Float = mx - x - border
						Local p:Float = d/(image.w-(border*2))
						SetValue(Round(p*100))
						change = 1
					End
				End
			End
		End
		Return change
	End

	Method Draw:Void()
		If active
			DrawImage(image.image,x,y)
			DrawImage(dotImage.image,dotX,dotY)
		End
	End
End

Import diddy

Const VERTICAL:Int = 0
Const HORIZONTAL:Int = 1

Class SimpleMenu Extends List<SimpleButton>
	Field x:Float, y:Float
	Field buttonGap:Int = 0
	Field mouseOverName:String = ""
	Field clickedName:String = ""
	Field clearClickedName:Int = 1
	Field nextX:Int = 0
	Field nextY:Int = 0
	Field w:Int, h:Int
	Field addGap:Int = 0
	Field soundMouseOver:GameSound
	Field soundClick:GameSound
	Field useVirtualRes:Bool = False
	Field orientation:Int = VERTICAL

	Method New()
		Error "Please use a different constructor"
	End

	Method New(soundMouseOverFile$, soundClickFile$, x:Int, y:Int, gap:Int, useVirtualRes:Bool, orientation:Int = VERTICAL)
		Init(soundMouseOverFile, soundClickFile, x, y, gap, useVirtualRes, orientation)
	End

	Method Init:Void(soundMouseOverFile:String="", soundClickFile:String="", x:Float, y:Float, gap:Int, useVirtualRes:Bool, orientation:Int)
		Self.Clear()
		Self.useVirtualRes = useVirtualRes
		Self.orientation = orientation
		Self.x = x
		Self.y = y
		nextX = x
		nextY = y
		Self.buttonGap = gap
		w = 0
		h = 0
		mouseOverName = ""
		clickedName = ""
		addGap = 0
		If soundMouseOverFile<>"" Then
			soundMouseOver = New GameSound
			soundMouseOver.Load(soundMouseOverFile)
		End
		If soundClickFile<>"" Then
			soundClick = New GameSound
			soundClick.Load(soundClickFile)
		End
	End

	Method CalcWidth:Int()
		Local left:Int=10000
		Local right:Int=-10000
		Local b:SimpleButton
		For b = EachIn Self
			If b.x < left Then left = b.x
			If b.x+b.image.w > right Then right = b.x + b.image.w
		Next
		w = right - left
		Return w
	End

	Method CalcHeight:Int()
		Local top:Int=10000
		Local bot:Int=-10000
		Local b:SimpleButton
		For b = EachIn Self
			If b.y < top Then top = b.y
			If b.y+b.image.h > bot Then bot = b.y + b.image.h
		Next
		h = bot - top
		Return h
	End

	Method SetX:Void(thex#)
		CalcLeft()
		Local oldx# = x
		x = thex
		Local diff# = x - oldx
		Local b:SimpleButton
		For b = EachIn Self
			b.MoveBy(diff,0)
		Next
	End

	Method SetY:Void(they#)
		CalcTop()
		Local oldy# = y
		y = they
		Local diff# = y-oldy
		Local b:SimpleButton
		For b = EachIn Self
			b.MoveBy(0,diff)
		Next
	End

	Method CalcLeft:Void()
		x = 10000
		Local b:SimpleButton
		For b = EachIn Self
			If b.x <x Then x = b.x
		Next
	End

	Method CalcTop:Void()
		y = 10000
		Local b:SimpleButton
		For b = EachIn Self
			If b.y < y Then y = b.y
		Next
	End

	Method CentreHoriz:Void()
		CalcWidth()
		if useVirtualRes
			SetX((SCREEN_WIDTH-w)/2)
		Else
			SetX((DEVICE_WIDTH-w)/2)
		End
	End

	Method CentreVert:Void()
		CalcHeight()
		if useVirtualRes
			SetY((SCREEN_HEIGHT-h)/2)
		Else
			SetY((DEVICE_HEIGHT-h)/2)
		End
	End

	Method Centre:Void()
		CentreHoriz()
		CentreVert()
	End

	Method SetMenuAlpha:Void(alpha:Float)
		Local b:SimpleButton
		For b = EachIn Self
			b.alpha = alpha
		Next
	End

	Method AddButton:SimpleButton(buttonImageFile:String, mouseOverFile:String, name:String="")
		Local b:SimpleButton = ProcessAddButton(buttonImageFile, mouseOverFile, name)
		If orientation = VERTICAL
			IncreaseHeight(b)
		Else
			IncreaseWidth(b)
		End
		Return b
	End

	Method IncreaseHeight:Void(b:SimpleButton)
		nextY = nextY + b.image.h + buttonGap

		h = h + b.image.h
		If addGap Then
			h = h + buttonGap
		Else
			addGap = 1
		End
	End

	Method IncreaseWidth:Void(b:SimpleButton)
		nextX = nextX + b.image.w + buttonGap

		w = w + b.image.w
		If addGap Then
			w = w + buttonGap
		Else
			addGap = 1
		End
	End

	Method ProcessAddButton:SimpleButton(buttonImageFile:String, mouseOverFile:String, name:String)
		Local b:SimpleButton = New SimpleButton
		b.Load(buttonImageFile, mouseOverFile)
		b.useVirtualRes = Self.useVirtualRes
		b.orientation = Self.orientation
		If name <> "" Then b.name = name.ToUpper()
		If orientation = VERTICAL
			b.CentreX(nextY)
		Else
			b.MoveTo(nextX, nextY)
		End

		b.soundMouseOver = soundMouseOver
		b.soundClick = soundClick
		AddLast(b)
		Return b
	End

	Method FindButton:SimpleButton(name:String)
		name = name.ToUpper()
		Local b:SimpleButton
		For b = EachIn Self
			If b.name = name Then Return b
		Next
		Return Null
	End

	Method Clicked:Int(name:String)
		name = name.ToUpper()
		If name = clickedName
			If clearClickedName Then clickedName = ""
			Return 1
		Else
			Return 0
		End
	End

	Method Update:Int()
		If game.screenFade.active
			Return 0
		EndIf
		clickedName = ""
		Local b:SimpleButton
		For b = EachIn Self
			b.Update()
			If b.mouseOver Then mouseOverName = b.name
			If b.clicked Then clickedName = b.name
		Next
		Return 1
	End

	Method Precache:Void()
		For Local b:SimpleButton = EachIn Self
			b.Precache()
		Next
	End

	Method Draw:Void()
		For Local b:SimpleButton = EachIn Self
			b.Draw()
		Next
	End
End

Class SimpleButton Extends Sprite
	Field active:Int = 1
	Field clicked:Int = 0
	Field mouseOver:Int = 0
	Field disabled:Bool = False
	Field soundMouseOver:GameSound
	Field soundClick:GameSound
	Field imageMouseOver:GameImage
	Field useVirtualRes:Bool = False
	Field orientation:Int = VERTICAL

	Method Precache:Void()
		If image<>null
			Super.Precache()
		End
	End

	Method Draw:Void()
		If active = 0 Then Return
		SetAlpha Self.alpha
		if mouseOver
			DrawImage Self.imageMouseOver.image, x, y
		else
			DrawImage Self.image.image, x, y
		EndIf
		SetAlpha 1
	End

	Method Click:Void()
		If clicked = 0
			clicked = 1
			If soundClick <> null
				soundClick.Play()
			End
		End
	End

	Method CentreX:Void(yCoord:Int)
		if useVirtualRes
			MoveTo((SCREEN_WIDTH-image.w)/2, yCoord)
		Else
			MoveTo((DEVICE_WIDTH-image.w)/2, yCoord)
		End

	End

	Method CentreY:Void(xCoord:Int)
		If useVirtualRes
			MoveTo((SCREEN_HEIGHT-image.h)/2, xCoord)
		Else
			MoveTo((DEVICE_HEIGHT-image.h)/2, xCoord)
		End
	End

	Method MoveBy:Void(dx:Float,dy:Float)
		x+=dx
		y+=dy
	End Method

	Method MoveTo:Void(dx:Float,dy:Float)
		x=dx
		y=dy
	End Method

	Method Load:Void(buttonImage:String, mouseOverImage:String = "", soundMouseOverFile:String="", soundClickFile:String="")
		Self.image = New GameImage
		image.Load(game.images.path + buttonImage, False)

		if  mouseOverImage <> ""
			imageMouseOver = New GameImage
			imageMouseOver.Load(game.images.path + mouseOverImage, False)
		End

		name = StripAll(buttonImage.ToUpper())

		If soundMouseOverFile<>"" Then
			soundMouseOver = New GameSound
			soundMouseOver.Load(soundMouseOverFile)
		End
		If soundClickFile<>"" Then
			soundClick = New GameSound
			soundClick.Load(soundClickFile)
		End
	End

	Method Update:Void()
		If active = 0 or disabled Then Return
		Local mx:Int = game.mouseX
		Local my:Int = game.mouseY
		if not useVirtualRes
			mx = MouseX()
			my = MouseY()
		End
		If mx >= x And mx < x+image.w And my >= y And my < y+image.h Then
			If mouseOver = 0
				if soundMouseOver <> null
					soundMouseOver.Play()
				End
			End
			mouseOver = 1
			If MouseHit() Then
				Click()
			Else
				clicked = 0
			End
		Else
			mouseOver = 0
			clicked = 0
		End
	End
End

Class SimpleSlider Extends Sprite
	Field active:Int
	Field dotImage:GameImage
	Field dotX:Int, dotY:Int
	Field value:Int
	Field border:Int=0
	Field borderY:Int=5
	Field useVirtualRes:Bool = False

	Method New(barFile:String, dotFile:String, x:Int, y:int, border:int = 0, name:String="", borderY:int=5, useVirtualRes:Bool = True)
		Self.image = New GameImage
		Self.useVirtualRes = useVirtualRes

		image.Load(game.images.path + barFile, False)
		name = StripAll(barFile.ToUpper())

		dotImage = New GameImage
		dotImage.Load(game.images.path + dotFile, False)
		dotImage.name = StripAll(dotFile.ToUpper())

		Self.x = x
		Self.y = y
		Self.border = border
		Self.borderY = borderY

		Self.SetValue(50)
		Self.dotY = y-3
		Self.active = 1
	End

	Method SetValue:Void(toSet:int)
		value = toSet
		If toSet < 0 Then value = 0
		If toSet > 100 Then value = 100
		Local percent:Float = value/100.0
		dotX = x + border + (percent * (image.w - (border * 2))) - dotImage.w2
	End Method

	Method Update:Int()
		Local change:Int=0
		If active
			Local buffer:int = 10
			Local mx:Int = game.mouseX
			Local my:Int = game.mouseY
			if not useVirtualRes
				mx = MouseX()
				my = MouseY()
			End
			If mx >= x-buffer And mx < x + image.w + buffer And my >= y-borderY And my < y+image.h+borderY
				If MouseDown(MOUSE_LEFT)
					If mx <= x+border
						SetValue(0)
						change = 1
					ElseIf mx >= x+image.w-border
						SetValue(100)
						change = 1
					Else
						Local d:Float = mx - x - border
						Local p:Float = d/(image.w-(border*2))
						SetValue(Round(p*100))
						change = 1
					End
				End
			End
		End
		Return change
	End

	Method Draw:Void()
		If active
			DrawImage(image.image,x,y)
			DrawImage(dotImage.image,dotX,dotY)
		End
	End
End


update to 0.9.2

update to 0.9.2

Updating the Main file to Version 0.9.2.

-updated: 'IntroScene', added therefor a Quotes-System, which loads
automatically, showing some Lighning effects, Skippable after Inittime
is over.
-Added some new Images
-Documentation is now updated

#Rem monkeydoc Module maniac
	Copyright (C) 2015  Stephan Duckerschein~n
	Version: 0.9.2 Alpha~n
	This Framework provides many additional Graphical Effects and primite Drawings, like unfilled rectangular , ellipsis etc. Diverse GUI Elements.~n
	It has it's own TileMap Engine included and even a Debug Tracking-System. ~n
	~n
	Installation:~n
	to use this Module, you have to Copy the "lib/" Folder data to Your App's Data.~n
	~n
	In the following is an Example, how to Include the maniac Framework to your Monkey Project.~n
Example:
<pre>
'This Example Shows how to integrate the Maniac-Framework to your App

'1. First You have to Import the Libs
import mojo
import maniac

'2. Main Function and App extending Class
Function Main:Int()
	New Example
	Return 0
End

Class Example extends App
	Method OnCreate:Int()
		SetUpdateRate( 60 )
		maniacInit()			' THIS INITS THE MANIAC FRAMEWORK! THIS NEED TO BE DONE BEFORE USING IT!!!!!
	end Method

	Method OnUpdate:int()
		maniacUpdate()			'THIS UPDATES ALL NEEDED DATA FOR THE MANIAC-GLOBALS
	end method

	Method OnRender:int()
		Cls

		maniacDraw()
	end Method
End class
</pre>

~n
Featurelist:
	GUI:
	- Button  (ver: 0.9)

#End

#rem
 <The Duke Game Framework. It provides useful little helperfunctions and class to develope 2D Games with Monkey X>
    Copyright (C) 2014-2015  Stephan Duckerschein

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
#end
Import mojo
'426
Import maniacTween				'665
Import maniacMisc				'684
Import maniacGraphics			'899
Import maniacFont				'249
Import maniacDebug				'334

'Importing GUI-Elements
Import maniacButton				'746
Import maniacTextfield
Import maniacTabLine
Import maniacSlider
Import maniacGallery
Import maniacRadioGroup
Import maniacCalendar
Import maniacCheckbox
Import maniacNumberSelector

#rem
	Global Data
#end
Global DW:Float,DH:Float',MX:Float,MY:Float

Global gl_clicked:Bool
Global gl_mousereleased:Bool

Global bClickedNext:Bool = False

Global MANIAC_DEBUG:Bool = False
Global MANIAC_LOADASYNC:Bool = False 		'## RECOMMEND: SET ON FALSE, as there is no Async Loader included @ the moment !!!

Global GLOBAL_SOUNDON:Bool = False 			'if set to false, No Sound at all; else it decides by local setting

Global GLOBAL_LANGUAGE:String 				'selected Language for Standard UI-
Const MANIAC_LANGUAGE_GERMAN:String 	= "Deutsch"
Const MANIAC_LANGUAGE_ENGLISH:String 	= "English"
Const MANAIC_LANGUAGE_FRENCH:String 	= "Francaise"

Global quotes:String[][]

#rem monkeydoc
	This Function returns the current Language.~n
	Return String
#end
Function getManiacLanguage:String()
	Return GLOBAL_LANGUAGE
End Function

#rem monkeydoc
	This Function sets the current Language.~n
#end
Function setManiacLanguage:Void(_Language:String = MANIAC_LANGUAGE_GERMAN)
	GLOBAL_LANGUAGE = _Language
End Function

#rem monkeydoc
	This Function sets the current global Caption Color.~n
#end
Function setManiacButton_CaptionColor:Void(_Color:Int )
	BUTTON_STD_CAPTIONCOLOR = _Color
End Function

'### StringPath to Std-Lib Images ###
Global IMG_LOGO:Int 					= 0 , PATH_IMG_LOGO:String 						= "lib/logo.png"
Global IMG_BACKGROUND:Int 				= 1 , PATH_IMG_BACKGROUND:String 				= "lib/Hintergrund.png"
Global IMG_STYLE_MODERN_BACKGROUND:Int 	= 2 , PATH_IMG_STYLE_MODERN_BACKGROUND:String 	= "lib/Button/ModernBackground.png"
Global IMG_STYLE_MODERN_FRAME:Int     	= 3	, PATH_IMG_STYLE_MODERN_FRAME:String 		= "lib/Button/ModernFrame.png"
Global IMG_STYLE_ROUND_BACKGROUND:Int 	= 4 , PATH_IMG_STYLE_ROUND_BACKGROUND:String 	= "lib/Button/RoundedBackground.png"
Global IMG_STYLE_ROUND_FRAME:Int		= 5 , PATH_IMG_STYLE_ROUND_FRAME:String			= "lib/Button/RoundedFrame.png"
Global IMG_STYLE_CIRCLE_BACKGROUND:Int 	= 6 , PATH_IMG_STYLE_CIRCLE_BACKGROUND:String 	= "lib/Button/CircleBackground.png"
Global IMG_STYLE_CIRCLE_FRAME:Int		= 7 , PATH_IMG_STYLE_CIRCLE_FRAME:String		= "lib/Button/CircleFrame.png"

Global IMG_SLIDER_FLATLINE:Int			= 8	, PATH_IMG_STYLE_FLATLINE:String			= "lib/Slider/Slider_Line.png"
Global IMG_SLIDER_PICKER:Int			= 9 , PATH_IMG_STYLE_PICKER:String				= "lib/Slider/Slider_Picker.png"

Global IMG_ICON_CHECKEDARROW:Int 		= 10, PATH_IMG_CHECKEDARROW:String 				= "lib/Icons/ico_check.png"
Global IMG_ICON_ARROWDOWN:Int			= 11, PATH_IMG_ARROWDOWN:String					= "lib/Icons/ico_arrowdown.png"
Global IMG_ICON_ARROWUP:Int				= 12, PATH_IMG_ARROWUP:String					= "lib/Icons/ico_arrowup.png"

'### Std-Lib Image/Sound Array ###
Global ManiacImg:Image[]
Global ManiacSnd:Sound[]
Global MANIAC_FONT:ManiacFont

'### Standard Init-Logo Time Settings ###
Global mInit:Bool = True
Global mInitTime:Int = 2500
Global mCurrInitTime:Int

Const ALIGNMENT_LEFT:Int 		= 1
Const ALIGNMENT_MIDDLE:Int 		= 2
Const ALIGNMENT_RIGHT:Int 		= 3
Const ALIGNMENT_TOP:Int 		= 4
Const ALIGNMENT_MIDDLEY:int 	= 5
Const ALIGNMENT_BOTTOM:Int 		= 6

Const ANIM_DROP:Int 	= 1
Const ANIM_FADE:Int		= 2
Const ANIM_ROTATE:Int 	= 3
Const ANIM_ROLL:Int		= 4
Const ANIM_SLIDE:Int 	= 5
Const ANIM_CIRCLE:Int	= 6
Const ANIM_POPOUT:Int 	= 7

Const BUTTON_STYLE_STD:Int 		= 0
Const BUTTON_STYLE_STDGLOW:Int 	= 1
Const BUTTON_STYLE_MODERN:Int 	= 2
Const BUTTON_STYLE_ROUND:Int 	= 3
Const BUTTON_STYLE_CIRCLE:Int	= 4
Global BUTTON_STD_CAPTIONCOLOR:Int 	= COLOR_WHITE
Global BUTTON_STD_MAINCOLOR:Int
Global BUTTON_STD_FRAMECOLOR:Int

Const BUTTON_STATE_MOUSEOVER:Int		= 90
Const BUTTON_STATE_MOUSECLICK:Int		= 91
Const BUTTON_STATE_MOUSECLICKDOWN:Int	= 92
Const BUTTON_STATE_MOUSERELEASED:Int 	= 93

Const TAB_DISPOSAL_MIDDLE:Int	= 0
Const TAB_DISPOSAL_ALL:Int		= 1
Const TAB_DISPOSAL_TOP:Int		= 2
Const TAB_DISPOSAL_BOTTOM:Int 	= 3
Const TAB_DISPOSAL_LEFT:Int		= 4
Const TAB_DISPOSAL_RIGHT:Int	= 5

Const TAB_ALIGN_TOP:Int			= 0
Const TAB_ALIGN_LEFT:Int		= 1
Const TAB_ALIGN_RIGHT:Int		= 2
Const TAB_ALIGN_BOTTOM:Int		= 3

Const TAB_MOUSEOVERSTYLE_RESIZE:Int			= 1
Const TAB_MOUSEOVERSTYLE_BRIGHTENING:Int	= 2
Const TAB_MOUSEOVERSTYLE_WOBBLE:Int			= 3
Global maniac_lastTime:Int
Global maniac_timeScale:Float

#rem monkeydoc
	This Function Initializes the maniac-Framework.~n
	_DEBUG << can be True or False ;
#end
Function maniacInit:Void(_DEBUG:Bool = MANIAC_DEBUG)
	MANIAC_DEBUG = _DEBUG
	DW = DeviceWidth()
	DH = DeviceHeight()
	ManiacImg = New Image[30]		'Initialize an Array of 30 Images
	ManiacSnd = New Sound[5]		' -"- 5 Sounds

	If MANIAC_LOADASYNC = False
		MANIAC_FONT = New ManiacFont(22,27,["lib/font2.png"],[[32,5,27,0,0,0,0,0,0,19],[33,5,27,0,393,46,7,18,-1,4],[34,9,27,0,122,99,10,10,-1,3],[35,15,27,0,51,66,17,17,-1,5],[36,16,27,0,478,0,18,22,-1,2],[37,20,27,0,332,25,21,21,-1,2],[38,16,27,0,34,66,17,17,-1,5],[39,5,27,0,116,99,6,10,-1,3],[40,9,27,0,89,0,11,24,-1,2],[41,9,27,0,78,0,11,24,-1,2],[42,14,27,0,378,46,15,18,-1,4],[43,12,27,0,386,83,14,14,-1,6],[44,6,27,0,109,99,7,10,-1,14],[45,10,27,0,174,99,12,7,-1,10],[46,5,27,0,219,99,6,6,-1,15],[47,12,27,0,366,25,13,21,-1,2],[48,18,27,0,24,83,19,16,-1,5],[49,12,27,0,60,83,14,16,-1,5],[50,14,27,0,171,83,15,15,-1,6],[51,16,27,0,154,83,17,15,-1,6],[52,15,27,0,154,66,17,17,-1,5],[53,15,27,0,138,66,16,17,-1,5],[54,16,27,0,121,66,17,17,-1,5],[55,13,27,0,106,66,15,17,-1,5],[56,15,27,0,89,66,17,17,-1,5],[57,15,27,0,43,83,17,16,-1,6],[58,5,27,0,424,83,6,14,-1,7],[59,6,27,0,68,66,7,17,-1,7],[60,10,27,0,412,83,12,14,-1,7],[61,14,27,0,79,99,16,11,-1,7],[62,10,27,0,400,83,12,14,-1,7],[63,13,27,0,75,66,14,17,-1,5],[64,21,27,0,14,46,22,20,-1,6],[65,17,27,0,461,66,18,17,-1,5],[66,14,27,0,446,66,15,17,-1,5],[67,15,27,0,430,66,16,17,-1,5],[68,15,27,0,414,66,16,17,-1,5],[69,14,27,0,399,66,15,17,-1,5],[70,13,27,0,385,66,14,17,-1,5],[71,15,27,0,369,66,16,17,-1,5],[72,14,27,0,353,66,16,17,-1,5],[73,11,27,0,142,83,12,16,-1,6],[74,15,27,0,126,83,16,16,-1,5],[75,14,27,0,337,66,16,17,-1,5],[76,14,27,0,322,66,15,17,-1,5],[77,17,27,0,304,66,18,17,-1,5],[78,15,27,0,287,66,17,17,-1,5],[79,18,27,0,107,83,19,16,-1,5],[80,15,27,0,416,46,16,18,-1,4],[81,18,27,0,268,66,19,17,-1,5],[82,15,27,0,400,46,16,18,-1,4],[83,16,27,0,250,66,18,17,-1,5],[84,15,27,0,319,83,16,15,-1,6],[85,15,27,0,90,83,17,16,-1,5],[86,16,27,0,233,66,17,17,-1,5],[87,16,27,0,215,66,18,17,-1,5],[88,15,27,0,199,66,16,17,-1,5],[89,14,27,0,184,66,15,17,-1,5],[90,15,27,0,74,83,16,16,-1,5],[91,9,27,0,67,0,11,24,-1,2],[92,12,27,0,353,25,13,21,-1,2],[93,9,27,0,56,0,11,24,-1,2],[94,12,27,0,26,99,13,12,-1,2],[95,15,27,0,203,99,16,6,-1,20],[96,7,27,0,141,99,8,9,-1,3],[97,14,27,0,304,83,15,15,-1,7],[98,12,27,0,287,46,13,19,-1,3],[99,12,27,0,472,83,13,14,-1,7],[100,12,27,0,70,46,14,20,-1,2],[101,13,27,0,290,83,14,15,-1,7],[102,12,27,0,274,46,13,19,-1,3],[103,13,27,0,260,46,14,19,-1,7],[104,13,27,0,246,46,14,19,-1,3],[105,5,27,0,239,46,7,19,-1,3],[106,5,27,0,315,0,7,23,-1,3],[107,12,27,0,56,46,14,20,-1,2],[108,5,27,0,50,46,6,20,-1,2],[109,16,27,0,272,83,18,15,-1,7],[110,13,27,0,258,83,14,15,-1,7],[111,12,27,0,458,83,14,14,-1,7],[112,12,27,0,36,46,14,20,-1,7],[113,13,27,0,225,46,14,19,-1,7],[114,10,27,0,246,83,12,15,-1,7],[115,13,27,0,232,83,14,15,-1,7],[116,12,27,0,171,66,13,17,-1,4],[117,12,27,0,218,83,14,15,-1,7],[118,13,27,0,443,83,15,14,-1,7],[119,16,27,0,200,83,18,15,-1,7],[120,13,27,0,186,83,14,15,-1,7],[121,13,27,0,211,46,14,19,-1,7],[122,12,27,0,430,83,13,14,-1,8],[123,12,27,0,28,0,14,25,-1,2],[124,5,27,0,309,0,6,23,-1,3],[125,12,27,0,14,0,14,25,-1,2],[126,15,27,0,157,99,17,8,-1,10],[127,13,27,0,0,46,14,20,-1,3],[161,5,27,0,371,46,7,18,-1,9],[162,12,27,0,465,0,13,22,-1,3],[163,14,27,0,18,66,16,17,-1,5],[164,16,27,0,0,66,18,17,-1,4],[165,14,27,0,481,46,15,17,-1,5],[166,5,27,0,303,0,6,23,-1,3],[167,13,27,0,317,25,15,21,-1,5],[168,9,27,0,192,99,11,6,-1,5],[169,21,27,0,189,46,22,19,-1,5],[170,13,27,0,65,99,14,11,-1,5],[171,17,27,0,368,83,18,14,-1,7],[172,12,27,0,95,99,14,10,-1,10],[174,21,27,0,167,46,22,19,-1,5],[176,12,27,0,52,99,13,11,-1,4],[177,13,27,0,357,46,14,18,-1,4],[178,12,27,0,0,99,13,13,-1,4],[179,12,27,0,13,99,13,12,-1,5],[180,8,27,0,132,99,9,9,-1,3],[181,14,27,0,152,46,15,19,-1,7],[182,18,27,0,297,25,20,21,-1,4],[183,5,27,0,186,99,6,6,-1,10],[184,7,27,0,149,99,8,8,-1,17],[185,7,27,0,498,83,8,13,-1,5],[186,11,27,0,39,99,13,11,-1,5],[187,17,27,0,350,83,18,14,-1,7],[188,17,27,0,278,25,19,21,-1,2],[189,18,27,0,259,25,19,21,-1,2],[190,18,27,0,239,25,20,21,-1,2],[191,13,27,0,467,46,14,17,-1,10],[192,17,27,0,285,0,18,23,-1,-1],[193,17,27,0,267,0,18,23,-1,-1],[194,17,27,0,249,0,18,23,-1,-1],[195,17,27,0,447,0,18,22,-1,0],[196,17,27,0,221,25,18,21,-1,1],[197,17,27,0,231,0,18,23,-1,-1],[198,22,27,0,0,83,24,16,-1,6],[199,15,27,0,486,25,16,20,-1,5],[200,14,27,0,216,0,15,23,-1,-1],[201,14,27,0,201,0,15,23,-1,-1],[202,14,27,0,186,0,15,23,-1,-1],[203,14,27,0,206,25,15,21,-1,1],[204,11,27,0,174,0,12,23,-1,-1],[205,11,27,0,162,0,12,23,-1,-1],[206,12,27,0,148,0,14,23,-1,-1],[207,11,27,0,194,25,12,21,-1,1],[208,17,27,0,448,46,19,17,-1,5],[209,15,27,0,430,0,17,22,-1,0],[210,18,27,0,411,0,19,22,-1,-1],[211,18,27,0,392,0,19,22,-1,-1],[212,18,27,0,373,0,19,22,-1,-1],[213,18,27,0,175,25,19,21,-1,0],[214,18,27,0,467,25,19,20,-1,1],[215,12,27,0,485,83,13,13,-1,7],[216,18,27,0,129,0,19,23,-1,2],[217,15,27,0,356,0,17,22,-1,-1],[218,15,27,0,339,0,17,22,-1,-1],[219,15,27,0,322,0,17,22,-1,-1],[220,15,27,0,450,25,17,20,-1,1],[221,14,27,0,114,0,15,23,-1,-1],[222,14,27,0,432,46,16,17,-1,5],[223,14,27,0,342,46,15,18,-1,4],[224,14,27,0,160,25,15,21,-1,1],[225,14,27,0,145,25,15,21,-1,1],[226,14,27,0,130,25,15,21,-1,1],[227,14,27,0,435,25,15,20,-1,2],[228,14,27,0,137,46,15,19,-1,3],[229,14,27,0,115,25,15,21,-1,1],[230,21,27,0,479,66,23,16,-1,6],[231,12,27,0,329,46,13,18,-1,7],[232,13,27,0,101,25,14,21,-1,1],[233,13,27,0,87,25,14,21,-1,1],[234,13,27,0,72,25,15,21,-1,1],[235,13,27,0,123,46,14,19,-1,3],[236,7,27,0,64,25,8,21,-1,1],[237,8,27,0,55,25,9,21,-1,1],[238,11,27,0,42,25,13,21,-1,1],[239,9,27,0,112,46,11,19,-1,3],[240,14,27,0,314,46,15,18,-1,3],[241,13,27,0,421,25,14,20,-1,2],[242,12,27,0,407,25,14,20,-1,1],[243,12,27,0,393,25,14,20,-1,1],[244,12,27,0,379,25,14,20,-1,1],[245,12,27,0,98,46,14,19,-1,2],[246,12,27,0,300,46,14,18,-1,3],[247,14,27,0,335,83,15,14,-1,5],[248,12,27,0,28,25,14,21,-1,4],[249,12,27,0,14,25,14,21,-1,1],[250,12,27,0,0,25,14,21,-1,1],[251,12,27,0,496,0,14,21,-1,1],[252,12,27,0,84,46,14,19,-1,3],[253,13,27,0,0,0,14,25,-1,1],[254,12,27,0,42,0,14,24,-1,3],[255,13,27,0,100,0,14,23,-1,3]])
		ManiacImg[IMG_LOGO] 		= LoadImage(PATH_IMG_LOGO)
		ManiacImg[IMG_BACKGROUND] 	= LoadImage(PATH_IMG_BACKGROUND)
		ManiacImg[IMG_STYLE_MODERN_BACKGROUND] 		= LoadImage(PATH_IMG_STYLE_MODERN_BACKGROUND,1,Image.MidHandle)
		ManiacImg[IMG_STYLE_MODERN_FRAME] 			= LoadImage(PATH_IMG_STYLE_MODERN_FRAME,1,Image.MidHandle)
		ManiacImg[IMG_STYLE_ROUND_BACKGROUND] 		= LoadImage(PATH_IMG_STYLE_ROUND_BACKGROUND,1,Image.MidHandle)
		ManiacImg[IMG_STYLE_ROUND_FRAME] 			= LoadImage(PATH_IMG_STYLE_ROUND_FRAME,1,Image.MidHandle)
		ManiacImg[IMG_STYLE_CIRCLE_BACKGROUND] 		= LoadImage(PATH_IMG_STYLE_CIRCLE_BACKGROUND,1,Image.MidHandle)
		ManiacImg[IMG_STYLE_CIRCLE_FRAME] 			= LoadImage(PATH_IMG_STYLE_CIRCLE_FRAME,1,Image.MidHandle)
		ManiacImg[IMG_SLIDER_FLATLINE] 				= LoadImage(PATH_IMG_STYLE_FLATLINE,1,Image.MidHandle)
		ManiacImg[IMG_SLIDER_PICKER] 				= LoadImage(PATH_IMG_STYLE_PICKER,1,Image.MidHandle)
		ManiacImg[IMG_ICON_CHECKEDARROW]			= LoadImage(PATH_IMG_CHECKEDARROW,1,Image.MidHandle)
		ManiacImg[IMG_ICON_ARROWDOWN]				= LoadImage(PATH_IMG_ARROWDOWN,1,Image.MidHandle)
		ManiacImg[IMG_ICON_ARROWUP]					= LoadImage(PATH_IMG_ARROWUP,1,Image.MidHandle)

		'ManiacImg[IMG_LOGO] 		=
		'MANIAC_IMG_BACKGROUND = )
		'MANIAC_IMG_STAR = LoadImage("lib/star.png")
		'MANIAC_IMG_LOGO = LoadImage("lib/logo.png")
		#rem
		MANIAC_IMG_FRAME_RAW = LoadImage("lib/Button/Frame_Round3.png",1,Image.MidHandle)
		MANIAC_IMG_FRAME_RECT2	= LoadImage("lib/Button/Frame_Rect2.png",1,Image.MidHandle)
		MANIAC_IMG_FRAME_ROUND1	= LoadImage("lib/Button/Frame_Round1.png",1,Image.MidHandle)
		MANIAC_IMG_FRAME_ROUND2	= LoadImage("lib/Button/Frame_Round2.png",1,Image.MidHandle)
		MANIAC_IMG_FRAME_ROUND3 = LoadImage("lib/Button/Frame_Round3.png",1,Image.MidHandle)
		MANIAC_IMG_BG_SMOOTHRECT = LoadImage("lib/Button/BG_Round3.png",1,Image.MidHandle)		'## DEPRECATED !!! Will be removed within next patch
		MANIAC_IMG_BG_ROUND1 = LoadImage("lib/Button/BG_Round1.png",1,Image.MidHandle)
		MANIAC_IMG_BG_ROUND2 = LoadImage("lib/Button/BG_Round2.png",1,Image.MidHandle)
		MANIAC_IMG_BG_ROUND3 = LoadImage("lib/Button/BG_Round3.png",1,Image.MidHandle)

		MANIAC_IMG_FRAME_BLUR = LoadImage("lib/Frame_blur.png",1,Image.MidHandle)
		'MANIAC_IMG_EDITICON = LoadImage("lib/ico_edit.png")
		MANIAC_IMG_SLIDERLINE = LoadImage("lib/Slider_Line.png")
		MANIAC_IMG_SLIDERPICKER = LoadImage("lib/Slider_Picker.png",1,Image.MidHandle)
		MANIAC_IMG_CHECK = LoadImage("lib/ico_check.png")
		MANIAC_IMG_DROPDOWN = LoadImage("lib/ico_dropdown.png")
		MANIAC_IMG_ARROWDOWN = LoadImage("lib/ico_arrowdown.png")

		'MANIAC_IMG_ICO_SOUND = LoadImage("lib/Icons/Icon_Std_Sound.png")
		'MANIAC_IMG_ICO_BACK = LoadImage("lib/Icons/Icon_Std_Back.png")
		'MANIAC_SND_SLIDE = LoadSound("lib/SFX/slide1.wav")
		'MANIAC_SND_SLIDE2 = LoadSound("lib/SFX/slide2.wav")
		'MANIAC_SND_SLIDE3 = LoadSound("lib/SFX/slide3.wav")
		#end
	Else
		#rem
			TO DO:
			Try to find a way to include some Async Loading stuff with the lowest impact of how to use this Framework.
			## RECOMMEND : SET TO FALSE ##
		#end
	Endif

	If MANIAC_DEBUG = True
'		MANIAC_FPSGRAPH = New Maniac_Debug(DW*0.1,DH*0.7,DW*0.8,DH*0.29)
	Endif

	initData_Quotes()
	mCurrInitTime = Millisecs()
End Function

#rem monkeydoc
	This Function Draws additional Stuff, Like Intro ; Explosion Effects etc. .~n
	_DEBUG << can be True or False ;
#end
Function maniacDraw()
	If MANIAC_DEBUG = True
		'MANIAC_FPSGRAPH.Draw()
	Else

	Endif

	If mInit = True
		DrawImage ManiacImg[IMG_LOGO],DW*0.1,DH*0.1,0,DW*0.8/ManiacImg[IMG_LOGO].Width(),DH*0.5/ManiacImg[IMG_LOGO].Height()
		Local scale:Float = 0.8
		Drw_ManiacText(" - " + quotes[16][0]+" -  ("+ quotes[16][1]+")",DW*0.05,DH*0.62,DW*0.9/scale,DH*0.9,ALIGNMENT_LEFT,ALIGNMENT_TOP,0.8)

		Drw_ManiacText("Powered by",DW*0.2,DH*0.83,DW*0.6,DH*0.08,ALIGNMENT_LEFT,ALIGNMENT_MIDDLEY,2.3)
		Drw_ManiacText("The Maniac Framework",DW*0.2,DH*0.91,DW*0.6,DH*0.08,ALIGNMENT_MIDDLE,ALIGNMENT_MIDDLEY,1.7)

		Drw_Lightning(DW*0.1,DH*0.1,0,0,1)
		Drw_Lightning(DW*0.9,DH*0.1,DW,0,1)
		Drw_Lightning(DW*0.1,DH*0.6,0,DH,1)
		Drw_Lightning(DW*0.9,DH*0.6,DW,DH,1)

		#rem
		Drw_Lightning(DW*0.05,0,DW*0.05,DH,1)
		Drw_Lightning(DW*0.95,0,DW*0.95,DH,1)
		#end
	Endif

	If Millisecs() -  mCurrInitTime > mInitTime And bClickedNext = False
		Drw_ManiacText("[Click on Display]",DW*0.2,DH*0.02,DW*0.6,DH*0.08,ALIGNMENT_LEFT,ALIGNMENT_MIDDLEY,2.3)
	Endif
End Function

#rem monkeydoc
	This Function Updates additional Stuff, Like Intro ; Explosion Effects etc. .~n
	_DEBUG << can be True or False ;
#end
Function maniacUpdate:Bool()

	If MANIAC_DEBUG = True
		Maniac_Debug.addCall()
	Endif
	If Millisecs() -  mCurrInitTime > mInitTime And bClickedNext = True
		mInit = False
	Endif
	'MX = MouseX()
	'MY = MouseY()

	Maniac_CheckMouseState()

	ll_UpdateSpeeds()
	If mInit = True
		If TouchHit()
			bClickedNext = True
		Endif
		Return True

	Else
		Return False
	Endif
End Function

Const MANIAC_INITTIME_SHORT:Int = 750
Const MANIAC_INITTIME_EXTENDSHORT:Int = 1000
Const MANIAC_INITTIME_MEDIUM:Int		= 1500
Const MANIAC_INITTIME_EXTENDMEDIUM:Int	= 1750
Const MANIAC_INITTIME_LONG:Int 			= 2000
Const MANIAC_INITTIME_EXTENDLONG:Int	= 2250
Const MANIAC_INITTIME_VERYLONG:Int 		= 2500
Const MANIAC_INITTIME_EXTREME:Int		= 5000

#rem monkeydoc
	This function sets the Init / Intro Time.
	Eather you can use the predefined Length:
		MANIAC_INITTIME_SHORT,MANIAC_INITTIME_EXTENDSHORT,MANIAC_INITTIME_MEDIUM,MANIAC_INITTIME_EXTENDMEDIUM,MANIAC_INITTIME_LONG,MANIAC_INITTIME_EXTENDLONG,MANIAC_INITTIME_VERYLONG,MANIAC_INITTIME_EXTREME
	Params:
#end
Function setInitTime:Void(_TimeInMilliSecs:Int)
	mInitTime = _TimeInMilliSecs
End Function

#rem monkeydoc
	This Function Checks, wether the Framework is still Initing.

	returns true, if maniac is loading Data
	returns false, if the Framework is ready to use
#end
Function maniacIsIniting:Bool()
	If mInit = True
		Return True
	Else
		Return False
	Endif
End Function

#rem monkeydoc
	This Functions Loads the Quotes from Datafiles to the ManiacSystem.
#end
private
Function initData_Quotes()
	'arrDayOf = Array2Dstr(12,31)
	quotes = Array2Dstr(100,2)
	Local file:ManiacTextFile

	file = New ManiacTextFile("lib/Quotes_german.dat")

	If file <> Null Then
			'Print "FOUND FILE"
			Local i:Int = 0
		While file.Eof() = False

			file.ReadLine()
				'Print file.GetLine()
			Local quote:String =  file.GetDataName()
			Local author:String = file.GetDataValue()
			'Print "("+i+") Zitat: " + quote + " by " + author

			quotes[i][0] = quote
			quotes[i][1] = author
			i +=1
			#rem
			If ll_ContainDate(date) = True
				'Print "Found Date! " + date + " " + value
				Local month:Int = ll_convertDateToMonth(date)
				Local day:Int = ll_convertDateToDay(date)

				arrDayOf[month][day] = value
			Endif
			#end
		End While
	Endif
End Function

#Rem monkeydoc Module maniac
	Copyright (C) 2015  Stephan Duckerschein~n
	Version: 0.9.1 Alpha~n
	This Framework provides many additional Graphical Effects and primite Drawings, like unfilled rectangular , ellipsis etc. Diverse GUI Elements.~n
	It has it's own TileMap Engine included and even a Debug Tracking-System. ~n
	~n
	Installation:~n
	to use this Module, you have to Copy the "lib/" Folder data to Your App's Data.~n
	~n
	In the following is an Example, how to Include the maniac Framework to your Monkey Project.~n
Example:
<pre>
'This Example Shows how to integrate the Maniac-Framework to your App

'1. First You have to Import the Libs
import mojo
import maniac

'2. Main Function and App extending Class
Function Main:Int()
	New Example
	Return 0
End

Class Example extends App
	Method OnCreate:Int()
		SetUpdateRate( 60 )
		maniacInit()			' THIS INITS THE MANIAC FRAMEWORK! THIS NEED TO BE DONE BEFORE USING IT!!!!!
	end Method

	Method OnUpdate:int()
		maniacUpdate()			'THIS UPDATES ALL NEEDED DATA FOR THE MANIAC-GLOBALS
	end method

	Method OnRender:int()
		Cls

		maniacDraw()
	end Method
End class
</pre>

~n
Featurelist:
	GUI:
	- Button  (ver: 0.9)

#End

#rem
 <The Duke Game Framework. It provides useful little helperfunctions and class to develope 2D Games with Monkey X>
    Copyright (C) 2014-2015  Stephan Duckerschein

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 #end
Import mojo
Import maniacMisc
Import maniacGraphics
Import maniacFont				'249
Import maniacDebug				'334
Import maniacButton				'746
Import maniacTween
Import maniacTabLine

Global DW:Float,DH:Float',MX:Float,MY:Float
Global gl_clicked:Bool
Global gl_mousereleased:Bool

Global MANIAC_DEBUG:Bool = False
Global MANIAC_LOADASYNC:Bool = False 		'## RECOMMEND: SET ON FALSE, as there is no Async Loader included @ the moment !!!

Global GLOBAL_SOUNDON:Bool = False 			'if set to false, No Sound at all

Global GLOBAL_LANGUAGE:String
'### StringPath to Std-Lib Images ###
Global IMG_LOGO:Int 					= 0 , PATH_IMG_LOGO:String 						= "lib/logo.png"
Global IMG_BACKGROUND:Int 				= 1 , PATH_IMG_BACKGROUND:String 				= "lib/Hintergrund.png"
Global IMG_STYLE_MODERN_BACKGROUND:Int 	= 2 , PATH_IMG_STYLE_MODERN_BACKGROUND:String 	= "lib/Button/ModernBackground.png"
Global IMG_STYLE_MODERN_FRAME:Int     	= 3	, PATH_IMG_STYLE_MODERN_FRAME:String 		= "lib/Button/ModernFrame.png"
Global IMG_STYLE_ROUND_BACKGROUND:Int 	= 4 , PATH_IMG_STYLE_ROUND_BACKGROUND:String 	= "lib/Button/RoundedBackground.png"
Global IMG_STYLE_ROUND_FRAME:Int		= 5 , PATH_IMG_STYLE_ROUND_FRAME:String			= "lib/Button/RoundedFrame.png"
Global IMG_STYLE_CIRCLE_BACKGROUND:Int 	= 6 , PATH_IMG_STYLE_CIRCLE_BACKGROUND:String 	= "lib/Button/CircleBackground.png"
Global IMG_STYLE_CIRCLE_FRAME:Int		= 7 , PATH_IMG_STYLE_CIRCLE_FRAME:String		= "lib/Button/CircleFrame.png"

'### Std-Lib Image/Sound Array ###
Global ManiacImg:Image[]
Global ManiacSnd:Sound[]
Global MANIAC_FONT:ManiacFont

Global mInit:Bool = True
Global mInitTime:Int = 4000
Global mCurrInitTime:Int

Const ALIGNMENT_LEFT:Int 		= 1
Const ALIGNMENT_MIDDLE:Int 		= 2
Const ALIGNMENT_RIGHT:Int 		= 3
Const ALIGNMENT_TOP:Int 		= 4
Const ALIGNMENT_MIDDLEY:int 	= 5
Const ALIGNMENT_BOTTOM:Int 		= 6

Const ANIM_DROP:Int 	= 1
Const ANIM_FADE:Int		= 2
Const ANIM_ROTATE:Int 	= 3
Const ANIM_ROLL:Int		= 4
Const ANIM_SLIDE:Int 	= 5
Const ANIM_CIRCLE:Int	= 6
Const ANIM_POPOUT:Int 	= 7

Const BUTTON_STYLE_STD:Int 		= 0
Const BUTTON_STYLE_STDGLOW:Int 	= 1
Const BUTTON_STYLE_MODERN:Int 	= 2
Const BUTTON_STYLE_ROUND:Int 	= 3
Const BUTTON_STYLE_CIRCLE:Int	= 4

Global maniac_lastTime:Int
Global maniac_timeScale:Float

Function maniacInit:Void(_DEBUG:Bool = MANIAC_DEBUG)
	MANIAC_DEBUG = _DEBUG
	DW = DeviceWidth()
	DH = DeviceHeight()
	ManiacImg = New Image[30]
	ManiacSnd = New Sound[5]

	If MANIAC_LOADASYNC = False
		MANIAC_FONT = New ManiacFont(22,27,["lib/font2.png"],[[32,5,27,0,0,0,0,0,0,19],[33,5,27,0,393,46,7,18,-1,4],[34,9,27,0,122,99,10,10,-1,3],[35,15,27,0,51,66,17,17,-1,5],[36,16,27,0,478,0,18,22,-1,2],[37,20,27,0,332,25,21,21,-1,2],[38,16,27,0,34,66,17,17,-1,5],[39,5,27,0,116,99,6,10,-1,3],[40,9,27,0,89,0,11,24,-1,2],[41,9,27,0,78,0,11,24,-1,2],[42,14,27,0,378,46,15,18,-1,4],[43,12,27,0,386,83,14,14,-1,6],[44,6,27,0,109,99,7,10,-1,14],[45,10,27,0,174,99,12,7,-1,10],[46,5,27,0,219,99,6,6,-1,15],[47,12,27,0,366,25,13,21,-1,2],[48,18,27,0,24,83,19,16,-1,5],[49,12,27,0,60,83,14,16,-1,5],[50,14,27,0,171,83,15,15,-1,6],[51,16,27,0,154,83,17,15,-1,6],[52,15,27,0,154,66,17,17,-1,5],[53,15,27,0,138,66,16,17,-1,5],[54,16,27,0,121,66,17,17,-1,5],[55,13,27,0,106,66,15,17,-1,5],[56,15,27,0,89,66,17,17,-1,5],[57,15,27,0,43,83,17,16,-1,6],[58,5,27,0,424,83,6,14,-1,7],[59,6,27,0,68,66,7,17,-1,7],[60,10,27,0,412,83,12,14,-1,7],[61,14,27,0,79,99,16,11,-1,7],[62,10,27,0,400,83,12,14,-1,7],[63,13,27,0,75,66,14,17,-1,5],[64,21,27,0,14,46,22,20,-1,6],[65,17,27,0,461,66,18,17,-1,5],[66,14,27,0,446,66,15,17,-1,5],[67,15,27,0,430,66,16,17,-1,5],[68,15,27,0,414,66,16,17,-1,5],[69,14,27,0,399,66,15,17,-1,5],[70,13,27,0,385,66,14,17,-1,5],[71,15,27,0,369,66,16,17,-1,5],[72,14,27,0,353,66,16,17,-1,5],[73,11,27,0,142,83,12,16,-1,6],[74,15,27,0,126,83,16,16,-1,5],[75,14,27,0,337,66,16,17,-1,5],[76,14,27,0,322,66,15,17,-1,5],[77,17,27,0,304,66,18,17,-1,5],[78,15,27,0,287,66,17,17,-1,5],[79,18,27,0,107,83,19,16,-1,5],[80,15,27,0,416,46,16,18,-1,4],[81,18,27,0,268,66,19,17,-1,5],[82,15,27,0,400,46,16,18,-1,4],[83,16,27,0,250,66,18,17,-1,5],[84,15,27,0,319,83,16,15,-1,6],[85,15,27,0,90,83,17,16,-1,5],[86,16,27,0,233,66,17,17,-1,5],[87,16,27,0,215,66,18,17,-1,5],[88,15,27,0,199,66,16,17,-1,5],[89,14,27,0,184,66,15,17,-1,5],[90,15,27,0,74,83,16,16,-1,5],[91,9,27,0,67,0,11,24,-1,2],[92,12,27,0,353,25,13,21,-1,2],[93,9,27,0,56,0,11,24,-1,2],[94,12,27,0,26,99,13,12,-1,2],[95,15,27,0,203,99,16,6,-1,20],[96,7,27,0,141,99,8,9,-1,3],[97,14,27,0,304,83,15,15,-1,7],[98,12,27,0,287,46,13,19,-1,3],[99,12,27,0,472,83,13,14,-1,7],[100,12,27,0,70,46,14,20,-1,2],[101,13,27,0,290,83,14,15,-1,7],[102,12,27,0,274,46,13,19,-1,3],[103,13,27,0,260,46,14,19,-1,7],[104,13,27,0,246,46,14,19,-1,3],[105,5,27,0,239,46,7,19,-1,3],[106,5,27,0,315,0,7,23,-1,3],[107,12,27,0,56,46,14,20,-1,2],[108,5,27,0,50,46,6,20,-1,2],[109,16,27,0,272,83,18,15,-1,7],[110,13,27,0,258,83,14,15,-1,7],[111,12,27,0,458,83,14,14,-1,7],[112,12,27,0,36,46,14,20,-1,7],[113,13,27,0,225,46,14,19,-1,7],[114,10,27,0,246,83,12,15,-1,7],[115,13,27,0,232,83,14,15,-1,7],[116,12,27,0,171,66,13,17,-1,4],[117,12,27,0,218,83,14,15,-1,7],[118,13,27,0,443,83,15,14,-1,7],[119,16,27,0,200,83,18,15,-1,7],[120,13,27,0,186,83,14,15,-1,7],[121,13,27,0,211,46,14,19,-1,7],[122,12,27,0,430,83,13,14,-1,8],[123,12,27,0,28,0,14,25,-1,2],[124,5,27,0,309,0,6,23,-1,3],[125,12,27,0,14,0,14,25,-1,2],[126,15,27,0,157,99,17,8,-1,10],[127,13,27,0,0,46,14,20,-1,3],[161,5,27,0,371,46,7,18,-1,9],[162,12,27,0,465,0,13,22,-1,3],[163,14,27,0,18,66,16,17,-1,5],[164,16,27,0,0,66,18,17,-1,4],[165,14,27,0,481,46,15,17,-1,5],[166,5,27,0,303,0,6,23,-1,3],[167,13,27,0,317,25,15,21,-1,5],[168,9,27,0,192,99,11,6,-1,5],[169,21,27,0,189,46,22,19,-1,5],[170,13,27,0,65,99,14,11,-1,5],[171,17,27,0,368,83,18,14,-1,7],[172,12,27,0,95,99,14,10,-1,10],[174,21,27,0,167,46,22,19,-1,5],[176,12,27,0,52,99,13,11,-1,4],[177,13,27,0,357,46,14,18,-1,4],[178,12,27,0,0,99,13,13,-1,4],[179,12,27,0,13,99,13,12,-1,5],[180,8,27,0,132,99,9,9,-1,3],[181,14,27,0,152,46,15,19,-1,7],[182,18,27,0,297,25,20,21,-1,4],[183,5,27,0,186,99,6,6,-1,10],[184,7,27,0,149,99,8,8,-1,17],[185,7,27,0,498,83,8,13,-1,5],[186,11,27,0,39,99,13,11,-1,5],[187,17,27,0,350,83,18,14,-1,7],[188,17,27,0,278,25,19,21,-1,2],[189,18,27,0,259,25,19,21,-1,2],[190,18,27,0,239,25,20,21,-1,2],[191,13,27,0,467,46,14,17,-1,10],[192,17,27,0,285,0,18,23,-1,-1],[193,17,27,0,267,0,18,23,-1,-1],[194,17,27,0,249,0,18,23,-1,-1],[195,17,27,0,447,0,18,22,-1,0],[196,17,27,0,221,25,18,21,-1,1],[197,17,27,0,231,0,18,23,-1,-1],[198,22,27,0,0,83,24,16,-1,6],[199,15,27,0,486,25,16,20,-1,5],[200,14,27,0,216,0,15,23,-1,-1],[201,14,27,0,201,0,15,23,-1,-1],[202,14,27,0,186,0,15,23,-1,-1],[203,14,27,0,206,25,15,21,-1,1],[204,11,27,0,174,0,12,23,-1,-1],[205,11,27,0,162,0,12,23,-1,-1],[206,12,27,0,148,0,14,23,-1,-1],[207,11,27,0,194,25,12,21,-1,1],[208,17,27,0,448,46,19,17,-1,5],[209,15,27,0,430,0,17,22,-1,0],[210,18,27,0,411,0,19,22,-1,-1],[211,18,27,0,392,0,19,22,-1,-1],[212,18,27,0,373,0,19,22,-1,-1],[213,18,27,0,175,25,19,21,-1,0],[214,18,27,0,467,25,19,20,-1,1],[215,12,27,0,485,83,13,13,-1,7],[216,18,27,0,129,0,19,23,-1,2],[217,15,27,0,356,0,17,22,-1,-1],[218,15,27,0,339,0,17,22,-1,-1],[219,15,27,0,322,0,17,22,-1,-1],[220,15,27,0,450,25,17,20,-1,1],[221,14,27,0,114,0,15,23,-1,-1],[222,14,27,0,432,46,16,17,-1,5],[223,14,27,0,342,46,15,18,-1,4],[224,14,27,0,160,25,15,21,-1,1],[225,14,27,0,145,25,15,21,-1,1],[226,14,27,0,130,25,15,21,-1,1],[227,14,27,0,435,25,15,20,-1,2],[228,14,27,0,137,46,15,19,-1,3],[229,14,27,0,115,25,15,21,-1,1],[230,21,27,0,479,66,23,16,-1,6],[231,12,27,0,329,46,13,18,-1,7],[232,13,27,0,101,25,14,21,-1,1],[233,13,27,0,87,25,14,21,-1,1],[234,13,27,0,72,25,15,21,-1,1],[235,13,27,0,123,46,14,19,-1,3],[236,7,27,0,64,25,8,21,-1,1],[237,8,27,0,55,25,9,21,-1,1],[238,11,27,0,42,25,13,21,-1,1],[239,9,27,0,112,46,11,19,-1,3],[240,14,27,0,314,46,15,18,-1,3],[241,13,27,0,421,25,14,20,-1,2],[242,12,27,0,407,25,14,20,-1,1],[243,12,27,0,393,25,14,20,-1,1],[244,12,27,0,379,25,14,20,-1,1],[245,12,27,0,98,46,14,19,-1,2],[246,12,27,0,300,46,14,18,-1,3],[247,14,27,0,335,83,15,14,-1,5],[248,12,27,0,28,25,14,21,-1,4],[249,12,27,0,14,25,14,21,-1,1],[250,12,27,0,0,25,14,21,-1,1],[251,12,27,0,496,0,14,21,-1,1],[252,12,27,0,84,46,14,19,-1,3],[253,13,27,0,0,0,14,25,-1,1],[254,12,27,0,42,0,14,24,-1,3],[255,13,27,0,100,0,14,23,-1,3]])
		ManiacImg[IMG_LOGO] 		= LoadImage(PATH_IMG_LOGO)
		ManiacImg[IMG_BACKGROUND] 	= LoadImage(PATH_IMG_BACKGROUND)
		ManiacImg[IMG_STYLE_MODERN_BACKGROUND] 		= LoadImage(PATH_IMG_STYLE_MODERN_BACKGROUND,1,Image.MidHandle)
		ManiacImg[IMG_STYLE_MODERN_FRAME] 			= LoadImage(PATH_IMG_STYLE_MODERN_FRAME,1,Image.MidHandle)
		ManiacImg[IMG_STYLE_ROUND_BACKGROUND] 		= LoadImage(PATH_IMG_STYLE_ROUND_BACKGROUND,1,Image.MidHandle)
		ManiacImg[IMG_STYLE_ROUND_FRAME] 			= LoadImage(PATH_IMG_STYLE_ROUND_FRAME,1,Image.MidHandle)
		ManiacImg[IMG_STYLE_CIRCLE_BACKGROUND] 		= LoadImage(PATH_IMG_STYLE_CIRCLE_BACKGROUND,1,Image.MidHandle)
		ManiacImg[IMG_STYLE_CIRCLE_FRAME] 			= LoadImage(PATH_IMG_STYLE_CIRCLE_FRAME,1,Image.MidHandle)
		'ManiacImg[IMG_LOGO] 		=
		'MANIAC_IMG_BACKGROUND = )
		'MANIAC_IMG_STAR = LoadImage("lib/star.png")
		'MANIAC_IMG_LOGO = LoadImage("lib/logo.png")
		#rem
		MANIAC_IMG_FRAME_RAW = LoadImage("lib/Button/Frame_Round3.png",1,Image.MidHandle)
		MANIAC_IMG_FRAME_RECT2	= LoadImage("lib/Button/Frame_Rect2.png",1,Image.MidHandle)
		MANIAC_IMG_FRAME_ROUND1	= LoadImage("lib/Button/Frame_Round1.png",1,Image.MidHandle)
		MANIAC_IMG_FRAME_ROUND2	= LoadImage("lib/Button/Frame_Round2.png",1,Image.MidHandle)
		MANIAC_IMG_FRAME_ROUND3 = LoadImage("lib/Button/Frame_Round3.png",1,Image.MidHandle)
		MANIAC_IMG_BG_SMOOTHRECT = LoadImage("lib/Button/BG_Round3.png",1,Image.MidHandle)		'## DEPRECATED !!! Will be removed within next patch
		MANIAC_IMG_BG_ROUND1 = LoadImage("lib/Button/BG_Round1.png",1,Image.MidHandle)
		MANIAC_IMG_BG_ROUND2 = LoadImage("lib/Button/BG_Round2.png",1,Image.MidHandle)
		MANIAC_IMG_BG_ROUND3 = LoadImage("lib/Button/BG_Round3.png",1,Image.MidHandle)

		MANIAC_IMG_FRAME_BLUR = LoadImage("lib/Frame_blur.png",1,Image.MidHandle)
		'MANIAC_IMG_EDITICON = LoadImage("lib/ico_edit.png")
		MANIAC_IMG_SLIDERLINE = LoadImage("lib/Slider_Line.png")
		MANIAC_IMG_SLIDERPICKER = LoadImage("lib/Slider_Picker.png",1,Image.MidHandle)
		MANIAC_IMG_CHECK = LoadImage("lib/ico_check.png")
		MANIAC_IMG_DROPDOWN = LoadImage("lib/ico_dropdown.png")
		MANIAC_IMG_ARROWDOWN = LoadImage("lib/ico_arrowdown.png")

		'MANIAC_IMG_ICO_SOUND = LoadImage("lib/Icons/Icon_Std_Sound.png")
		'MANIAC_IMG_ICO_BACK = LoadImage("lib/Icons/Icon_Std_Back.png")
		'MANIAC_SND_SLIDE = LoadSound("lib/SFX/slide1.wav")
		'MANIAC_SND_SLIDE2 = LoadSound("lib/SFX/slide2.wav")
		'MANIAC_SND_SLIDE3 = LoadSound("lib/SFX/slide3.wav")
		#end
	Else
		#rem
			TO DO:
			Try to find a way to include some Async Loading stuff with the lowest impact of how to use this Framework.
			## RECOMMEND : SET TO FALSE ##
		#end
	Endif

	If MANIAC_DEBUG = True
'		MANIAC_FPSGRAPH = New Maniac_Debug(DW*0.1,DH*0.7,DW*0.8,DH*0.29)
	Endif

	mCurrInitTime = Millisecs()
End Function

Function maniacDraw()
	If MANIAC_DEBUG = True
		'MANIAC_FPSGRAPH.Draw()
	Else

	Endif

	If Millisecs() -  mCurrInitTime > mInitTime
		mInit = False
	Endif

	If mInit = True
		DrawImage ManiacImg[IMG_LOGO],DW*0.2,DH*0.2,0,DW*0.6/ManiacImg[IMG_LOGO].Width(),DH*0.5/ManiacImg[IMG_LOGO].Height()
	Endif
End Function

Function maniacUpdate:Bool()
	UpdateAsyncEvents()
	If MANIAC_DEBUG = True
		Maniac_Debug.addCall()
	Endif

	'MX = MouseX()
	'MY = MouseY()

	Maniac_CheckMouseState()

	ll_UpdateSpeeds()
	If mInit = True
		Return True
	Else
		Return False
	Endif
End Function