Fixed alias

Fixed alias

Strict

Import mojo
Import reflection

Import flxextern
Import flxbasic
Import flxgame
Import flxcamera
Import flxobject
Import flxsignals
Import flxsound
Import flxmusic
Import flxu

Import system.input.accel
Import system.input.joystick
Import system.input.keyboard
Import system.input.mouse
Import system.input.touch
Import system.tweens.flxtween
Import system.tweens.util.ease
Import system.tweens.misc.multivartween
Import system.resolutionpolicy.flxresolutionpolicy
Import system.resolutionpolicy.fill
Import system.flxresourcesmanager
Import system.flxquadtree
Import system.flxreplay
Import system.flximagedata

Import plugin.timermanager
Import plugin.debugpathdisplay

Alias AccelInput = accel.Accel
Alias MouseInput = mouse.Mouse
Alias TouchInput = touch.Touch
Alias JoystickInput = joystick.Joystick
Alias MojoDeviceWidth = mojo.app.DeviceWidth
Alias MojoDeviceHeight = mojo.app.DeviceHeight

Class FlxG

	Const LIBRARY_NAME:String = "Flixel for Monkey"

	Const LIBRARY_MAJOR_VERSION:Int = 1

	Const LIBRARY_MINOR_VERSION:Int = 0

	Const DATA_SUFFIX:String = "_flx"

	Const RED:Int = $FFFF0012

	Const GREEN:Int = $FF00F225

	Const BLUE:Int = $FF0090E9

	Const PINK:Int = $FFF01EFF

	Const WHITE:Int = $FFFFFFFF

	Const BLACK:Int = $FF000000

	Global Paused:Bool

#If FLX_DEBUG_ENABLED
	Global Debug:Bool = True
#Else
	Global Debug:Bool = False
#End

	Global Elapsed:Float

	Global TimeScale:Float

	Global DeviceWidth:Int

	Global DeviceHeight:Int

	Global Width:Int

	Global Height:Int

	Global WorldBounds:FlxRect

	Global WorldDivisions:Int

	Global VisualDebug:Bool

	Global Mobile:Bool

	Global GlobalSeed:Int

	Global Scores:Stack<Int>

	Global Score:Int

	Global Levels:Stack<Int>

	Global Level:Int

	Global Accel:AccelInput

	Global Keys:Keyboard

	Global Mouse:MouseInput

	Global Music:FlxMusic

	Global Sounds:FlxGroup

	Global Mute:Bool

	Global Cameras:Stack<FlxCamera>

	Global Camera:FlxCamera

	Global Plugins:Stack<FlxBasic>

	Global VolumeHandler:FlxVolumeChangeListener

	Global Updaterate:Int

	Global Tweener:FlxBasic

	Global Signals:FlxSignals

	Global _DeviceScaleFactorX:Float = 1

	Global _DeviceScaleFactorY:Float = 1

	Global _DeviceOffsetX:Int

	Global _DeviceOffsetY:Int

	Global _BgColor:FlxColor = FlxColor.ARGB(FlxG.BLACK)

	Global _Game:FlxGame

	Global _Volume:Float

	Global _BitmapCache:FlxResourcesManager<Image>

	Global _SoundCache:FlxResourcesManager<Sound>

	Global _LastDrawingColor:Int

	Global _LastDrawingAlpha:Float

	Global _LastDrawingBlend:Int

	Global _CurrentCamera:FlxCamera

Private
#If TARGET = "psm"
	Const _JOY_UNITS_COUNT:Int = 1
#Else
	Const _JOY_UNITS_COUNT:Int = 4
#End
	Const _TOUCH_COUNT:Int = 32

	Global _Joystick:JoystickInput[_JOY_UNITS_COUNT]

	Global _Touch:TouchInput[_TOUCH_COUNT]

	Global _CollideListener:FlxCollideProcessListener = New FlxCollideProcessListener()

	Global _ResolutionPolicy:FlxResolutionPolicy = New FillResolutionPolicy()

	Global _Point:FlxPoint = New FlxPoint()

Public
	Function GetLibraryName:String()
		Return FlxG.LIBRARY_NAME + " v" + FlxG.LIBRARY_MAJOR_VERSION + "." + FlxG.LIBRARY_MINOR_VERSION
	End Function

	Function Log:Void(data:String)
	#If FLX_DEBUG_ENABLED
		'note: TODO: to add log objects
		Print data
	#End
	End Function

	Function Random:Float()
		FlxG.GlobalSeed = (FlxG.GlobalSeed * 1664525 + 1013904223) | 0
		Return FlxU.Srand(FlxG.GlobalSeed)
	End Function

	Function Random:Float(range:Float)
		Return FlxG.Random() * range
	End Function

	Function Random:Float(low:Float, high:Float)
		Return FlxG.Random(high - low) + low
	End Function

	Function Random:Int(range:Int)
		Return Int(FlxG.Random() * (1 + range))
	End Function

	Function Random:Int(low:Int, high:Int)
		Return FlxG.Random(high - low) + low
	End Function

	#Rem
	Function GetRandom:Object(objects:Object[], startIndex:Int = 0, length:Int = 0)
		GetRandom is not currently supported in Monkey. Use FlxArray.GetSafeRandom method
	End Function
	#End

	Function LoadReplay:Void(data:String, state:FlxState = Null, cancelKeys:Int[] = [], timeout:Float = 0, callback:FlxReplayListener = Null)
		_Game._replay.Load(data)
		If (state = Null) Then
			FlxG.ResetGame()
		Else
			FlxG.SwitchState(state)
		End If

		_Game._replayCancelKeys = cancelKeys
		_Game._replayTimer = timeout * 1000
		_Game._replayCallback = callback
		_Game._replayRequested = True
	End Function

	Function ReloadReplay:Void(standardMode:Bool = True)
		If (standardMode) Then
			FlxG.ResetGame()
		Else
			FlxG.ResetState()
		End If

		If (_Game._replay.frameCount > 0) _Game._replayRequested = True
	End Function

	Function StopReplay:Void()
		_Game._replaying = False

	#If FLX_DEBUG_ENABLED
		If (_Game._debugger <> Null) Then
			'note: TODO:
		End If
	#End

		ResetInput()
	End Function

	Function RecordReplay:Void(standardMode:Bool = True)
		If (standardMode) Then
			FlxG.ResetGame()
		Else
			FlxG.ResetState()
		End If

		_Game._recordingRequested = True
	End Function

	Function StopRecording:String()
		_Game._recording = False

	#If FLX_DEBUG_ENABLED
		If (_Game._debugger <> Null) Then
			'note: TODO:
		End If
	#End

		Return _Game._replay.Save()
	End Function

	Function ResetState:Void()
		_Game._requestedState = FlxState(_Game._state.GetClassInfo().NewInstance())
	End Function

	Function ResetGame:Void()
		_Game._requestedReset = True
	End Function

	Function ResetInput:Void()
		For Local i:Int = 0 Until _JOY_UNITS_COUNT
			_Joystick[i].Reset()
		Next

		For Local i:Int = 0 Until _TOUCH_COUNT
			_Touch[i].Reset()
		Next

		Accel.Reset()
		Mouse.Reset()
		Keys.Reset()
	End Function

	Function PlayMusic:Void(music:String, volume:Float = 1.0)
		If (FlxG.Music = Null) Then
			FlxG.Music = New FlxMusic()

		ElseIf (FlxG.Music.active) Then
			FlxG.Music.Stop()
		End If

		FlxG.Music.Load(music, True)
		FlxG.Music.Volume = volume
		FlxG.Music.survive = True

		FlxG.Music.Play()
	End Function

	Function LoadSound:FlxSound(sound:String, volume:Float = 1.0, looped:Bool = False, autoDestroy:Bool = False, autoPlay:Bool = False, stopPrevious:Bool = True)
		Local s:FlxSound = FlxSound(Sounds.Recycle(FlxSound.__CLASS__))

		s.Load(sound, looped, autoDestroy, stopPrevious)
		s.Volume = volume
		If (autoPlay) s.Play()

		Return s
	End Function

	Function Play:FlxSound(sound:String, volume:Float = 1.0, looped:Bool = False, autoDestroy:Bool = True)
		Return FlxG.LoadSound(sound, volume, looped, autoDestroy, True, False)
	End Function

	Function Volume:Float()
		Return _Volume
	End Function

	Function Volume:Void(volume:Float)
		_Volume = volume

		If (_Volume < 0) Then
			_Volume = 0
		ElseIf (_Volume > 1) Then
			_Volume = 1
		End If

		If (VolumeHandler <> Null) Then
			If (FlxG.Mute) Then
				VolumeHandler.OnVolumeChange(0)
			Else
				VolumeHandler.OnVolumeChange(_Volume)
			End If
		End If

		If (Music <> Null And Music.active) Then
			Music._UpdateTransform()
		End If

		For Local basic:FlxBasic = EachIn Sounds
			FlxSound(basic)._UpdateTransform()
		Next
	End Function

	Function DestroySounds:Void(forceDestroy:Bool = False)
		If (Music <> Null And (forceDestroy Or Not Music.survive)) Then
			Music.Destroy()
			Music = Null
		End If

		Local sound:FlxSound

		For Local basic:FlxBasic = EachIn Sounds
			sound = FlxSound(basic)

			If (sound <> Null And (forceDestroy Or Not sound.survive)) Then
				sound.Destroy()
			End If
		Next
	End Function

	Function UpdateSounds:Void()
		If (Music <> Null And Music.active) Then
			Music.Update()
		End If

		If (Sounds <> Null And Sounds.active) Then
			Sounds.Update()
		End If
	End Function

	Function PauseSounds:Void()
		If (Music <> Null And Music.exists And Music.active) Then
			Music.Pause()
		End If

		Local sound:FlxSound

		For Local basic:FlxBasic = EachIn Sounds
			sound = FlxSound(basic)

			If (sound <> Null And sound.exists And sound.active) Then
				sound.Pause()
			End If
		Next
	End Function

	Function ResumeSounds:Void()
		If (Music <> Null And Music.exists) Then
			Music.Resume()
		End If

		Local sound:FlxSound

		For Local basic:FlxBasic = EachIn Sounds
			sound = FlxSound(basic)

			If (sound <> Null And sound.exists) Then
				sound.Resume()
			End If
		Next
	End Function

	Function CheckBitmapCache:Bool(key:String)
		Return _BitmapCache.CheckResource(key)
	End Function

	Function CreateBitmap:Image(width:Int, height:Int, color:Int, unigue:Bool, key:String = "")
		If (key.Length() = 0) Then
			key = width + "x" + height + ":" + color

			If (unigue And CheckBitmapCache(key)) Then
				Local inc:Int = 0
				Local ukey:String

				Repeat
					ukey = key + inc
					inc += 1
				Until (CheckBitmapCache(ukey))

				key = ukey
			End If
		End If

		Return _BitmapCache.GetResource(key, New CreateImageResource(key, width, height, color))
	End Function

	Function AddBitmap:Image(resource:FlxResource<Image>, unique:Bool = False, key:String = "")
		If (key.Length() = 0) Then
			key = resource.name

			If (unique And CheckBitmapCache(key)) Then
				Local inc:Int = 0
				Local ukey:String

				Repeat
					ukey = key + inc
					inc += 1
				Until(CheckBitmapCache(ukey))

				key = ukey
			End If
		End If

		Return _BitmapCache.GetResource(key, resource)
	End Function

	Function RemoveBitmap:Void(graphic:String)
		If (_BitmapCache <> Null) Then
			_BitmapCache.RemoveResource(graphic)
		End If
	End Function

	Function ClearBitmapCache:Void()
		If (_BitmapCache = Null) _BitmapCache = New FlxResourcesManager<Image>()
		_BitmapCache.Clear()
	End Function

	Function AddSound:Sound(resource:FlxResource<Sound>)
		Return _SoundCache.GetResource(resource.name, resource)
	End Function

	Function ClearSoundCache:Void()
		If (_SoundCache = Null) _SoundCache = New FlxResourcesManager<Sound>()
		_SoundCache.Clear()
	End Function

	Function State:FlxState()
		Return _Game._state
	End Function

	Function SwitchState:Void(state:FlxState)
		FlxG._Game._requestedState = state
	End Function

	Function SetSwitchStateListener:Void(listener:FlxSwitchStateListener)
		FlxG._Game.SetSwitchStateListener(listener)
	End Function

	Function AddCamera:FlxCamera(newCamera:FlxCamera)
		FlxG.Cameras.Push(newCamera)
		Return newCamera
	End Function

	Function RemoveCamera:Void(camera:FlxCamera, destroy:Bool = True)
		FlxG.Cameras.RemoveEach(camera)
		If (destroy) camera.Destroy()
	End Function

	Function ResetCameras:Void(newCamera:FlxCamera = Null)
		Local cam:FlxCamera
		Local i:Int = 0
		Local l:Int = FlxG.Cameras.Length()

		While(i < l)
			cam = FlxG.Cameras.Get(i)
			cam.Destroy()
			i+=1
		Wend

		FlxG.Cameras.Clear()
		FlxG.Camera = Null

		If (newCamera = Null) newCamera = New FlxCamera(0, 0, FlxG.Width, FlxG.Height)

		FlxG.Camera = FlxG.AddCamera(newCamera)
	End Function

	Function Flash:Void(color:Int = FlxG.WHITE, duration:Float = 1, onComplete:FlxCameraFlashListener = Null, force:Bool = False)
		Local i:Int = 0
		Local l:Int = FlxG.Cameras.Length()

		While(i < l)
			FlxG.Cameras.Get(i).Flash(color, duration, onComplete, force)
			i+=1
		Wend
	End Function

	Function Fade:Void(color:Int = FlxG.BLACK, duration:Float = 1, onComplete:FlxCameraFadeListener = Null, force:Bool = False)
		Local i:Int = 0
		Local l:Int = FlxG.Cameras.Length()

		While(i < l)
			FlxG.Cameras.Get(i).Fade(color, duration, onComplete, force)
			i+=1
		Wend
	End Function

	Function Shake:Void(intensity:Float = 0.05, duration:Float = 0.5, onComplete:FlxCameraShakeListener = Null, force:Bool = True, direction:Int = FlxCamera.SHAKE_BOTH_AXES)
		Local i:Int = 0
		Local l:Int = FlxG.Cameras.Length()

		While(i < l)
			FlxG.Cameras.Get(i).Shake(intensity, duration, onComplete, force, direction)
			i+=1
		Wend
	End Function

	Function BgColor:Int()
		If (FlxG.Camera = Null Or Not FlxG.Camera.alive) Return FlxG._BgColor.argb
		Return FlxG.Camera.BgColor
	End Function

	Function SetBgColor:Void(color:Int)
		Local i:Int = 0
		Local l:Int = FlxG.Cameras.Length()

		While(i < l)
			FlxG.Cameras.Get(i).BgColor = color
			i+=1
		Wend

		FlxG._BgColor.SetARGB(color)
	End Function

	Function Overlap:Bool(objectOrGroup1:FlxBasic = Null, objectOrGroup2:FlxBasic, notifyCallback:FlxOverlapNotifyListener = Null, processCallback:FlxOverlapProcessListener = Null)
		If (objectOrGroup1 = Null) objectOrGroup1 = FlxG.State()
		If (objectOrGroup2 = objectOrGroup1) objectOrGroup2 = Null

		FlxQuadTree.Divisions = FlxG.WorldDivisions

		Local quadTree:FlxQuadTree = FlxQuadTree.Recycle(FlxG.WorldBounds.x, FlxG.WorldBounds.y, FlxG.WorldBounds.width, FlxG.WorldBounds.height)
		quadTree.Load(objectOrGroup1, objectOrGroup2, notifyCallback, processCallback)

		Local result:Bool = quadTree.Execute()
		quadTree.Destroy()

		Return result
	End Function

	Function Collide:Bool(objectOrGroup1:FlxBasic = Null, objectOrGroup2:FlxBasic = Null, notifyCallback:FlxOverlapNotifyListener = Null)
		Return	Overlap(objectOrGroup1, objectOrGroup2, notifyCallback, _CollideListener)
	End Function

	Function AddPlugin:FlxBasic(plugin:FlxBasic)
		Local pluginList:Stack<FlxBasic> = FlxG.Plugins
		Local i:Int = 0
		Local l:Int = pluginList.Length()

		While(i < l)
			If (pluginList.Get(i).ToString() = plugin.ToString()) Then
				Return plugin
			End If

			i+=1
		Wend

		pluginList.Push(plugin)
		Return plugin
	End Function

	Function GetPlugin:FlxBasic(objectClass:ClassInfo)
		Local pluginList:Stack<FlxBasic> = FlxG.Plugins
		Local plugin:FlxBasic
		Local i:Int = 0
		Local l:Int = pluginList.Length()

		While(i < l)
			plugin = pluginList.Get(i)
			If (plugin.GetClassInfo().ExtendsClass(objectClass)) Return plugin

			i+=1
		Wend

		Return Null
	End Function

	Function GetPlugin:FlxBasic(objectOrClass:Object)
		If (ClassInfo(objectOrClass) <> Null) Then
			Return GetPlugin(ClassInfo(objectOrClass))
		Else
			Return GetPlugin(GetClass(objectOrClass))
		End If
	End Function

	Function RemovePlugin:FlxBasic(plugin:FlxBasic)
		Plugins.RemoveEach(plugin)
		Return plugin
	End Function

	Function RemovePluginType:Bool(objectClass:ClassInfo)
		Local results:Bool = False
		Local pluginList:Stack<FlxBasic> = FlxG.Plugins
		Local i:Int = pluginList.Length() - 1

		While(i >= 0)
			If (pluginList.Get(i).GetClassInfo().ExtendsClass(objectClass)) Then
				pluginList.Remove(i)
				results = True
			End If

			i-=1
		Wend

		Return results
	End Function

	Function Init:Void(game:FlxGame, width:Int, height:Int, zoom:Float)
		FlxG._Game = game
		FlxG.Width = width
		FlxG.Height = height

		FlxG.Tweener = New FlxBasic()
		FlxG.Signals = New FlxSignals()

		FlxG.Mute = False
		FlxG._Volume = .5
		FlxG.Sounds = New FlxGroup()
		FlxG.VolumeHandler = Null

		FlxG.ClearBitmapCache()

		FlxCamera.DefaultZoom = zoom
		FlxG.Cameras = New Stack<FlxCamera>()

		Plugins = New Stack<FlxBasic>

	#If FLX_DEBUG_ENABLED
		AddPlugin(New DebugPathDisplay())
	#End
		AddPlugin(New TimerManager())

		FlxG.Accel = New AccelInput()
		FlxG.Keys = New Keyboard()
		FlxG.Mouse = New MouseInput()

		For Local i:Int = 0 Until _JOY_UNITS_COUNT
			_Joystick[i] = New JoystickInput(i)
		Next

		For Local i:Int = 0 Until _TOUCH_COUNT
			_Touch[i] = New TouchInput(i)
		Next

		FlxG.Mobile = FlxIsMobile()

		FlxG.Scores = New Stack<Int>()
		FlxG.Levels = New Stack<Int>()
		FlxG.VisualDebug = False
	End Function

	Function Reset:Void()
		FlxG.ClearBitmapCache()
		FlxG.DestroySounds(True)
		FlxG.ClearSoundCache()
		FlxG.ResetInput()
		FlxG.Signals.Destroy()
		FlxG.Levels.Clear()
		FlxG.Scores.Clear()
		FlxG.Level = 0
		FlxG.Score = 0
		FlxG.TimeScale = 1
		FlxG.Elapsed = 0
		FlxG.GlobalSeed = Seed
		FlxG.WorldBounds = New FlxRect(-10, -10, FlxG.Width + 20, FlxG.Height + 20)
		FlxG.WorldDivisions = 6

	#If FLX_DEBUG_ENABLED
		Local debugPathDisplay:DebugPathDisplay = DebugPathDisplay(FlxG.GetPlugin(DebugPathDisplay.__CLASS__))
		If (debugPathDisplay <> Null) debugPathDisplay.Clear()
	#End
	End Function

	Function UpdateInput:Void()
	#If FLX_MOUSE_ENABLED
		#If FLX_DEBUG_ENABLED
			If (Not _Game._debuggerUp Or Not _Game._debugger.hasMouse) Then
				Mouse.Update(MouseX(), MouseY())
			End If
		#Else
			Mouse.Update(MouseX(), MouseY())
		#End

		_Touch[0].Update(TouchX(), TouchY())
	#End

	#If FLX_KEYBOARD_ENABLED
		Keys.Update()
	#End

	#If FLX_JOYSTICK_ENABLED
		For Local i:Int = 0 Until _JOY_UNITS_COUNT
			_Joystick[i].Update()
		Next
	#End

	#If FLX_MULTITOUCH_ENABLED
		For Local i:Int = 1 Until _TOUCH_COUNT
			_Touch[i].Update(TouchX(i), TouchY(i))

			If ( Not _Touch[i].Used) Exit
		Next
	#End

	#If FLX_ACCEL_ENABLED
		Accel.Update(AccelX(), AccelY(), AccelZ())
	#End
	End Function

	Function UpdateCameras:Void()
		Local cam:FlxCamera
		Local cams:Stack<FlxCamera> = FlxG.Cameras
		Local i:Int = 0
		Local l:Int = cams.Length()

		While(i < l)
			cam = cams.Get(i)
			If (cam <> Null And cam.exists And cam.active) cam.Update()
			i+=1
		Wend
	End Function

	Function UpdatePlugins:Void()
		Local plugin:FlxBasic
		Local pluginList:Stack<FlxBasic> = FlxG.Plugins
		Local i:Int = 0
		Local l:Int = pluginList.Length()

		While(i < l)
			plugin = pluginList.Get(i)
			If (plugin.exists And plugin.active) plugin.Update()
			i+=1
		Wend
	End Function

	Function DrawPlugins:Void()
		Local plugin:FlxBasic
		Local pluginList:Stack<FlxBasic> = FlxG.Plugins
		Local i:Int = 0
		Local l:Int = pluginList.Length()

		While(i < l)
			plugin = pluginList.Get(i)
			If (plugin.exists And plugin.visible) plugin.Draw()
			i+=1
		Wend
	End Function

	Function Joystick:JoystickInput(unit:Int = 0)
		Return _Joystick[unit]
	End Function

	Function Touch:TouchInput(index:Int = 0)
		Return _Touch[index]
	End Function

	Function JoystickCount:Int()
		Return _JOY_UNITS_COUNT
	End Function

	Function TouchCount:Int()
		Return _TOUCH_COUNT
	End Function

	Function SetResolutionPolicy:Void(resolutionPolicy:FlxResolutionPolicy)
		_ResolutionPolicy = resolutionPolicy
		_Measure()
	End Function

	Function UpdateDevice:Void()
		If(FlxG.DeviceWidth <> MojoDeviceWidth() Or FlxG.DeviceHeight <> MojoDeviceHeight()) Then
			_Measure()
		End If
	End Function

	Function Tween:MultiVarTween(object:Object, values:StringMap<Float>, duration:Float, type:Int = FlxTween.ONESHOT, complete:FlxTweenListener = Null, ease:FlxEaseFunction = Null, tweener:FlxBasic = Null)
		If (tweener = Null) Then
			If (FlxBasic(object) <> Null) Then
				tweener = FlxBasic(object)
			Else
				tweener = FlxG.Tweener
			End If
		End If

		Local tween:MultiVarTween = New MultiVarTween(complete, type)
		tween.Tween(object, values, duration, ease)
		tweener.AddTween(tween)

		Return tween
	End Function

Private
	Function _Measure:Void()
		FlxG.DeviceWidth = MojoDeviceWidth()
		FlxG.DeviceHeight = MojoDeviceHeight()

		_ResolutionPolicy.OnMeasure(FlxG.DeviceWidth, FlxG.DeviceHeight, _Point)

		FlxG._DeviceScaleFactorX = _Point.x / Float(FlxG.Width)
		FlxG._DeviceScaleFactorY = _Point.y / Float(FlxG.Height)

		Local zoom:Float = FlxCamera.DefaultZoom
		If(FlxG.Camera <> Null) zoom = FlxG.Camera.Zoom

		FlxG._DeviceOffsetX = Ceil( (FlxG.DeviceWidth - _Point.x * zoom) * 0.5)
		FlxG._DeviceOffsetY = Ceil( (FlxG.DeviceHeight - _Point.y * zoom) * 0.5)

		Local i:Int = 0
		Local l:Int = FlxG.Cameras.Length()
		Local cam:FlxCamera

		While(i < l)
			cam = FlxG.Cameras.Get(i)

			'recalc values
			cam.X = cam.X
			cam.Y = cam.Y
			cam.Width = cam.Width
			cam.Height = cam.Height

			i += 1
		Wend
	End Function

End Class

Interface FlxVolumeChangeListener

	Method OnVolumeChange:Void(volume:Float)

 End Interface

Private

Class FlxCollideProcessListener Implements FlxOverlapProcessListener

	Method OnOverlapProcess:Bool(object1:FlxObject, object2:FlxObject)
		Return FlxObject.Separate(object1, object2)
	End Method

End Class

Class CreateImageResource Extends FlxResource<Image>

	Field width:Float

	Field height:Float

	Field color:Int

	Field image:Image

	Method New(name:String, width:Float, height:Float, color:Int)
		Super.New(name)
		Self.width = width
		Self.height = height
		Self.color = color
	End Method

	Method Load:Image()
		image = (New FlxImageData(width, height, False, color)).Image
		Return image
	End Method

	Method Use:Image()
		Return image
	End Method

	Method Discard:Void()
		image.Discard()
		image = Null
	End Method

End Class

Strict

Import mojo
Import reflection

Import flxextern
Import flxbasic
Import flxgame
Import flxcamera
Import flxobject
Import flxsignals
Import flxsound
Import flxmusic
Import flxu

Import system.input.accel
Import system.input.joystick
Import system.input.keyboard
Import system.input.mouse
Import system.input.touch
Import system.tweens.flxtween
Import system.tweens.util.ease
Import system.tweens.misc.multivartween
Import system.resolutionpolicy.flxresolutionpolicy
Import system.resolutionpolicy.fill
Import system.flxresourcesmanager
Import system.flxquadtree
Import system.flxreplay
Import system.flximagedata

Import plugin.timermanager
Import plugin.debugpathdisplay

Alias AccelInput = accel.Accel
Alias MouseInput = mouse.Mouse
Alias TouchInput = touch.Touch
Alias JoystickInput = joystick.Joystick
Alias MojoDeviceWidth = mojo.graphics.DeviceWidth
Alias MojoDeviceHeight = mojo.graphics.DeviceHeight

Class FlxG

	Const LIBRARY_NAME:String = "Flixel for Monkey"

	Const LIBRARY_MAJOR_VERSION:Int = 1

	Const LIBRARY_MINOR_VERSION:Int = 0

	Const DATA_SUFFIX:String = "_flx"

	Const RED:Int = $FFFF0012

	Const GREEN:Int = $FF00F225

	Const BLUE:Int = $FF0090E9

	Const PINK:Int = $FFF01EFF

	Const WHITE:Int = $FFFFFFFF

	Const BLACK:Int = $FF000000

	Global Paused:Bool

#If FLX_DEBUG_ENABLED
	Global Debug:Bool = True
#Else
	Global Debug:Bool = False
#End

	Global Elapsed:Float

	Global TimeScale:Float

	Global DeviceWidth:Int

	Global DeviceHeight:Int

	Global Width:Int

	Global Height:Int

	Global WorldBounds:FlxRect

	Global WorldDivisions:Int

	Global VisualDebug:Bool

	Global Mobile:Bool

	Global GlobalSeed:Int

	Global Scores:Stack<Int>

	Global Score:Int

	Global Levels:Stack<Int>

	Global Level:Int

	Global Accel:AccelInput

	Global Keys:Keyboard

	Global Mouse:MouseInput

	Global Music:FlxMusic

	Global Sounds:FlxGroup

	Global Mute:Bool

	Global Cameras:Stack<FlxCamera>

	Global Camera:FlxCamera

	Global Plugins:Stack<FlxBasic>

	Global VolumeHandler:FlxVolumeChangeListener

	Global Updaterate:Int

	Global Tweener:FlxBasic

	Global Signals:FlxSignals

	Global _DeviceScaleFactorX:Float = 1

	Global _DeviceScaleFactorY:Float = 1

	Global _DeviceOffsetX:Int

	Global _DeviceOffsetY:Int

	Global _BgColor:FlxColor = FlxColor.ARGB(FlxG.BLACK)

	Global _Game:FlxGame

	Global _Volume:Float

	Global _BitmapCache:FlxResourcesManager<Image>

	Global _SoundCache:FlxResourcesManager<Sound>

	Global _LastDrawingColor:Int

	Global _LastDrawingAlpha:Float

	Global _LastDrawingBlend:Int

	Global _CurrentCamera:FlxCamera

Private
#If TARGET = "psm"
	Const _JOY_UNITS_COUNT:Int = 1
#Else
	Const _JOY_UNITS_COUNT:Int = 4
#End
	Const _TOUCH_COUNT:Int = 32

	Global _Joystick:JoystickInput[_JOY_UNITS_COUNT]

	Global _Touch:TouchInput[_TOUCH_COUNT]

	Global _CollideListener:FlxCollideProcessListener = New FlxCollideProcessListener()

	Global _ResolutionPolicy:FlxResolutionPolicy = New FillResolutionPolicy()

	Global _Point:FlxPoint = New FlxPoint()

Public
	Function GetLibraryName:String()
		Return FlxG.LIBRARY_NAME + " v" + FlxG.LIBRARY_MAJOR_VERSION + "." + FlxG.LIBRARY_MINOR_VERSION
	End Function

	Function Log:Void(data:String)
	#If FLX_DEBUG_ENABLED
		'note: TODO: to add log objects
		Print data
	#End
	End Function

	Function Random:Float()
		FlxG.GlobalSeed = (FlxG.GlobalSeed * 1664525 + 1013904223) | 0
		Return FlxU.Srand(FlxG.GlobalSeed)
	End Function

	Function Random:Float(range:Float)
		Return FlxG.Random() * range
	End Function

	Function Random:Float(low:Float, high:Float)
		Return FlxG.Random(high - low) + low
	End Function

	Function Random:Int(range:Int)
		Return Int(FlxG.Random() * (1 + range))
	End Function

	Function Random:Int(low:Int, high:Int)
		Return FlxG.Random(high - low) + low
	End Function

	#Rem
	Function GetRandom:Object(objects:Object[], startIndex:Int = 0, length:Int = 0)
		GetRandom is not currently supported in Monkey. Use FlxArray.GetSafeRandom method
	End Function
	#End

	Function LoadReplay:Void(data:String, state:FlxState = Null, cancelKeys:Int[] = [], timeout:Float = 0, callback:FlxReplayListener = Null)
		_Game._replay.Load(data)
		If (state = Null) Then
			FlxG.ResetGame()
		Else
			FlxG.SwitchState(state)
		End If

		_Game._replayCancelKeys = cancelKeys
		_Game._replayTimer = timeout * 1000
		_Game._replayCallback = callback
		_Game._replayRequested = True
	End Function

	Function ReloadReplay:Void(standardMode:Bool = True)
		If (standardMode) Then
			FlxG.ResetGame()
		Else
			FlxG.ResetState()
		End If

		If (_Game._replay.frameCount > 0) _Game._replayRequested = True
	End Function

	Function StopReplay:Void()
		_Game._replaying = False

	#If FLX_DEBUG_ENABLED
		If (_Game._debugger <> Null) Then
			'note: TODO:
		End If
	#End

		ResetInput()
	End Function

	Function RecordReplay:Void(standardMode:Bool = True)
		If (standardMode) Then
			FlxG.ResetGame()
		Else
			FlxG.ResetState()
		End If

		_Game._recordingRequested = True
	End Function

	Function StopRecording:String()
		_Game._recording = False

	#If FLX_DEBUG_ENABLED
		If (_Game._debugger <> Null) Then
			'note: TODO:
		End If
	#End

		Return _Game._replay.Save()
	End Function

	Function ResetState:Void()
		_Game._requestedState = FlxState(_Game._state.GetClassInfo().NewInstance())
	End Function

	Function ResetGame:Void()
		_Game._requestedReset = True
	End Function

	Function ResetInput:Void()
		For Local i:Int = 0 Until _JOY_UNITS_COUNT
			_Joystick[i].Reset()
		Next

		For Local i:Int = 0 Until _TOUCH_COUNT
			_Touch[i].Reset()
		Next

		Accel.Reset()
		Mouse.Reset()
		Keys.Reset()
	End Function

	Function PlayMusic:Void(music:String, volume:Float = 1.0)
		If (FlxG.Music = Null) Then
			FlxG.Music = New FlxMusic()

		ElseIf (FlxG.Music.active) Then
			FlxG.Music.Stop()
		End If

		FlxG.Music.Load(music, True)
		FlxG.Music.Volume = volume
		FlxG.Music.survive = True

		FlxG.Music.Play()
	End Function

	Function LoadSound:FlxSound(sound:String, volume:Float = 1.0, looped:Bool = False, autoDestroy:Bool = False, autoPlay:Bool = False, stopPrevious:Bool = True)
		Local s:FlxSound = FlxSound(Sounds.Recycle(FlxSound.__CLASS__))

		s.Load(sound, looped, autoDestroy, stopPrevious)
		s.Volume = volume
		If (autoPlay) s.Play()

		Return s
	End Function

	Function Play:FlxSound(sound:String, volume:Float = 1.0, looped:Bool = False, autoDestroy:Bool = True)
		Return FlxG.LoadSound(sound, volume, looped, autoDestroy, True, False)
	End Function

	Function Volume:Float()
		Return _Volume
	End Function

	Function Volume:Void(volume:Float)
		_Volume = volume

		If (_Volume < 0) Then
			_Volume = 0
		ElseIf (_Volume > 1) Then
			_Volume = 1
		End If

		If (VolumeHandler <> Null) Then
			If (FlxG.Mute) Then
				VolumeHandler.OnVolumeChange(0)
			Else
				VolumeHandler.OnVolumeChange(_Volume)
			End If
		End If

		If (Music <> Null And Music.active) Then
			Music._UpdateTransform()
		End If

		For Local basic:FlxBasic = EachIn Sounds
			FlxSound(basic)._UpdateTransform()
		Next
	End Function

	Function DestroySounds:Void(forceDestroy:Bool = False)
		If (Music <> Null And (forceDestroy Or Not Music.survive)) Then
			Music.Destroy()
			Music = Null
		End If

		Local sound:FlxSound

		For Local basic:FlxBasic = EachIn Sounds
			sound = FlxSound(basic)

			If (sound <> Null And (forceDestroy Or Not sound.survive)) Then
				sound.Destroy()
			End If
		Next
	End Function

	Function UpdateSounds:Void()
		If (Music <> Null And Music.active) Then
			Music.Update()
		End If

		If (Sounds <> Null And Sounds.active) Then
			Sounds.Update()
		End If
	End Function

	Function PauseSounds:Void()
		If (Music <> Null And Music.exists And Music.active) Then
			Music.Pause()
		End If

		Local sound:FlxSound

		For Local basic:FlxBasic = EachIn Sounds
			sound = FlxSound(basic)

			If (sound <> Null And sound.exists And sound.active) Then
				sound.Pause()
			End If
		Next
	End Function

	Function ResumeSounds:Void()
		If (Music <> Null And Music.exists) Then
			Music.Resume()
		End If

		Local sound:FlxSound

		For Local basic:FlxBasic = EachIn Sounds
			sound = FlxSound(basic)

			If (sound <> Null And sound.exists) Then
				sound.Resume()
			End If
		Next
	End Function

	Function CheckBitmapCache:Bool(key:String)
		Return _BitmapCache.CheckResource(key)
	End Function

	Function CreateBitmap:Image(width:Int, height:Int, color:Int, unigue:Bool, key:String = "")
		If (key.Length() = 0) Then
			key = width + "x" + height + ":" + color

			If (unigue And CheckBitmapCache(key)) Then
				Local inc:Int = 0
				Local ukey:String

				Repeat
					ukey = key + inc
					inc += 1
				Until (CheckBitmapCache(ukey))

				key = ukey
			End If
		End If

		Return _BitmapCache.GetResource(key, New CreateImageResource(key, width, height, color))
	End Function

	Function AddBitmap:Image(resource:FlxResource<Image>, unique:Bool = False, key:String = "")
		If (key.Length() = 0) Then
			key = resource.name

			If (unique And CheckBitmapCache(key)) Then
				Local inc:Int = 0
				Local ukey:String

				Repeat
					ukey = key + inc
					inc += 1
				Until(CheckBitmapCache(ukey))

				key = ukey
			End If
		End If

		Return _BitmapCache.GetResource(key, resource)
	End Function

	Function RemoveBitmap:Void(graphic:String)
		If (_BitmapCache <> Null) Then
			_BitmapCache.RemoveResource(graphic)
		End If
	End Function

	Function ClearBitmapCache:Void()
		If (_BitmapCache = Null) _BitmapCache = New FlxResourcesManager<Image>()
		_BitmapCache.Clear()
	End Function

	Function AddSound:Sound(resource:FlxResource<Sound>)
		Return _SoundCache.GetResource(resource.name, resource)
	End Function

	Function ClearSoundCache:Void()
		If (_SoundCache = Null) _SoundCache = New FlxResourcesManager<Sound>()
		_SoundCache.Clear()
	End Function

	Function State:FlxState()
		Return _Game._state
	End Function

	Function SwitchState:Void(state:FlxState)
		FlxG._Game._requestedState = state
	End Function

	Function SetSwitchStateListener:Void(listener:FlxSwitchStateListener)
		FlxG._Game.SetSwitchStateListener(listener)
	End Function

	Function AddCamera:FlxCamera(newCamera:FlxCamera)
		FlxG.Cameras.Push(newCamera)
		Return newCamera
	End Function

	Function RemoveCamera:Void(camera:FlxCamera, destroy:Bool = True)
		FlxG.Cameras.RemoveEach(camera)
		If (destroy) camera.Destroy()
	End Function

	Function ResetCameras:Void(newCamera:FlxCamera = Null)
		Local cam:FlxCamera
		Local i:Int = 0
		Local l:Int = FlxG.Cameras.Length()

		While(i < l)
			cam = FlxG.Cameras.Get(i)
			cam.Destroy()
			i+=1
		Wend

		FlxG.Cameras.Clear()
		FlxG.Camera = Null

		If (newCamera = Null) newCamera = New FlxCamera(0, 0, FlxG.Width, FlxG.Height)

		FlxG.Camera = FlxG.AddCamera(newCamera)
	End Function

	Function Flash:Void(color:Int = FlxG.WHITE, duration:Float = 1, onComplete:FlxCameraFlashListener = Null, force:Bool = False)
		Local i:Int = 0
		Local l:Int = FlxG.Cameras.Length()

		While(i < l)
			FlxG.Cameras.Get(i).Flash(color, duration, onComplete, force)
			i+=1
		Wend
	End Function

	Function Fade:Void(color:Int = FlxG.BLACK, duration:Float = 1, onComplete:FlxCameraFadeListener = Null, force:Bool = False)
		Local i:Int = 0
		Local l:Int = FlxG.Cameras.Length()

		While(i < l)
			FlxG.Cameras.Get(i).Fade(color, duration, onComplete, force)
			i+=1
		Wend
	End Function

	Function Shake:Void(intensity:Float = 0.05, duration:Float = 0.5, onComplete:FlxCameraShakeListener = Null, force:Bool = True, direction:Int = FlxCamera.SHAKE_BOTH_AXES)
		Local i:Int = 0
		Local l:Int = FlxG.Cameras.Length()

		While(i < l)
			FlxG.Cameras.Get(i).Shake(intensity, duration, onComplete, force, direction)
			i+=1
		Wend
	End Function

	Function BgColor:Int()
		If (FlxG.Camera = Null Or Not FlxG.Camera.alive) Return FlxG._BgColor.argb
		Return FlxG.Camera.BgColor
	End Function

	Function SetBgColor:Void(color:Int)
		Local i:Int = 0
		Local l:Int = FlxG.Cameras.Length()

		While(i < l)
			FlxG.Cameras.Get(i).BgColor = color
			i+=1
		Wend

		FlxG._BgColor.SetARGB(color)
	End Function

	Function Overlap:Bool(objectOrGroup1:FlxBasic = Null, objectOrGroup2:FlxBasic, notifyCallback:FlxOverlapNotifyListener = Null, processCallback:FlxOverlapProcessListener = Null)
		If (objectOrGroup1 = Null) objectOrGroup1 = FlxG.State()
		If (objectOrGroup2 = objectOrGroup1) objectOrGroup2 = Null

		FlxQuadTree.Divisions = FlxG.WorldDivisions

		Local quadTree:FlxQuadTree = FlxQuadTree.Recycle(FlxG.WorldBounds.x, FlxG.WorldBounds.y, FlxG.WorldBounds.width, FlxG.WorldBounds.height)
		quadTree.Load(objectOrGroup1, objectOrGroup2, notifyCallback, processCallback)

		Local result:Bool = quadTree.Execute()
		quadTree.Destroy()

		Return result
	End Function

	Function Collide:Bool(objectOrGroup1:FlxBasic = Null, objectOrGroup2:FlxBasic = Null, notifyCallback:FlxOverlapNotifyListener = Null)
		Return	Overlap(objectOrGroup1, objectOrGroup2, notifyCallback, _CollideListener)
	End Function

	Function AddPlugin:FlxBasic(plugin:FlxBasic)
		Local pluginList:Stack<FlxBasic> = FlxG.Plugins
		Local i:Int = 0
		Local l:Int = pluginList.Length()

		While(i < l)
			If (pluginList.Get(i).ToString() = plugin.ToString()) Then
				Return plugin
			End If

			i+=1
		Wend

		pluginList.Push(plugin)
		Return plugin
	End Function

	Function GetPlugin:FlxBasic(objectClass:ClassInfo)
		Local pluginList:Stack<FlxBasic> = FlxG.Plugins
		Local plugin:FlxBasic
		Local i:Int = 0
		Local l:Int = pluginList.Length()

		While(i < l)
			plugin = pluginList.Get(i)
			If (plugin.GetClassInfo().ExtendsClass(objectClass)) Return plugin

			i+=1
		Wend

		Return Null
	End Function

	Function GetPlugin:FlxBasic(objectOrClass:Object)
		If (ClassInfo(objectOrClass) <> Null) Then
			Return GetPlugin(ClassInfo(objectOrClass))
		Else
			Return GetPlugin(GetClass(objectOrClass))
		End If
	End Function

	Function RemovePlugin:FlxBasic(plugin:FlxBasic)
		Plugins.RemoveEach(plugin)
		Return plugin
	End Function

	Function RemovePluginType:Bool(objectClass:ClassInfo)
		Local results:Bool = False
		Local pluginList:Stack<FlxBasic> = FlxG.Plugins
		Local i:Int = pluginList.Length() - 1

		While(i >= 0)
			If (pluginList.Get(i).GetClassInfo().ExtendsClass(objectClass)) Then
				pluginList.Remove(i)
				results = True
			End If

			i-=1
		Wend

		Return results
	End Function

	Function Init:Void(game:FlxGame, width:Int, height:Int, zoom:Float)
		FlxG._Game = game
		FlxG.Width = width
		FlxG.Height = height

		FlxG.Tweener = New FlxBasic()
		FlxG.Signals = New FlxSignals()

		FlxG.Mute = False
		FlxG._Volume = .5
		FlxG.Sounds = New FlxGroup()
		FlxG.VolumeHandler = Null

		FlxG.ClearBitmapCache()

		FlxCamera.DefaultZoom = zoom
		FlxG.Cameras = New Stack<FlxCamera>()

		Plugins = New Stack<FlxBasic>

	#If FLX_DEBUG_ENABLED
		AddPlugin(New DebugPathDisplay())
	#End
		AddPlugin(New TimerManager())

		FlxG.Accel = New AccelInput()
		FlxG.Keys = New Keyboard()
		FlxG.Mouse = New MouseInput()

		For Local i:Int = 0 Until _JOY_UNITS_COUNT
			_Joystick[i] = New JoystickInput(i)
		Next

		For Local i:Int = 0 Until _TOUCH_COUNT
			_Touch[i] = New TouchInput(i)
		Next

		FlxG.Mobile = FlxIsMobile()

		FlxG.Scores = New Stack<Int>()
		FlxG.Levels = New Stack<Int>()
		FlxG.VisualDebug = False
	End Function

	Function Reset:Void()
		FlxG.ClearBitmapCache()
		FlxG.DestroySounds(True)
		FlxG.ClearSoundCache()
		FlxG.ResetInput()
		FlxG.Signals.Destroy()
		FlxG.Levels.Clear()
		FlxG.Scores.Clear()
		FlxG.Level = 0
		FlxG.Score = 0
		FlxG.TimeScale = 1
		FlxG.Elapsed = 0
		FlxG.GlobalSeed = Seed
		FlxG.WorldBounds = New FlxRect(-10, -10, FlxG.Width + 20, FlxG.Height + 20)
		FlxG.WorldDivisions = 6

	#If FLX_DEBUG_ENABLED
		Local debugPathDisplay:DebugPathDisplay = DebugPathDisplay(FlxG.GetPlugin(DebugPathDisplay.__CLASS__))
		If (debugPathDisplay <> Null) debugPathDisplay.Clear()
	#End
	End Function

	Function UpdateInput:Void()
	#If FLX_MOUSE_ENABLED
		#If FLX_DEBUG_ENABLED
			If (Not _Game._debuggerUp Or Not _Game._debugger.hasMouse) Then
				Mouse.Update(MouseX(), MouseY())
			End If
		#Else
			Mouse.Update(MouseX(), MouseY())
		#End

		_Touch[0].Update(TouchX(), TouchY())
	#End

	#If FLX_KEYBOARD_ENABLED
		Keys.Update()
	#End

	#If FLX_JOYSTICK_ENABLED
		For Local i:Int = 0 Until _JOY_UNITS_COUNT
			_Joystick[i].Update()
		Next
	#End

	#If FLX_MULTITOUCH_ENABLED
		For Local i:Int = 1 Until _TOUCH_COUNT
			_Touch[i].Update(TouchX(i), TouchY(i))

			If ( Not _Touch[i].Used) Exit
		Next
	#End

	#If FLX_ACCEL_ENABLED
		Accel.Update(AccelX(), AccelY(), AccelZ())
	#End
	End Function

	Function UpdateCameras:Void()
		Local cam:FlxCamera
		Local cams:Stack<FlxCamera> = FlxG.Cameras
		Local i:Int = 0
		Local l:Int = cams.Length()

		While(i < l)
			cam = cams.Get(i)
			If (cam <> Null And cam.exists And cam.active) cam.Update()
			i+=1
		Wend
	End Function

	Function UpdatePlugins:Void()
		Local plugin:FlxBasic
		Local pluginList:Stack<FlxBasic> = FlxG.Plugins
		Local i:Int = 0
		Local l:Int = pluginList.Length()

		While(i < l)
			plugin = pluginList.Get(i)
			If (plugin.exists And plugin.active) plugin.Update()
			i+=1
		Wend
	End Function

	Function DrawPlugins:Void()
		Local plugin:FlxBasic
		Local pluginList:Stack<FlxBasic> = FlxG.Plugins
		Local i:Int = 0
		Local l:Int = pluginList.Length()

		While(i < l)
			plugin = pluginList.Get(i)
			If (plugin.exists And plugin.visible) plugin.Draw()
			i+=1
		Wend
	End Function

	Function Joystick:JoystickInput(unit:Int = 0)
		Return _Joystick[unit]
	End Function

	Function Touch:TouchInput(index:Int = 0)
		Return _Touch[index]
	End Function

	Function JoystickCount:Int()
		Return _JOY_UNITS_COUNT
	End Function

	Function TouchCount:Int()
		Return _TOUCH_COUNT
	End Function

	Function SetResolutionPolicy:Void(resolutionPolicy:FlxResolutionPolicy)
		_ResolutionPolicy = resolutionPolicy
		_Measure()
	End Function

	Function UpdateDevice:Void()
		If(FlxG.DeviceWidth <> MojoDeviceWidth() Or FlxG.DeviceHeight <> MojoDeviceHeight()) Then
			_Measure()
		End If
	End Function

	Function Tween:MultiVarTween(object:Object, values:StringMap<Float>, duration:Float, type:Int = FlxTween.ONESHOT, complete:FlxTweenListener = Null, ease:FlxEaseFunction = Null, tweener:FlxBasic = Null)
		If (tweener = Null) Then
			If (FlxBasic(object) <> Null) Then
				tweener = FlxBasic(object)
			Else
				tweener = FlxG.Tweener
			End If
		End If

		Local tween:MultiVarTween = New MultiVarTween(complete, type)
		tween.Tween(object, values, duration, ease)
		tweener.AddTween(tween)

		Return tween
	End Function

Private
	Function _Measure:Void()
		FlxG.DeviceWidth = MojoDeviceWidth()
		FlxG.DeviceHeight = MojoDeviceHeight()

		_ResolutionPolicy.OnMeasure(FlxG.DeviceWidth, FlxG.DeviceHeight, _Point)

		FlxG._DeviceScaleFactorX = _Point.x / Float(FlxG.Width)
		FlxG._DeviceScaleFactorY = _Point.y / Float(FlxG.Height)

		Local zoom:Float = FlxCamera.DefaultZoom
		If(FlxG.Camera <> Null) zoom = FlxG.Camera.Zoom

		FlxG._DeviceOffsetX = Ceil( (FlxG.DeviceWidth - _Point.x * zoom) * 0.5)
		FlxG._DeviceOffsetY = Ceil( (FlxG.DeviceHeight - _Point.y * zoom) * 0.5)

		Local i:Int = 0
		Local l:Int = FlxG.Cameras.Length()
		Local cam:FlxCamera

		While(i < l)
			cam = FlxG.Cameras.Get(i)

			'recalc values
			cam.X = cam.X
			cam.Y = cam.Y
			cam.Width = cam.Width
			cam.Height = cam.Height

			i += 1
		Wend
	End Function

End Class

Interface FlxVolumeChangeListener

	Method OnVolumeChange:Void(volume:Float)

 End Interface

Private

Class FlxCollideProcessListener Implements FlxOverlapProcessListener

	Method OnOverlapProcess:Bool(object1:FlxObject, object2:FlxObject)
		Return FlxObject.Separate(object1, object2)
	End Method

End Class

Class CreateImageResource Extends FlxResource<Image>

	Field width:Float

	Field height:Float

	Field color:Int

	Field image:Image

	Method New(name:String, width:Float, height:Float, color:Int)
		Super.New(name)
		Self.width = width
		Self.height = height
		Self.color = color
	End Method

	Method Load:Image()
		image = (New FlxImageData(width, height, False, color)).Image
		Return image
	End Method

	Method Use:Image()
		Return image
	End Method

	Method Discard:Void()
		image.Discard()
		image = Null
	End Method

End Class


Added shallow array comparison to Arrays utility class.

' Example:
' Arrays<Int>.Join([1,2,3], [4,5]) returns a new array [1,2,3,4,5]
' Arrays<String>.Fill(["a","b","c"], "d") fills the existing array and returns it ["d","d","d"] (it doesn't create a new array)
' Arrays<Int>.Slice([1,3,5,7,9], 1, 4) returns a new array [3,5,7] which is from 1 (inclusive) to 4 (exclusive)
' Arrays<Float>.Clone([1.0,2.5,3.0]) returns a new array with the same contents [1.0,2.5,3.0]
' Arrays<Int>.Copy([1,2,3,4], 1, [5,6,7,8], 2, 2) copies 2 characters from index 1 in src to index 3 in dest. dest now contains [5,6,2,3]
' Join accepts up to 10 arrays.  Unused parameters are assumed to be empty arrays.
Class Arrays<T>
	Function Join:T[](arr1:T[], arr2:T[], arr3:T[]=[], arr4:T[]=[], arr5:T[]=[], arr6:T[]=[], arr7:T[]=[], arr8:T[]=[], arr9:T[]=[], arr10:T[]=[])
		Local rv:T[] = New T[arr1.Length + arr2.Length + arr3.Length + arr4.Length + arr5.Length + arr6.Length + arr7.Length + arr8.Length + arr9.Length + arr10.Length]
		Local ptr:Int = 0
		If arr1.Length > 0 Then
			For Local i:Int = 0 Until arr1.Length
				rv[i] = arr1[i]
			Next
			ptr += arr1.Length
		End
		If arr2.Length > 0 Then
			For Local i:Int = 0 Until arr2.Length
				rv[i+ptr] = arr2[i]
			Next
			ptr += arr2.Length
		End
		If arr3.Length > 0 Then
			For Local i:Int = 0 Until arr3.Length
				rv[i+ptr] = arr3[i]
			Next
			ptr += arr3.Length
		End
		If arr4.Length > 0 Then
			For Local i:Int = 0 Until arr4.Length
				rv[i+ptr] = arr4[i]
			Next
			ptr += arr4.Length
		End
		If arr5.Length > 0 Then
			For Local i:Int = 0 Until arr5.Length
				rv[i+ptr] = arr5[i]
			Next
			ptr += arr5.Length
		End
		If arr6.Length > 0 Then
			For Local i:Int = 0 Until arr6.Length
				rv[i+ptr] = arr6[i]
			Next
			ptr += arr6.Length
		End
		If arr7.Length > 0 Then
			For Local i:Int = 0 Until arr7.Length
				rv[i+ptr] = arr7[i]
			Next
			ptr += arr7.Length
		End
		If arr8.Length > 0 Then
			For Local i:Int = 0 Until arr8.Length
				rv[i+ptr] = arr8[i]
			Next
			ptr += arr8.Length
		End
		If arr9.Length > 0 Then
			For Local i:Int = 0 Until arr9.Length
				rv[i+ptr] = arr9[i]
			Next
			ptr += arr9.Length
		End
		If arr10.Length > 0 Then
			For Local i:Int = 0 Until arr10.Length
				rv[i+ptr] = arr10[i]
			Next
			ptr += arr10.Length
		End
		Return rv
	End

	Function Fill:T[](arr:T[], val:T)
		For Local i:Int = 0 Until arr.Length
			arr[i] = val
		Next
		Return arr
	End

	Function Clone:T[](arr:T[])
		Local rv:T[] = New T[arr.Length]
		For Local i:Int = 0 Until arr.Length
			rv[i] = arr[i]
		Next
		Return rv
	End

	Function Copy:Void(src:T[], srcPos:Int, dest:T[], destPos:Int, length:Int)
		If length = 0 Then Return
		If length < 0 Then Error("Arrays.Copy: length < 0")
		If srcPos < 0 Then Error("Arrays.Copy: srcPos < 0")
		If destPos < 0 Then Error("Arrays.Copy: destPos < 0")
		If srcPos >= src.Length Then Error("Arrays.Copy: srcPos ("+srcPos+") >= src.Length ("+src.Length+")")
		If destPos >= dest.Length Then Error("Arrays.Copy: destPos ("+destPos+") >= dest.Length ("+dest.Length+")")
		If srcPos + length > src.Length Then Error("Arrays.Copy: srcPos ("+srcPos+") + length ("+length+") > src.Length ("+src.Length+")")
		If destPos + length > dest.Length Then Error("Arrays.Copy: destPos ("+destPos+") + length ("+length+") > dest.Length ("+dest.Length+")")

		' since we can't compare array object references, we must never assume that src and dest are different objects
		' as such, we'll copy the src values into a temp array (wasted cycles, but oh well)
		Local temp:T[] = New T[length]
		For Local i:Int = 0 Until length
			temp[i] = src[srcPos+i]
		Next
		For Local i:Int = 0 Until length
			dest[destPos+i] = temp[i]
		Next
	End

	Function Slice:T[](arr:T[], startIndex:Int, endIndex:Int)
		Local length:Int = endIndex-startIndex
		Local rv:T[] = New T[length]
		For Local i:Int = 0 Until length
			rv[i] = arr[startIndex+i]
		Next
		Return rv
	End

	Function Reverse:Void(arr:T[])
		For Local i:Int = 0 Until arr.Length/2
			Local tmp:Int = arr[i]
			arr[i] = arr[arr.Length-i-1]
			arr[arr.Length-i-1] = tmp
		Next
	End

	Function Equals:Bool(arr1:T[], arr2:T[])
		If arr1.Length <> arr2.Length Then Return False
		For Local i:Int = 0 Until arr1.Length
			If arr1[i] <> arr2[i] Then Return False
		Next
		Return True
	End
End

' Example:
' Arrays<Int>.Join([1,2,3], [4,5]) returns a new array [1,2,3,4,5]
' Arrays<String>.Fill(["a","b","c"], "d") fills the existing array and returns it ["d","d","d"] (it doesn't create a new array)
' Arrays<Int>.Slice([1,3,5,7,9], 1, 4) returns a new array [3,5,7] which is from 1 (inclusive) to 4 (exclusive)
' Arrays<Float>.Clone([1.0,2.5,3.0]) returns a new array with the same contents [1.0,2.5,3.0]
' Arrays<Int>.Copy([1,2,3,4], 1, [5,6,7,8], 2, 2) copies 2 characters from index 1 in src to index 3 in dest. dest now contains [5,6,2,3]
' Join accepts up to 10 arrays.  Unused parameters are assumed to be empty arrays.
Class Arrays<T>
	Function Join:T[](arr1:T[], arr2:T[], arr3:T[]=[], arr4:T[]=[], arr5:T[]=[], arr6:T[]=[], arr7:T[]=[], arr8:T[]=[], arr9:T[]=[], arr10:T[]=[])
		Local rv:T[] = New T[arr1.Length + arr2.Length + arr3.Length + arr4.Length + arr5.Length + arr6.Length + arr7.Length + arr8.Length + arr9.Length + arr10.Length]
		Local ptr:Int = 0
		If arr1.Length > 0 Then
			For Local i:Int = 0 Until arr1.Length
				rv[i] = arr1[i]
			Next
			ptr += arr1.Length
		End
		If arr2.Length > 0 Then
			For Local i:Int = 0 Until arr2.Length
				rv[i+ptr] = arr2[i]
			Next
			ptr += arr2.Length
		End
		If arr3.Length > 0 Then
			For Local i:Int = 0 Until arr3.Length
				rv[i+ptr] = arr3[i]
			Next
			ptr += arr3.Length
		End
		If arr4.Length > 0 Then
			For Local i:Int = 0 Until arr4.Length
				rv[i+ptr] = arr4[i]
			Next
			ptr += arr4.Length
		End
		If arr5.Length > 0 Then
			For Local i:Int = 0 Until arr5.Length
				rv[i+ptr] = arr5[i]
			Next
			ptr += arr5.Length
		End
		If arr6.Length > 0 Then
			For Local i:Int = 0 Until arr6.Length
				rv[i+ptr] = arr6[i]
			Next
			ptr += arr6.Length
		End
		If arr7.Length > 0 Then
			For Local i:Int = 0 Until arr7.Length
				rv[i+ptr] = arr7[i]
			Next
			ptr += arr7.Length
		End
		If arr8.Length > 0 Then
			For Local i:Int = 0 Until arr8.Length
				rv[i+ptr] = arr8[i]
			Next
			ptr += arr8.Length
		End
		If arr9.Length > 0 Then
			For Local i:Int = 0 Until arr9.Length
				rv[i+ptr] = arr9[i]
			Next
			ptr += arr9.Length
		End
		If arr10.Length > 0 Then
			For Local i:Int = 0 Until arr10.Length
				rv[i+ptr] = arr10[i]
			Next
			ptr += arr10.Length
		End
		Return rv
	End

	Function Fill:T[](arr:T[], val:T)
		For Local i:Int = 0 Until arr.Length
			arr[i] = val
		Next
		Return arr
	End

	Function Clone:T[](arr:T[])
		Local rv:T[] = New T[arr.Length]
		For Local i:Int = 0 Until arr.Length
			rv[i] = arr[i]
		Next
		Return rv
	End

	Function Copy:Void(src:T[], srcPos:Int, dest:T[], destPos:Int, length:Int)
		If length = 0 Then Return
		If length < 0 Then Error("Arrays.Copy: length < 0")
		If srcPos < 0 Then Error("Arrays.Copy: srcPos < 0")
		If destPos < 0 Then Error("Arrays.Copy: destPos < 0")
		If srcPos >= src.Length Then Error("Arrays.Copy: srcPos ("+srcPos+") >= src.Length ("+src.Length+")")
		If destPos >= dest.Length Then Error("Arrays.Copy: destPos ("+destPos+") >= dest.Length ("+dest.Length+")")
		If srcPos + length > src.Length Then Error("Arrays.Copy: srcPos ("+srcPos+") + length ("+length+") > src.Length ("+src.Length+")")
		If destPos + length > dest.Length Then Error("Arrays.Copy: destPos ("+destPos+") + length ("+length+") > dest.Length ("+dest.Length+")")

		' since we can't compare arrays, we must never assume that src and dest are different objects
		' as such, we'll copy the src values into a temp array (wasted cycles, but oh well)
		Local temp:T[] = New T[length]
		For Local i:Int = 0 Until length
			temp[i] = src[srcPos+i]
		Next
		For Local i:Int = 0 Until length
			dest[destPos+i] = temp[i]
		Next
	End

	Function Slice:T[](arr:T[], startIndex:Int, endIndex:Int)
		Local length:Int = endIndex-startIndex
		Local rv:T[] = New T[length]
		For Local i:Int = 0 Until length
			rv[i] = arr[startIndex+i]
		Next
		Return rv
	End

	Function Reverse:Void(arr:T[])
		For Local i:Int = 0 Until arr.Length/2
			Local tmp:Int = arr[i]
			arr[i] = arr[arr.Length-i-1]
			arr[arr.Length-i-1] = tmp
		Next
	End
End


Added missing imports

Added missing imports

Import flxbasic
Import flxcamera
Import flxextern
Import flxg
Import flxgame
Import flxgroup
Import flxobject
Import flxpath
Import flxpoint
Import flxrect
Import flxsprite
Import flxstate
Import flxtext
Import flxtilemap
Import flxtimer
Import flxu

Import system.flxanim
Import system.flxarray
Import system.flxassetsmanager
Import system.flxcolor
Import system.flxfont
Import system.flxresourcesmanager

Import plugin.debugpathdisplay
Import plugin.timermanager

Import flxextern
Import flxpoint
Import flxrect
Import flxbasic
Import flxgroup
Import flxobject
Import flxsprite
Import flxtext
Import flxstate
Import flxtimer
Import flxg
Import flxgame
Import flxu

Import system.flxcolor
Import system.flxarray
Import system.flxassetsmanager
Import system.flxresourcesmanager
Import system.flxfont
Import system.flxanim


Missing brackets - sorry

Missing brackets - sorry

Strict

#BONO_ANDROID_MARKET="google"
#If Not (BONO_ANDROID_MARKET="google") And Not (BONO_ANDROID_MARKET="amazon")
#Error "Invalid BONO_ANDROID_MARKET setting - must be 'google' or 'amazon'"
#End

Class Target Abstract

#If BONO_ANDROID_MARKET="google"
    Const IS_MARKET_GOOGLE:Bool = True
#Else
    Const IS_MARKET_GOOGLE:Bool = False
#End

#If BONO_ANDROID_MARKET="amazon"
    Const IS_MARKET_AMAZON:Bool = True
#Else
    Const IS_MARKET_AMAZON:Bool = False
#End

#If TARGET="android"
    Const IS_ANDROID:Bool = True
#Else
    Const IS_ANDROID:Bool = False
#End

#If TARGET="flash"
    Const IS_FLASH:Bool = True
#Else
    Const IS_FLASH:Bool = False
#End

#If TARGET="glfw"
    Const IS_GLFW:Bool = True
#Else
    Const IS_GLFW:Bool = False
#End

#If TARGET="html4"
    Const IS_HTML5:Bool = True
#Else
    Const IS_HTML5:Bool = False
#End

#If TARGET="ios"
    Const IS_IOS:Bool = True
#Else
    Const IS_IOS:Bool = False
#End

#If TARGET="metro"
    Const IS_METRO:Bool = True
#Else
    Const IS_METRO:Bool = False
#End

#If TARGET="psm"
    Const IS_PSM:Bool = True
#Else
    Const IS_PSM:Bool = False
#End

#If TARGET="stdcpp"
    Const IS_STDCPP:Bool = True
#Else
    Const IS_STDCPP:Bool = False
#End

#If TARGET="xna"
    Const IS_XNA:Bool = True
#Else
    Const IS_XNA:Bool = False
#End

End

Strict

#BONO_ANDROID_MARKET="google"
#If Not BONO_ANDROID_MARKET="google" And Not BONO_ANDROID_MARKET="amazon"
#Error "Invalid BONO_ANDROID_MARKET setting - must be 'google' or 'amazon'"
#End

Class Target Abstract

#If BONO_ANDROID_MARKET="google"
    Const IS_MARKET_GOOGLE:Bool = True
#Else
    Const IS_MARKET_GOOGLE:Bool = False
#End

#If BONO_ANDROID_MARKET="amazon"
    Const IS_MARKET_AMAZON:Bool = True
#Else
    Const IS_MARKET_AMAZON:Bool = False
#End

#If TARGET="android"
    Const IS_ANDROID:Bool = True
#Else
    Const IS_ANDROID:Bool = False
#End

#If TARGET="flash"
    Const IS_FLASH:Bool = True
#Else
    Const IS_FLASH:Bool = False
#End

#If TARGET="glfw"
    Const IS_GLFW:Bool = True
#Else
    Const IS_GLFW:Bool = False
#End

#If TARGET="html4"
    Const IS_HTML5:Bool = True
#Else
    Const IS_HTML5:Bool = False
#End

#If TARGET="ios"
    Const IS_IOS:Bool = True
#Else
    Const IS_IOS:Bool = False
#End

#If TARGET="metro"
    Const IS_METRO:Bool = True
#Else
    Const IS_METRO:Bool = False
#End

#If TARGET="psm"
    Const IS_PSM:Bool = True
#Else
    Const IS_PSM:Bool = False
#End

#If TARGET="stdcpp"
    Const IS_STDCPP:Bool = True
#Else
    Const IS_STDCPP:Bool = False
#End

#If TARGET="xna"
    Const IS_XNA:Bool = True
#Else
    Const IS_XNA:Bool = False
#End

End


Fixed a few typos.

Fixed a few typos.

Strict

Public

' Imports (Public):
Import bitfield
Import compare

' Imports (Private):
Private

Import regal.sizeof

Import brl.stream
Import brl.databuffer

Import except

Public

' 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:UInt(I:UInt)
	If (Not BigEndian()) Then
		Return AsByte(I)
	Endif

	Return I
End

' This command is little-endian only:
Function AsByte:UInt(I:UInt)
	Return ((I Shl 24) Shr 24) ' (I & $FF)
End

' This converts an "address" (Real offset) to an index with a 2-byte stride.
Function ToShortArrayIndex:UInt(Address:UInt)
	Return (Address / SizeOf_Short)
End

' This converts an "address" (Real offset) to an index with a 4-byte stride.
Function ToIntArrayIndex:UInt(Address:UInt)
	Return (Address / SizeOf_Integer)
End

' This converts a 2-byte stride into bytes.
Function FromShortArrayIndex:UInt(Index:UInt)
	Return (Index * SizeOf_Short)
End

' This converts a 4-byte stride into bytes.
Function FromIntArrayIndex:Uint(Index:UInt)
	Return (Index * SizeOf_Integer)
End

' This command is useful when dealing with arrays.
Function OutOfBounds:Bool(Position:UInt, Length:UInt)
	Return (Position >= Length)
End

' This performs a transfer operation from 'InputStream' to
' 'OutputStream', using a block of memory of size 'DataSize'.
Function Transfer:Void(InputStream:Stream, OutputStream:Stream, DataSize:UInt)
	' Check for errors:
	#If Not MONKEYLANG_EXTENSION_TYPE_UNISGNED_INT
		If (DataSize <= 0) Then
			Throw New StreamTransferException(Null, DataSize)
		Endif
	#End

	If (InputStream = Null Or OutputStream = Null) Then
		Throw New StreamUnavailableException()
	End

	' Local variable(s):
	#If UTIL_TEMP_BUFFERS
		Local Data:DataBuffer = New DataBuffer(DataSize)

		If (Data = Null) Then ' Data.Length <> DataSize
			Throw New BulkAllocationException<DataBuffer>(Data, DataSize)
		Endif

		Local DataLength:= DataSize ' Data.Length

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

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

		' This is terrible, but it's our only option without temporary buffers.
		For Local I:= 1 To DataSize ' Data.Length
			OutputStream.WriteByte(InputStream.ReadByte())
		Next
	#End

	Return
End

Function ResizeBuffer:DataBuffer(Buffer:DataBuffer, Size:Long=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

Function SetBuffer:Void(Output:DataBuffer, Value:Byte, Count:UInt, Offset:UInt=0)
	For Local I:= Offset Until (Count + Offset)
		Output.PokeByte(I, Value)
	Next

	Return
End

Function SetBuffer:Void(Output:DataBuffer, Value:Byte, Offset:UInt=0)
	SetBuffer(Output, Value, Output.Length - Offset, Offset)

	Return
End

' This writes a 16-bit integer at the "index" specified using the input-value.
' The index specified has a stride of 2 bytes.
Function ArraySetShort:Void(Output:DataBuffer, Index:UInt, Value:UShort, Offset:UInt=0)
	Output.PokeShort(Offset + FromShortArrayIndex(Index), Short(Value & $FFFF))

	Return
End

' This writes a 32-bit integer at the "index" specified using the input-value.
' The index specified has a stride of 4 bytes.
Function ArraySetInt:Void(Output:DataBuffer, Index:UInt, Value:UInt, Offset:UInt=0)
	Output.PokeInt(Offset + FromIntArrayIndex(Index), Int(Value & $FFFFFFFF))

	Return
End

' This reads a 16-bit integer at the "index" specified.
' The index specified has a stride of 2 bytes.
Function ArrayGetShort:UShort(Input:DataBuffer, Index:UInt, Offset:UInt=0)
	Return (Input.PeekShort(Offset + FromShortArrayIndex(Index)) & $FFFF)
End

' This reads a 32-bit integer at the "index" specified.
' The index specified has a stride of 4 bytes.
Function ArrayGetInt:UInt(Input:DataBuffer, Index:UInt, Offset:UInt=0)
	Return (Input.PeekInt(Offset + FromIntArrayIndex(Index)) & $FFFFFFFF)
End

Function SetBufferBytes:Void(Output:DataBuffer, Bytes:Byte[], Bytes_Length:UInt, Bytes_Offset:UInt=0, Offset:UInt=0)
	For Local I:= 0 Until Bytes_Length
		Output.PokeByte((I + Offset), (Bytes[I + Bytes_Offset] & $FF)) ' (I * SizeOf_Byte)
	Next

	Return
End

Function SetBufferBytes:Void(Output:DataBuffer, Bytes:Byte[], Offset:UInt=0)
	SetBufferBytes(Output, Bytes, Bytes.Length, 0, Offset)

	Return
End

Function SetBufferShorts:Void(Output:DataBuffer, Shorts:Short[], Shorts_Length:UInt, Shorts_Offset:UInt=0, Offset:UInt=0)
	For Local I:= 0 Until Shorts_Length
		Output.PokeShort(((I * SizeOf_Short) + Offset), (Shorts[I + Shorts_Offset] & $FFFF))
	Next

	Return
End

Function SetBufferShorts:Void(Output:DataBuffer, Shorts:Short[], Offset:UInt=0)
	SetBufferShorts(Output, Shorts, Shorts.Length, 0, Offset)

	Return
End

Function SetBufferInts:Void(Output:DataBuffer, Ints:Int[], Ints_Length:UInt, Ints_Offset:UInt=0, Offset:UInt=0)
	For Local I:= 0 Until Ints_Length
		Output.PokeInt(((I * SizeOf_Integer) + Offset), (Ints[I + Ints_Offset] & $FFFFFFFF))
	Next

	Return
End

Function SetBufferInts:Void(Output:DataBuffer, Ints:Int[], Offset:UInt=0)
	SetBufferInts(Output, Ints, Ints.Length, 0, Offset)

	Return
End

Strict

Public

' Imports (Public):
Import bitfield
Import compare

' Imports (Private):
Private

Import regal.sizeof

Import brl.stream
Import brl.databuffer

Import except

Public

' 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:UInt(I:UInt)
	If (Not BigEndian()) Then
		Return AsByte(I)
	Endif

	Return I
End

' This command is little-endian only:
Function AsByte:UInt(I:UInt)
	Return ((I Shl 24) Shr 24) ' (I & $FF)
End

' This converts an "address" (Real offset) to an index with a 2-byte stride.
Function ToShortArrayIndex:UInt(Address:UInt)
	Return (Address / SizeOf_Short)
End

' This converts an "address" (Real offset) to an index with a 4-byte stride.
Function ToIntArrayIndex:UInt(Address:UInt)
	Return (Address / SizeOf_Integer)
End

' This converts a 2-byte stride into bytes.
Function FromShortArrayIndex:UInt(Index:UInt)
	Return (Index * SizeOf_Short)
End

' This converts a 4-byte stride into bytes.
Function FromIntArrayIndex:Uint(Index:UInt)
	Return (Index * SizeOf_Integer)
End

' This command is useful when dealing with arrays.
Function OutOfBounds:Bool(Position:UInt, Length:UInt)
	Return (Position >= Length)
End

' This performs a transfer operation from 'InputStream' to
' 'OutputStream', using a block of memory of size 'DataSize'.
Function Transfer:Void(InputStream:Stream, OutputStream:Stream, DataSize:UInt)
	' Check for errors:
	#If Not MONKEYLANG_EXTENSION_TYPE_UNISGNED_INT
		If (DataSize <= 0) Then
			Throw New StreamTransferException(Null, DataSize)
		Endif
	#End

	If (InputStream = Null Or OutputStream = Null) Then
		Throw New StreamUnavailableException()
	End

	' Local variable(s):
	#If UTIL_TEMP_BUFFERS
		Local Data:DataBuffer = New DataBuffer(DataSize)

		If (Data = Null) Then ' Data.Length <> DataSize
			Throw New BulkAllocationException<DataBuffer>(Data, DataSize)
		Endif

		Local DataLength:= DataSize ' Data.Length

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

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

		' This is terrible, but it's our only option without temporary buffers.
		For Local I:= 1 To DataSize ' Data.Length
			OutputStream.WriteByte(InputStream.ReadByte())
		Next
	#End

	Return
End

Function ResizeBuffer:DataBuffer(Buffer:DataBuffer, Size:Long=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

Function SetBuffer:Void(Output:DataBuffer, Value:Byte, Count:UInt, Offset:UInt=0)
	For Local I:= Offset Until (Count + Offset)
		Output.PokeByte(I, Value)
	Next

	Return
End

Function SetBuffer:Void(Output:DataBuffer, Value:Byte, Offset:UInt=0)
	SetBuffer(Output, Value, Output.Length - Offset, Offset)

	Return
End

' This writes a 16-bit integer at the "index" specified using the input-value.
' The index specified has a stride of 2 bytes.
Function ArraySetShort:Void(Output:DataBuffer, Index:UInt, Value:UShort, Offset:UInt=0)
	Output.PokeShort(Offset + FromShortArrayIndex(Index), Short(Value & $FFFF))

	Return
End

' This writes a 32-bit integer at the "index" specified using the input-value.
' The index specified has a stride of 4 bytes.
Function ArraySetInt:Void(Output:DataBuffer, Index:UInt, Value:UInt, Offset:UInt=0)
	Output.PokeInt(Offset + FromIntArrayIndex(Index), Int(Value & $FFFFFFFF))

	Return
End

' This reads a 16-bit integer at the "index" specified.
' The index specified has a stride of 2 bytes.
Function ArrayGetShort:UShort(Input:DataBuffer, Index:UInt, Offset:UInt=0)
	Return (Input.PeekShort(Offset + FromShortArrayIndex(Index)) & $FFFF)
End

' This reads a 32-bit integer at the "index" specified.
' The index specified has a stride of 4 bytes.
Function ArrayGetInt:UInt(Input:DataBuffer, Index:UInt, Offset:UInt=0)
	Return (Input.PeekInt(Offset + FromIntArrayIndex(Index)) & $FFFFFFFF)
End

Function SetBufferBytes:Void(Output:DataBuffer, Bytes:Byte[], Bytes_Length:UInt, Bytes_Offset:UInt=0, Offset:UInt=0)
	For Local I:= 0 Until Bytes_Length
		Output.PokeByte((I + Offset), (Bytes[I + Bytes_Offset] & $FF)) ' (I * SizeOf_Byte)
	Next

	Return
End

Function SetBufferBytes:Void(Output:DataBuffer, Bytes:Byte[], Offset:UInt=0)
	SetBytes(Output, Bytes, Bytes.Length, 0, Offset)

	Return
End

Function SetBufferShorts:Void(Output:DataBuffer, Shorts:Short[], Shorts_Length:UInt, Shorts_Offset:UInt=0, Offset:UInt=0)
	For Local I:= 0 Until Shorts_Length
		Output.PokeShort(((I * SizeOf_Short) + Offset), (Shorts[I + Shorts_Offset] & $FFFF))
	Next

	Return
End

Function SetBufferShorts:Void(Output:DataBuffer, Shorts:Short[], Offset:UInt=0)
	SetShorts(Output, Shorts, Shorts.Length, 0, Offset)

	Return
End

Function SetBufferInts:Void(Output:DataBuffer, Ints:Int[], Ints_Length:UInt, Ints_Offset:UInt=0, Offset:UInt=0)
	For Local I:= 0 Until Ints_Length
		Output.PokeInt(((I * SizeOf_Integer) + Offset), (Ints[I + Ints_Offset] & $FFFFFFFF))
	Next

	Return
End

Function SetBufferInts:Void(Output:DataBuffer, Ints:Int[], Offset:UInt=0)
	SetInts(Output, Ints, Ints.Length, 0, Offset)

	Return
End