Default reflection filter

Default reflection filter

#REFLECTION_FILTER += "flixel.flx*|flixel.plugin*"

#FLX_WEBGL_ENABLED  =False


Fixed target dependency

Fixed target dependency

Strict

#If TARGET="android" Or TARGET="flash" Or TARGET="glfw" Or TARGET="html5" Or TARGET="ios" Or TARGET="psm" Or TARGET="win8" Or TARGET="xna" Or TARGET="bmax"
	Import "native/flixel.${TARGET}.${LANG}"
	#FLX_NATIVE_IMPLEMENTED = True
#End

#FLX_NATIVE_IMPLEMENTED = False

#If TARGET = "html5"
	#If FLX_WEBGL_ENABLED = "1"
		Import "native/webgl/mojo.${TARGET}.gl.min.${LANG}"
	#End
#End

Extern

#If FLX_NATIVE_IMPLEMENTED = "1"
	#If LANG="cpp"
		Function FlxIsMobile:Bool() = "flixel::isMobile"
	#ElseIf TARGET = "xna" Or TARGET = "psm"
		Function FlxIsMobile:Bool() = "flixel.functions.isMobile"
	#Else
		Function FlxIsMobile:Bool() = "flixel.isMobile"
	#End

	#If TARGET = "xna" Or TARGET = "psm"
		Function FlxOpenURL:Void(url:String) = "flixel.functions.openURL"
	#End
#End

#If TARGET = "html5"
	Function FlxIsIE:Bool() = "flixel.isIE"
#End

Public

#If FLX_NATIVE_IMPLEMENTED = "0"
	Function FlxIsMobile:Bool()
		Return False
	End Function
#End

Strict

#If TARGET="android" Or TARGET="flash" Or TARGET="glfw" Or TARGET="html5" Or TARGET="ios" Or TARGET="psm" Or TARGET="win8" Or TARGET="xna" Or TARGET="bmax"
	Import "native/flixel.${TARGET}.${LANG}"
	#FLX_NATIVE_IMPLEMENTED = True
#End

#FLX_NATIVE_IMPLEMENTED = False

#If TARGET = "html5"
	#If FLX_WEBGL_ENABLED = "1"
		Import "native/webgl/mojo.${TARGET}.gl.min.${LANG}"
	#End
#End

Extern

#If LANG="cpp"
	Function FlxIsMobile:Bool() = "flixel::isMobile"
#ElseIf TARGET = "xna" Or TARGET = "psm"
	Function FlxIsMobile:Bool() = "flixel.functions.isMobile"
#Else
	Function FlxIsMobile:Bool() = "flixel.isMobile"
#End

#If TARGET = "xna" Or TARGET = "psm"
	Function FlxOpenURL:Void(url:String) = "flixel.functions.openURL"
#End

#If TARGET = "html5"
	Function FlxIsIE:Bool() = "flixel.isIE"
#End

Public

#If FLX_NATIVE_IMPLEMENTED = "0" Then
	Function FlxIsMobile:Bool()
		Return False
	End Function
#End


Added extra preprocessor flags to 'bufferview'.

Strict

Public

#Rem
	TODO:
		* Replace uses of 'Int' and 'Float' with 'Long' and 'Double'.
			('LongArrayView', 'DoubleArrayView', etc)
#End

' Preprocessor related:
#REGAL_UTIL_BUFFERVIEW = True

#REGAL_UTIL_BUFFERVIEW_BYTE_OPTIMIZATIONS = True

'#If CONFIG = "debug"
	'#REGAL_UTIL_BUFFERVIEW_SAFE = True
'#End

#If CONFIG = "debug"
	'#REGAL_UTIL_BUFFERVIEW_STOP_ON_EXCEPTION = True
#End

'#REGAL_UTIL_BUFFERVIEW_NO_UNSIGNED = True

' Imports (Public):
Import brl.databuffer

' Imports (Private):
Private

Import memory

Import regal.sizeof
Import regal.typetool

Import monkey.math

Public

' Interfaces:
Interface BufferView
	' Constant variable(s):
	Const MAX_VIEW_ELEMENTS:= 0 ' -1

	' Methods:
	' Nothing so far.

	' Properties:
	Method Data:DataBuffer() Property
	Method Offset:UInt() Property ' Int
End

Interface ElementView Extends BufferView
	' Methods:

	' This converts 'Index' into a "raw address";
	' used for internal memory operations.
	' For details, view the 'ArrayView.OffsetIndexToAddress' command.
	Method IndexToRawAddress:UInt(Index:UInt)

	' Properties:

	' This supplies the raw size of this view.
	' For details, view the 'ArrayView.Size' property.
	Method Size:UInt() Property ' Int

	' This specifies the size of each element in this view.
	Method ElementSize:UInt() Property ' Int
End

' Classes:
Class ArrayView<ValueType> Implements ElementView Abstract ' BufferView
	' Constant variable(s) (Public):
	Const MAX_VIEW_ELEMENTS:= BufferView.MAX_VIEW_ELEMENTS

	' Global variable(s) (Protected):
	Protected

	Global NIL:ValueType

	Public

	' Constructor(s) (Public):

	#Rem
		NOTES:
			* The 'ElementCount' argument(s) is/are bound by the amount of memory given to the view.
				This means the segment of a buffer that you intend to map must be at least the
				length you specify, scaled according to the requested size for each element.

				An invalid size will result in an exception.
	#End

	Method New(ElementSize:UInt, ElementCount:UInt, __Direct:Bool=False)
		Self.ElementSize = ElementSize

		InitializeCustomBuffer(ElementSize, ElementCount, __Direct)
	End

	Method New(ElementSize:UInt, Data:DataBuffer, OffsetInBytes:UInt=0, ElementCount:UInt=MAX_VIEW_ELEMENTS)
		Self.Offset = OffsetInBytes
		Self.ElementSize = ElementSize
		Self.Data = Data

		Self.Size = GetSize(Data, ElementSize, ElementCount)
	End

	' The 'ExtraOffset' argument is used to offset from the 'View' object's offset.
	Method New(ElementSize:UInt, View:BufferView, ElementCount:UInt=MAX_VIEW_ELEMENTS, ExtraOffset:UInt=0)
		Self.ElementSize = ElementSize

		Self.Offset = (View.Offset + ExtraOffset)

		Self.Data = View.Data

		Self.Size = GetSize(Self.Data, ElementSize, ElementCount)
	End

	' Constructor(s) (Private):
	Private

	Method GetSize:UInt(Data:DataBuffer, ElementSize:UInt, ElementCount:UInt=MAX_VIEW_ELEMENTS)
		If (ElementCount = MAX_VIEW_ELEMENTS) Then
			Return Data.Length
		Endif

		Local IntendedSize:= (ElementCount * ElementSize) ' CountInBytes(ElementCount)

		' Make sure the intended size is correct.
		If (IntendedSize < ElementSize Or IntendedSize > Data.Length) Then
			#If REGAL_UTIL_BUFFERVIEW_STOP_ON_EXCEPTION
				DebugStop()
			#End

			' The intended size is either too large, or too small.
			Throw New InvalidViewMappingOperation(Self, Offset, IntendedSize)
		Endif

		Return IntendedSize
	End

	' NOTE: It is considered unsafe to call this constructor before assigning a value to the 'ElementSize' property.
	Method InitializeCustomBuffer:Void(ElementSize:UInt, ElementCount:UInt, __Direct:Bool=False) Final
		If (ElementSize = 0 Or ElementCount = 0) Then
			#If REGAL_UTIL_BUFFERVIEW_STOP_ON_EXCEPTION
				DebugStop()
			#End

			Throw New BulkAllocationException<BufferView>(Self, 0) ' IntendedSize
		Endif

		Local IntendedSize:= (ElementCount * ElementSize)

		Self.Data = New DataBuffer(IntendedSize, __Direct) ' CountInBytes(ElementCount)

		Self.Offset = 0
		Self.Size = Self.Data.Length
	End

	Public

	' Methods (Public):

	' If overridden, these methods must respect the 'Offset' property:
	Method Get:ValueType(Index:UInt)
		Return GetRaw(Offset + IndexToAddress(Index))
	End

	Method Set:Void(Index:UInt, Value:ValueType)
		SetRaw(Offset + IndexToAddress(Index), Value)

		Return
	End

	' This performs a raw memory transfer/copy from this view to 'Output'.
	' This means the output is not casted, but rather a mapped copy of the data.
	Method Transfer:Bool(InputIndex:UInt, Output:ElementView, OutputIndex:Int, Count:UInt) ' ArrayView
		Return ArrayViewOperation<ArrayView, ElementView>.Transfer(Self, InputIndex, Output, OutputIndex, Count) ' ArrayView<ValueType>
	End

	' This performs an element-level transfer/copy from 'Input' to this view.
	' This means that each element is casted from their source type/size to the destination type/size.
	Method Copy:Bool(Index:UInt, Input:ArrayView, InputIndex:Int, Count:UInt) ' ArrayView<ValueType>
		Return ArrayViewOperation<ArrayView, ArrayView>.Copy(Input, InputIndex, Self, Index, Count) ' ArrayView<ValueType>
	End

	Method Copy:Bool(Index:UInt, Input:ArrayView, InputIndex:Int=0)
		Return Copy(Index, Input, InputIndex, Min(Self.Length, Input.Length))
	End

	Method Copy:Bool(Input:ArrayView)
		Return Copy(0, Input, 0)
	End

	' This returns 'False' if the bounds specified are considered invalid.
	Method GetArray:Bool(Index:UInt, Output:ValueType[], Count:UInt, OutputOffset:UInt=0)
		' Calculate the end-point we'll be reaching.
		Local ByteBounds:= OffsetIndexToAddress(Index+Count)

		' Make sure the end-point fits within our buffer-segment.
		If (ByteBounds > Size) Then
			Return False
		Endif

		' This will be used to store our current write-location in 'Output'.
		Local OutputPosition:= OutputOffset

		' The current raw address in the internal buffer.
		Local Address:= OffsetIndexToAddress(Index)

		' Continue until we've reached our described bounds.
		While (Address < ByteBounds)
			' Copy the value located at 'Address' into the output.
			Output[OutputPosition] = GetRaw_Unsafe(Address)

			' Move to the next target-location for the output-data.
			OutputPosition += 1

			' Move forward by one entry.
			Address += ElementSize
		Wend

		' Return the default response.
		Return True
	End

	Method GetArray:ValueType[](Index:UInt, Count:UInt, _ArrOff:UInt=0)
		Local Output:= New ValueType[_ArrOff + Count]

		If (Not GetArray(Index, Output, Count, _ArrOff)) Then
			Return []
		Endif

		Return Output
	End

	Method GetArray:ValueType[]()
		Return GetArray(0, Length)
	End

	' This returns 'False' if the bounds specified are considered invalid.
	Method SetArray:Bool(Index:UInt, Input:ValueType[], Count:UInt, InputOffset:UInt=0)
		' Calculate the end-point we'll be reaching.
		Local ByteBounds:= OffsetIndexToAddress(Index+Count)

		' Make sure the end-point fits within our buffer-segment.
		If (ByteBounds > Size) Then
			Return False
		Endif

		' This will store our current position in the 'Input' array.
		Local InputPosition:= InputOffset

		' The current raw address in the internal buffer.
		Local Address:= OffsetIndexToAddress(Index)

		' The amount 'Address' will move by on each iteration.
		Local Stride:= ElementSize

		' Continue until we've reached our described bounds.
		While (Address < ByteBounds)
			' Write a value at the current address using an entry from the input-data.
			SetRaw_Unsafe(Address, Input[InputPosition])

			' Move to the next entry in the input-data.
			InputPosition += 1

			' Move forward by one entry.
			Address += Stride
		Wend

		' Return the default response.
		Return True
	End

	Method SetArray:Bool(Index:UInt, Input:ValueType[])
		Return SetArray(Index, Input, Input.Length)
	End

	' TODO: Optimize this overload to bypass index conversion.
	Method SetArray:Bool(Input:ValueType[])
		Return SetArray(0, Input)
	End

	' This returns 'False' if the bounds specified are considered invalid.
	Method Clear:Bool(Index:UInt, Count:UInt, Value:ValueType)
		' Calculate the end-point we'll be reaching.
		Local ByteBounds:= OffsetIndexToAddress(Index+Count)

		' Make sure the end-point fits within our buffer-segment.
		If (ByteBounds > ViewBounds) Then
			Return False
		Endif

		' The current raw address in the internal buffer.
		Local Address:= OffsetIndexToAddress(Index)

		' The amount 'Address' will move by on each iteration.
		Local Stride:= ElementSize

		' Continue until we've reached our described bounds.
		While (Address < ByteBounds)
			' Clear an entry at our current location in the buffer.
			SetRaw(Address, Value)

			' Move forward by one entry.
			Address += Stride
		Wend

		' Return the default response.
		Return True
	End

	' This calls 'Clear' using the value of 'NIL'.
	Method Clear:Bool(Index:UInt, Count:UInt)
		Return Clear(Index, Count, NIL)
	End

	' This clears the entire view using the value specified.
	Method Clear:Bool(Value:ValueType)
		Return Clear(0, Length, Value)
	End

	' TODO: Optimize this overload to bypass either index conversion or standard assignment.
	Method Clear:Bool()
		Return Clear(NIL)
	End

	Method Add:ValueType(Index:UInt, Value:ValueType)
		Local Result:= (Get(Index) + Value)

		Set(Index, Result)

		Return Result
	End

	Method Subtract:ValueType(Index:UInt, Value:ValueType)
		Return Add(Index, -Value)
	End

	' This supplies the raw size of 'Count' elements in bytes.
	Method CountInBytes:UInt(Count:Int)
		Return IndexToAddress(Count) ' (Count * ElementSize)
	End

	' This converts an index to a raw address for use with the internal buffer.
	Method IndexToAddress:UInt(Index:UInt)
		#If REGAL_UTIL_BUFFERVIEW_BYTE_OPTIMIZATIONS
			If (ElementSize = 1) Then
				Return Index
			Endif
		#End

		Return (Index * ElementSize)
	End

	' This converts a raw address to an index.
	Method AddressToIndex:UInt(Address:UInt)
		#If REGAL_UTIL_BUFFERVIEW_BYTE_OPTIMIZATIONS
			If (ElementSize = 1) Then
				Return Address
			Endif
		#End

		Return (Address / ElementSize)
	End

	#Rem
		The result of this method is a non-convertible raw address.
		By definition, this address may not be used with commands like
		'AddressToIndex', as the value would be skewed.

		To fix this address for such commands, subtract a stored result gathered
		from the 'Offset' property at the time this method was called.

		Because the value of 'Offset' can be changed, you must always ensure that
		the offset you apply to restore the appropriate value corresponds with the
		original value associated with this object's 'Offset' property.

		This type of address manipulation is not recommended,
		and should be avoided wherever possible.
	#End

	Method OffsetIndexToAddress:UInt(Index:UInt) Final
		Return (IndexToAddress(Index) + Offset)
	End

	' This method is an extension, which should only be used when converting
	' a value from a real address to a convertible address.
	' This command is not recommended, and is subject to deletion.
	Method __OffsetAddressToIndex:UInt(_Address:UInt) Final
		Return AddressToIndex(_Address - Offset)
	End

	' Methods (Protected):
	Protected

	' Abstract:

	' These two methods operate on raw addresses.
	' This means the input should not be an index,
	' nor should it be a non-offset address.
	' Implementations should not bother with out-of-bounds checks.
	Method GetRaw_Unsafe:ValueType(RawAddress:UInt) Abstract
	Method SetRaw_Unsafe:Void(RawAddress:UInt, Value:ValueType) Abstract

	' Implemented:

	' This method wraps 'OffsetIndexToAddress' for compatibility with the 'ElementView' interface.
	Method IndexToRawAddress:UInt(Index:UInt) Final
		Return OffsetIndexToAddress(Index)
	End

	Method SetRaw:Void(Address:UInt, Value:ValueType) Final
		Local ElementSize:= Self.ElementSize

		If ((Address + ElementSize) > ViewBounds) Then
			#If REGAL_UTIL_BUFFERVIEW_STOP_ON_EXCEPTION
				DebugStop()
			#End

			Throw New InvalidViewWriteOperation(Self, Address, ElementSize)
		Endif

		SetRaw_Unsafe(Address, Value)

		Return
	End

	Method GetRaw:ValueType(Address:UInt) Final
		Local ElementSize:= Self.ElementSize

		If ((Address + ElementSize) > ViewBounds) Then
			#If REGAL_UTIL_BUFFERVIEW_STOP_ON_EXCEPTION
				DebugStop()
			#End

			Throw New InvalidViewReadOperation(Self, Address, ElementSize)
		Endif

		Return GetRaw_Unsafe(Address)
	End

	Public

	' Properties (Public):

	' This provides the number of elements in this view.
	Method Length:UInt() Property
		#If REGAL_UTIL_BUFFERVIEW_BYTE_OPTIMIZATIONS
			If (ElementSize = 1) Then
				Return Size
			Endif
		#End

		Return (Size / ElementSize)
	End

	' This describes the address of the absolute furthest into the internal buffer this view reaches.
	' This is mainly useful for raw bounds checks that already account for offsets.
	' For a good example of this, view the 'GetArray' command's implementation(s).
	Method ViewBounds:UInt() Property
		Return (Size + Offset)
	End

	' This returns the raw size of the internal buffer area (In bytes), without adjusting for offsets.
	' This is useful when the literal size (In bytes) of this view is required.
	Method Size:UInt() Property ' Int
		Return Self._Size ' UInt(Data.Length)
	End

	' This specifies the size of an element.
	Method ElementSize:UInt() Property
		Return Self._ElementSize
	End

	' This provides access to the internal buffer-offset.
	' Note: This is already accounted for when calculating 'Size'.
	Method Offset:UInt() Property ' Int
		Return Self._Offset
	End

	Method Offset:Void(Value:UInt) Property
		Self._Offset = Value

		#If REGAL_UTIL_BUFFERVIEW_SAFE
			' Nothing so far.
		#End

		Return
	End

	' This provides access to the internal buffer.
	Method Data:DataBuffer() Property ' Final
		Return Self._Data
	End

	' Properties (Protected):
	Protected

	Method Size:Void(Value:UInt) Property
		Self._Size = Value

		Return
	End

	Method Data:Void(Value:DataBuffer) Property
		Self._Data = Value

		Return
	End

	Method ElementSize:Void(Value:UInt) Property
		Self._ElementSize = Value

		Return
	End

	Public

	' Fields (Protected):
	Protected

	Field _ElementSize:UInt ' Int
	Field _Offset:UInt ' Int
	Field _Size:UInt ' Int
	Field _Data:DataBuffer

	Public
End

' This is an intermediate class which defines mathematical routines for both integral and floating-point types.
Class MathArrayView<ValueType> Extends ArrayView<ValueType> Abstract
	' Constructor(s):
	Method New(ElementSize:UInt, ElementCount:UInt, __Direct:Bool=False)
		Super.New(ElementSize, ElementCount, __Direct)
	End

	Method New(ElementSize:UInt, Data:DataBuffer, OffsetInBytes:UInt=0, ElementCount:UInt=MAX_VIEW_ELEMENTS)
		Super.New(ElementSize, Data, OffsetInBytes, ElementCount)
	End

	Method New(ElementSize:UInt, View:BufferView, ElementCount:UInt=MAX_VIEW_ELEMENTS, ExtraOffset:UInt=0)
		Super.New(ElementSize, View, ElementCount, ExtraOffset)
	End

	' Methods:

	' This increments the value located at 'Index' by one.
	Method Increment:ValueType(Index:UInt)
		Return Add(Index, ValueType(1))
	End

	' This decrements the value located at 'Index' by one.
	Method Decrement:ValueType(Index:UInt)
		Return Subtract(Index, ValueType(1))
	End

	' This multiplies the value located at 'Index' using the value specified.
	' The result is written into memory, then returned.
	Method Multiply:ValueType(Index:UInt, Value:ValueType)
		Local Result:= (Get(Index) * Value)

		Set(Index, Result)

		Return Result
	End

	' This divides the value located at 'Index' using the value specified.
	' The result is written into memory, then returned.
	Method Divide:ValueType(Index:UInt, Value:ValueType)
		Local Result:= (Get(Index) / Value)

		Set(Index, Result)

		Return Result
	End

	' This squares the value located at 'Index'.
	' The result is both returned by the method, and
	' written into memory at the specified location.
	Method Sq:ValueType(Index:UInt) ' Square
		Local Value:= Get(Index)
		Local Result:= (Value * Value)

		Set(Index, Result)

		Return Result
	End

	' This calculates the square-root of the value located at 'Index'.
	' The result is both returned by this method, and
	' written into memory at the specified location.
	Method Sqrt:ValueType(Index:UInt) ' SquareRoot
		Local Result:= Sqrt(Get(Index))

		Set(Index, Result)

		Return Result
	End
End

Class IntArrayView Extends MathArrayView<Int> ' ArrayView<Long> ' Int ' LongArrayView
	' Constant variable(s):
	Const Type_Size:= SizeOf_Integer ' 4

	' Constructor(s) (Public):
	Method New(Count:UInt, __Direct:Bool=False)
		Super.New(Type_Size, Count, __Direct)
	End

	Method New(Data:DataBuffer, OffsetInBytes:UInt=0, ElementCount:UInt=MAX_VIEW_ELEMENTS)
		Super.New(Type_Size, Data, OffsetInBytes, ElementCount)
	End

	Method New(View:BufferView, ElementCount:UInt=MAX_VIEW_ELEMENTS, ExtraOffset:UInt=0)
		Super.New(Type_Size, View, ElementCount, ExtraOffset)
	End

	' Constructor(s) (Protected):
	Protected

	Method New(Type_Size:UInt, ElementCount:UInt, __Direct:Bool=False)
		Super.New(Type_Size, ElementCount, __Direct)
	End

	Method New(Type_Size:UInt, Data:DataBuffer, OffsetInBytes:UInt=0, ElementCount:UInt=MAX_VIEW_ELEMENTS)
		Super.New(Type_Size, Data, OffsetInBytes, ElementCount)
	End

	Method New(Type_Size:UInt, View:BufferView, ElementCount:UInt=MAX_VIEW_ELEMENTS, ExtraOffset:UInt=0)
		Super.New(Type_Size, View, ElementCount, ExtraOffset)
	End

	Public

	' Methods (Public):
	Method GetUnsigned:Int(Index:UInt)
		#If Not REGAL_UTIL_BUFFERVIEW_NO_UNSIGNED
			Return (Get(Index) & $FFFFFFFF)
		#Else
			Return Get(Index)
		#End
	End

	Method SetUnsigned:Void(Index:UInt, Value:Int)
		Set(Index, (Value & $FFFFFFFF))

		Return
	End

	' Methods (Protected):
	Protected

	Method GetRaw_Unsafe:Int(Address:UInt) ' Final
		Return Data.PeekInt(Address)
	End

	Method SetRaw_Unsafe:Void(Address:UInt, Value:Int) ' Final
		Data.PokeInt(Address, Value)

		Return
	End

	Public
End

Class ShortArrayView Extends IntArrayView ' ArrayView<Int> ' Short
	' Constant variable(s):
	Const Type_Size:= SizeOf_Short

	' Constructor(s) (Public):
	Method New(Count:UInt, __Direct:Bool=False)
		Super.New(Type_Size, Count, __Direct)
	End

	Method New(Data:DataBuffer, OffsetInBytes:UInt=0, ElementCount:UInt=MAX_VIEW_ELEMENTS)
		Super.New(Type_Size, Data, OffsetInBytes, ElementCount)
	End

	Method New(View:BufferView, ElementCount:UInt=MAX_VIEW_ELEMENTS, ExtraOffset:UInt=0)
		Super.New(Type_Size, View, ElementCount, ExtraOffset)
	End

	' Constructor(s) (Protected):
	Protected

	Method New(Type_Size:UInt, ElementCount:UInt, __Direct:Bool=False)
		Super.New(Type_Size, ElementCount, __Direct)
	End

	Method New(Type_Size:UInt, Data:DataBuffer, OffsetInBytes:UInt=0, ElementCount:UInt=MAX_VIEW_ELEMENTS)
		Super.New(Type_Size, Data, OffsetInBytes, ElementCount)
	End

	Method New(Type_Size:UInt, View:BufferView, ElementCount:UInt=MAX_VIEW_ELEMENTS, ExtraOffset:UInt=0)
		Super.New(Type_Size, View, ElementCount, ExtraOffset)
	End

	Public

	' Methods (Public):
	Method GetUnsigned:Int(Index:UInt) ' Short
		#If Not REGAL_UTIL_BUFFERVIEW_NO_UNSIGNED
			Return (Get(Index) & $FFFF)
		#Else
			Return Get(Index)
		#End
	End

	Method SetUnsigned:Void(Index:UInt, Value:Int) ' Short
		Set(Index, (Value & $FFFF))

		Return
	End

	' Methods (Protected):
	Protected

	Method GetRaw_Unsafe:Int(Address:UInt) ' Final ' Short
		Return Data.PeekShort(Address)
	End

	Method SetRaw_Unsafe:Void(Address:UInt, Value:Int) ' Final ' Short
		Data.PokeShort(Address, Value)

		Return
	End

	Public
End

Class ByteArrayView Extends ShortArrayView ' ArrayView<Int> ' Byte
	' Constant variable(s):
	Const Type_Size:= SizeOf_Byte

	' Constructor(s):
	Method New(Count:UInt, __Direct:Bool=False)
		Super.New(Type_Size, Count, __Direct)
	End

	Method New(Data:DataBuffer, OffsetInBytes:UInt=0, ElementCount:UInt=MAX_VIEW_ELEMENTS)
		Super.New(Type_Size, Data, OffsetInBytes, ElementCount)
	End

	Method New(View:BufferView, ElementCount:UInt=MAX_VIEW_ELEMENTS, ExtraOffset:UInt=0)
		Super.New(Type_Size, View, ElementCount, ExtraOffset)
	End

	' Methods (Public):
	#If REGAL_UTIL_BUFFERVIEW_BYTE_OPTIMIZATIONS
		' These two methods follow the integrity rules of 'Offset':
		Method Get:Int(Address:UInt) ' Byte
			Return GetRaw(Offset + Address)
		End

		Method Set:Void(Address:UInt, Value:Int) ' Byte
			SetRaw(Offset + Address, Value)

			Return
		End

		#Rem
			Method IndexToAddress:UInt(Address:UInt) ' Index:UInt
				Return Address
			End

			Method AddressToIndex:UInt(Address:UInt)
				Return Address
			End
		#End
	#End

	Method GetUnsigned:Int(Address:UInt) ' Byte
		#If Not REGAL_UTIL_BUFFERVIEW_NO_UNSIGNED
			Return (Get(Address) & $FF)
		#Else
			Return Get(Address)
		#End
	End

	Method SetUnsigned:Void(Index:UInt, Value:Int) ' Byte
		Set(Index, (Value & $FF))

		Return
	End

	' Methods (Protected):
	Protected

	Method GetRaw_Unsafe:Int(Address:UInt) ' Final ' Byte
		Return Data.PeekByte(Address)
	End

	Method SetRaw_Unsafe:Void(Address:UInt, Value:Int) ' Final ' Byte
		Data.PokeByte(Address, Value)

		Return
	End

	Public
End

Class FloatArrayView Extends MathArrayView<Float> ' DoubleArrayView
	' Constant variable(s):
	Const Type_Size:= SizeOf_Float ' 4 ' 8

	' Constructor(s):
	Method New(Count:UInt, __Direct:Bool=False)
		Super.New(Type_Size, Count, __Direct)
	End

	Method New(Data:DataBuffer, OffsetInBytes:UInt=0, ElementCount:UInt=MAX_VIEW_ELEMENTS)
		Super.New(Type_Size, Data, OffsetInBytes, ElementCount)
	End

	Method New(View:BufferView, ElementCount:UInt=MAX_VIEW_ELEMENTS, ExtraOffset:UInt=0)
		Super.New(Type_Size, View, ElementCount, ExtraOffset)
	End

	' Methods (Protected):
	Protected

	Method GetRaw_Unsafe:Float(Address:UInt) ' Final ' Double
		Return Data.PeekFloat(Address)
	End

	Method SetRaw_Unsafe:Void(Address:UInt, Value:Float) ' Final ' Double
		Data.PokeFloat(Address, Value)

		Return
	End

	Public
End

' This class contains generic utilities for 'ArrayView' objects.
Class ArrayViewOperation<A, B> Abstract
	#Rem
		This performs a raw memory copy from one view to another.

		Address translations are performed before copy-operations
		take place, and are checked accordingly.

		The 'Count' argument specifies the number of elements to be copied from 'Input'.

		If preliminary bounds checks fail, this command will return 'False'.
	#End

	Function Transfer:Bool(Input:A, InputIndex:UInt, Output:B, OutputIndex:Int, Count:UInt) ' ArrayView ' ElementView
		' Get the appropriate element size.
		Local ElementSize:= Input.ElementSize ' Min(Input.ElementSize, Output.ElementSize)
		Local BytesToTransfer:= (ElementSize * Count)

		' Calculate the end-points we'll be reaching:
		Local InByteBounds:= Input.IndexToRawAddress(InputIndex + Count)
		Local OutByteBounds:= Output.IndexToRawAddress(OutputIndex) + BytesToTransfer ' Output.IndexToRawAddress(OutputIndex + Count)

		' Make sure the end-points fit within our buffer segments:
		If (InByteBounds > Input.Size Or OutByteBounds > Output.Size) Then
			Return False
		Endif

		' The starting raw address in the output buffer.
		Local OutputAddress:= Output.IndexToRawAddress(OutputIndex)

		' The starting raw address in the input buffer.
		Local InputAddress:= Input.IndexToRawAddress(InputIndex)

		' Perform a raw memory copy from 'Input.Data' to 'Output.Data'.
		Input.Data.CopyBytes(InputAddress, Output.Data, OutputAddress, BytesToTransfer)

		' Return the default response.
		Return True
	End

	' This performs an element-level copy from one view to another.
	' If preliminary bounds checks fail, this command will return 'False'.
	Function Copy:Bool(Input:A, InputIndex:UInt, Output:B, OutputIndex:Int, Count:UInt) ' ArrayView ' ElementView
		' Calculate the appropriate element size.
		Local InElementSize:= Input.ElementSize
		Local OutElementSize:= Output.ElementSize

		' Calculate the end-points we'll be reaching:
		Local InByteBounds:= Input.IndexToRawAddress(InputIndex + Count)
		Local OutByteBounds:= Output.IndexToRawAddress(OutputIndex + Count)

		' Make sure the end-points fit within our buffer segments:
		If (InByteBounds > Input.Size Or OutByteBounds > Output.Size) Then
			Return False
		Endif

		' The starting raw address in the output buffer.
		Local OutputAddress:= Output.IndexToRawAddress(OutputIndex)

		' The starting raw address in the input buffer.
		Local InputAddress:= Input.IndexToRawAddress(InputIndex)

		' Continue until we've reached our described bounds:
		While (InputAddress < InByteBounds)
			#If CONFIG = "debug"
				If (OutputAddress >= OutByteBounds) Then
					Exit
				Endif
			#End

			' Copy the value located at 'InputAddress' into the output at 'OutputAddress'.
			Output.SetRaw_Unsafe(OutputAddress, Input.GetRaw_Unsafe(InputAddress))

			' Move forward by one entry on each address:
			InputAddress += InElementSize
			OutputAddress += OutElementSize
		Wend

		' Return the default response.
		Return True
	End

	' Constructor(s) (Private):
	Private

	Method New() ' Final
		' This constructor is reserved.
	End

	Public
End

Class ElementViewOperation Extends ArrayViewOperation<ElementView, ElementView>
	' Nothing so far.
End

Strict

Public

#Rem
	TODO:
		* Replace uses of 'Int' and 'Float' with 'Long' and 'Double'.
			('LongArrayView', 'DoubleArrayView', etc)
#End

' Preprocessor related:
#REGAL_UTIL_BUFFERVIEW = True

#REGAL_UTIL_BUFFERVIEW_BYTE_OPTIMIZATIONS = True

'#If CONFIG = "debug"
	'#REGAL_UTIL_BUFFERVIEW_SAFE = True
'#End

' Imports (Public):
Import brl.databuffer

' Imports (Private):
Private

Import memory

Import regal.sizeof
Import regal.typetool

Import monkey.math

Public

' Interfaces:
Interface BufferView
	' Constant variable(s):
	Const MAX_VIEW_ELEMENTS:= 0 ' -1

	' Methods:
	' Nothing so far.

	' Properties:
	Method Data:DataBuffer() Property
	Method Offset:UInt() Property ' Int
End

Interface ElementView Extends BufferView
	' Methods:

	' This converts 'Index' into a "raw address";
	' used for internal memory operations.
	' For details, view the 'ArrayView.OffsetIndexToAddress' command.
	Method IndexToRawAddress:UInt(Index:UInt)

	' Properties:

	' This supplies the raw size of this view.
	' For details, view the 'ArrayView.Size' property.
	Method Size:UInt() Property ' Int

	' This specifies the size of each element in this view.
	Method ElementSize:UInt() Property ' Int
End

' Classes:
Class ArrayView<ValueType> Implements ElementView Abstract ' BufferView
	' Constant variable(s) (Public):
	Const MAX_VIEW_ELEMENTS:= BufferView.MAX_VIEW_ELEMENTS

	' Global variable(s) (Protected):
	Protected

	Global NIL:ValueType

	Public

	' Constructor(s) (Public):

	#Rem
		NOTES:
			* The 'ElementCount' argument(s) is/are bound by the amount of memory given to the view.
				This means the segment of a buffer that you intend to map must be at least the
				length you specify, scaled according to the requested size for each element.

				An invalid size will result in an exception.
	#End

	Method New(ElementSize:UInt, ElementCount:UInt, __Direct:Bool=False)
		Self.ElementSize = ElementSize

		InitializeCustomBuffer(ElementSize, ElementCount, __Direct)
	End

	Method New(ElementSize:UInt, Data:DataBuffer, OffsetInBytes:UInt=0, ElementCount:UInt=MAX_VIEW_ELEMENTS)
		Self.Offset = OffsetInBytes
		Self.ElementSize = ElementSize
		Self.Data = Data

		Self.Size = GetSize(Data, ElementSize, ElementCount)
	End

	' The 'ExtraOffset' argument is used to offset from the 'View' object's offset.
	Method New(ElementSize:UInt, View:BufferView, ElementCount:UInt=MAX_VIEW_ELEMENTS, ExtraOffset:UInt=0)
		Self.ElementSize = ElementSize

		Self.Offset = (View.Offset + ExtraOffset)

		Self.Data = View.Data

		Self.Size = GetSize(Self.Data, ElementSize, ElementCount)
	End

	' Constructor(s) (Private):
	Private

	Method GetSize:UInt(Data:DataBuffer, ElementSize:UInt, ElementCount:UInt=MAX_VIEW_ELEMENTS)
		If (ElementCount = MAX_VIEW_ELEMENTS) Then
			Return Data.Length
		Endif

		Local IntendedSize:= (ElementCount * ElementSize) ' CountInBytes(ElementCount)

		' Make sure the intended size is correct.
		If (IntendedSize < ElementSize Or IntendedSize > Data.Length) Then
			' The intended size is either too large, or too small.
			Throw New InvalidViewMappingOperation(Self, Offset, IntendedSize)
		Endif

		Return IntendedSize
	End

	' NOTE: It is considered unsafe to call this constructor before assigning a value to the 'ElementSize' property.
	Method InitializeCustomBuffer:Void(ElementSize:UInt, ElementCount:UInt, __Direct:Bool=False) Final
		If (ElementSize = 0 Or ElementCount = 0) Then
			Throw New BulkAllocationException<BufferView>(Self, 0) ' IntendedSize
		Endif

		Local IntendedSize:= (ElementCount * ElementSize)

		Self.Data = New DataBuffer(IntendedSize, __Direct) ' CountInBytes(ElementCount)

		Self.Offset = 0
		Self.Size = Self.Data.Length
	End

	Public

	' Methods (Public):

	' If overridden, these methods must respect the 'Offset' property:
	Method Get:ValueType(Index:UInt)
		Return GetRaw(Offset + IndexToAddress(Index))
	End

	Method Set:Void(Index:UInt, Value:ValueType)
		SetRaw(Offset + IndexToAddress(Index), Value)

		Return
	End

	' This performs a raw memory transfer/copy from this view to 'Output'.
	' This means the output is not casted, but rather a mapped copy of the data.
	Method Transfer:Bool(InputIndex:UInt, Output:ElementView, OutputIndex:Int, Count:UInt) ' ArrayView
		Return ArrayViewOperation<ArrayView, ElementView>.Transfer(Self, InputIndex, Output, OutputIndex, Count) ' ArrayView<ValueType>
	End

	' This performs an element-level transfer/copy from 'Input' to this view.
	' This means that each element is casted from their source type/size to the destination type/size.
	Method Copy:Bool(Index:UInt, Input:ArrayView, InputIndex:Int, Count:UInt) ' ArrayView<ValueType>
		Return ArrayViewOperation<ArrayView, ArrayView>.Copy(Input, InputIndex, Self, Index, Count) ' ArrayView<ValueType>
	End

	Method Copy:Bool(Index:UInt, Input:ArrayView, InputIndex:Int=0)
		Return Copy(Index, Input, InputIndex, Min(Self.Length, Input.Length))
	End

	Method Copy:Bool(Input:ArrayView)
		Return Copy(0, Input, 0)
	End

	' This returns 'False' if the bounds specified are considered invalid.
	Method GetArray:Bool(Index:UInt, Output:ValueType[], Count:UInt, OutputOffset:UInt=0)
		' Calculate the end-point we'll be reaching.
		Local ByteBounds:= OffsetIndexToAddress(Index+Count)

		' Make sure the end-point fits within our buffer-segment.
		If (ByteBounds > Size) Then
			Return False
		Endif

		' This will be used to store our current write-location in 'Output'.
		Local OutputPosition:= OutputOffset

		' The current raw address in the internal buffer.
		Local Address:= OffsetIndexToAddress(Index)

		' Continue until we've reached our described bounds.
		While (Address < ByteBounds)
			' Copy the value located at 'Address' into the output.
			Output[OutputPosition] = GetRaw_Unsafe(Address)

			' Move to the next target-location for the output-data.
			OutputPosition += 1

			' Move forward by one entry.
			Address += ElementSize
		Wend

		' Return the default response.
		Return True
	End

	Method GetArray:ValueType[](Index:UInt, Count:UInt, _ArrOff:UInt=0)
		Local Output:= New ValueType[_ArrOff + Count]

		If (Not GetArray(Index, Output, Count, _ArrOff)) Then
			Return []
		Endif

		Return Output
	End

	Method GetArray:ValueType[]()
		Return GetArray(0, Length)
	End

	' This returns 'False' if the bounds specified are considered invalid.
	Method SetArray:Bool(Index:UInt, Input:ValueType[], Count:UInt, InputOffset:UInt=0)
		' Calculate the end-point we'll be reaching.
		Local ByteBounds:= OffsetIndexToAddress(Index+Count)

		' Make sure the end-point fits within our buffer-segment.
		If (ByteBounds > Size) Then
			Return False
		Endif

		' This will store our current position in the 'Input' array.
		Local InputPosition:= InputOffset

		' The current raw address in the internal buffer.
		Local Address:= OffsetIndexToAddress(Index)

		' The amount 'Address' will move by on each iteration.
		Local Stride:= ElementSize

		' Continue until we've reached our described bounds.
		While (Address < ByteBounds)
			' Write a value at the current address using an entry from the input-data.
			SetRaw_Unsafe(Address, Input[InputPosition])

			' Move to the next entry in the input-data.
			InputPosition += 1

			' Move forward by one entry.
			Address += Stride
		Wend

		' Return the default response.
		Return True
	End

	Method SetArray:Bool(Index:UInt, Input:ValueType[])
		Return SetArray(Index, Input, Input.Length)
	End

	' TODO: Optimize this overload to bypass index conversion.
	Method SetArray:Bool(Input:ValueType[])
		Return SetArray(0, Input)
	End

	' This returns 'False' if the bounds specified are considered invalid.
	Method Clear:Bool(Index:UInt, Count:UInt, Value:ValueType)
		' Calculate the end-point we'll be reaching.
		Local ByteBounds:= OffsetIndexToAddress(Index+Count)

		' Make sure the end-point fits within our buffer-segment.
		If (ByteBounds > ViewBounds) Then
			Return False
		Endif

		' The current raw address in the internal buffer.
		Local Address:= OffsetIndexToAddress(Index)

		' The amount 'Address' will move by on each iteration.
		Local Stride:= ElementSize

		' Continue until we've reached our described bounds.
		While (Address < ByteBounds)
			' Clear an entry at our current location in the buffer.
			SetRaw(Address, Value)

			' Move forward by one entry.
			Address += Stride
		Wend

		' Return the default response.
		Return True
	End

	' This calls 'Clear' using the value of 'NIL'.
	Method Clear:Bool(Index:UInt, Count:UInt)
		Return Clear(Index, Count, NIL)
	End

	' This clears the entire view using the value specified.
	Method Clear:Bool(Value:ValueType)
		Return Clear(0, Length, Value)
	End

	' TODO: Optimize this overload to bypass either index conversion or standard assignment.
	Method Clear:Bool()
		Return Clear(NIL)
	End

	Method Add:ValueType(Index:UInt, Value:ValueType)
		Local Result:= (Get(Index) + Value)

		Set(Index, Result)

		Return Result
	End

	Method Subtract:ValueType(Index:UInt, Value:ValueType)
		Return Add(Index, -Value)
	End

	' This supplies the raw size of 'Count' elements in bytes.
	Method CountInBytes:UInt(Count:Int)
		Return IndexToAddress(Count) ' (Count * ElementSize)
	End

	' This converts an index to a raw address for use with the internal buffer.
	Method IndexToAddress:UInt(Index:UInt)
		#If REGAL_UTIL_BUFFERVIEW_BYTE_OPTIMIZATIONS
			If (ElementSize = 1) Then
				Return Index
			Endif
		#End

		Return (Index * ElementSize)
	End

	' This converts a raw address to an index.
	Method AddressToIndex:UInt(Address:UInt)
		#If REGAL_UTIL_BUFFERVIEW_BYTE_OPTIMIZATIONS
			If (ElementSize = 1) Then
				Return Address
			Endif
		#End

		Return (Address / ElementSize)
	End

	#Rem
		The result of this method is a non-convertible raw address.
		By definition, this address may not be used with commands like
		'AddressToIndex', as the value would be skewed.

		To fix this address for such commands, subtract a stored result gathered
		from the 'Offset' property at the time this method was called.

		Because the value of 'Offset' can be changed, you must always ensure that
		the offset you apply to restore the appropriate value corresponds with the
		original value associated with this object's 'Offset' property.

		This type of address manipulation is not recommended,
		and should be avoided wherever possible.
	#End

	Method OffsetIndexToAddress:UInt(Index:UInt) Final
		Return (IndexToAddress(Index) + Offset)
	End

	' This method is an extension, which should only be used when converting
	' a value from a real address to a convertible address.
	' This command is not recommended, and is subject to deletion.
	Method __OffsetAddressToIndex:UInt(_Address:UInt) Final
		Return AddressToIndex(_Address - Offset)
	End

	' Methods (Protected):
	Protected

	' Abstract:

	' These two methods operate on raw addresses.
	' This means the input should not be an index,
	' nor should it be a non-offset address.
	' Implementations should not bother with out-of-bounds checks.
	Method GetRaw_Unsafe:ValueType(RawAddress:UInt) Abstract
	Method SetRaw_Unsafe:Void(RawAddress:UInt, Value:ValueType) Abstract

	' Implemented:

	' This method wraps 'OffsetIndexToAddress' for compatibility with the 'ElementView' interface.
	Method IndexToRawAddress:UInt(Index:UInt) Final
		Return OffsetIndexToAddress(Index)
	End

	Method SetRaw:Void(Address:UInt, Value:ValueType) Final
		Local ElementSize:= Self.ElementSize

		If ((Address + ElementSize) > ViewBounds) Then
			Throw New InvalidViewWriteOperation(Self, Address, ElementSize)
		Endif

		SetRaw_Unsafe(Address, Value)

		Return
	End

	Method GetRaw:ValueType(Address:UInt) Final
		Local ElementSize:= Self.ElementSize

		If ((Address + ElementSize) > ViewBounds) Then
			Throw New InvalidViewReadOperation(Self, Address, ElementSize)
		Endif

		Return GetRaw_Unsafe(Address)
	End

	Public

	' Properties (Public):

	' This provides the number of elements in this view.
	Method Length:UInt() Property
		#If REGAL_UTIL_BUFFERVIEW_BYTE_OPTIMIZATIONS
			If (ElementSize = 1) Then
				Return Size
			Endif
		#End

		Return (Size / ElementSize)
	End

	' This describes the address of the absolute furthest into the internal buffer this view reaches.
	' This is mainly useful for raw bounds checks that already account for offsets.
	' For a good example of this, view the 'GetArray' command's implementation(s).
	Method ViewBounds:UInt() Property
		Return (Size + Offset)
	End

	' This returns the raw size of the internal buffer area (In bytes), without adjusting for offsets.
	' This is useful when the literal size (In bytes) of this view is required.
	Method Size:UInt() Property ' Int
		Return Self._Size ' UInt(Data.Length)
	End

	' This specifies the size of an element.
	Method ElementSize:UInt() Property
		Return Self._ElementSize
	End

	' This provides access to the internal buffer-offset.
	' Note: This is already accounted for when calculating 'Size'.
	Method Offset:UInt() Property ' Int
		Return Self._Offset
	End

	Method Offset:Void(Value:UInt) Property
		Self._Offset = Value

		#If REGAL_UTIL_BUFFERVIEW_SAFE
			' Nothing so far.
		#End

		Return
	End

	' This provides access to the internal buffer.
	Method Data:DataBuffer() Property ' Final
		Return Self._Data
	End

	' Properties (Protected):
	Protected

	Method Size:Void(Value:UInt) Property
		Self._Size = Value

		Return
	End

	Method Data:Void(Value:DataBuffer) Property
		Self._Data = Value

		Return
	End

	Method ElementSize:Void(Value:UInt) Property
		Self._ElementSize = Value

		Return
	End

	Public

	' Fields (Protected):
	Protected

	Field _ElementSize:UInt ' Int
	Field _Offset:UInt ' Int
	Field _Size:UInt ' Int
	Field _Data:DataBuffer

	Public
End

' This is an intermediate class which defines mathematical routines for both integral and floating-point types.
Class MathArrayView<ValueType> Extends ArrayView<ValueType> Abstract
	' Constructor(s):
	Method New(ElementSize:UInt, ElementCount:UInt, __Direct:Bool=False)
		Super.New(ElementSize, ElementCount, __Direct)
	End

	Method New(ElementSize:UInt, Data:DataBuffer, OffsetInBytes:UInt=0, ElementCount:UInt=MAX_VIEW_ELEMENTS)
		Super.New(ElementSize, Data, OffsetInBytes, ElementCount)
	End

	Method New(ElementSize:UInt, View:BufferView, ElementCount:UInt=MAX_VIEW_ELEMENTS, ExtraOffset:UInt=0)
		Super.New(ElementSize, View, ElementCount, ExtraOffset)
	End

	' Methods:

	' This increments the value located at 'Index' by one.
	Method Increment:ValueType(Index:UInt)
		Return Add(Index, ValueType(1))
	End

	' This decrements the value located at 'Index' by one.
	Method Decrement:ValueType(Index:UInt)
		Return Subtract(Index, ValueType(1))
	End

	' This multiplies the value located at 'Index' using the value specified.
	' The result is written into memory, then returned.
	Method Multiply:ValueType(Index:UInt, Value:ValueType)
		Local Result:= (Get(Index) * Value)

		Set(Index, Result)

		Return Result
	End

	' This divides the value located at 'Index' using the value specified.
	' The result is written into memory, then returned.
	Method Divide:ValueType(Index:UInt, Value:ValueType)
		Local Result:= (Get(Index) / Value)

		Set(Index, Result)

		Return Result
	End

	' This squares the value located at 'Index'.
	' The result is both returned by the method, and
	' written into memory at the specified location.
	Method Sq:ValueType(Index:UInt) ' Square
		Local Value:= Get(Index)
		Local Result:= (Value * Value)

		Set(Index, Result)

		Return Result
	End

	' This calculates the square-root of the value located at 'Index'.
	' The result is both returned by this method, and
	' written into memory at the specified location.
	Method Sqrt:ValueType(Index:UInt) ' SquareRoot
		Local Result:= Sqrt(Get(Index))

		Set(Index, Result)

		Return Result
	End
End

Class IntArrayView Extends MathArrayView<Int> ' ArrayView<Long> ' Int ' LongArrayView
	' Constant variable(s):
	Const Type_Size:= SizeOf_Integer ' 4

	' Constructor(s) (Public):
	Method New(Count:UInt, __Direct:Bool=False)
		Super.New(Type_Size, Count, __Direct)
	End

	Method New(Data:DataBuffer, OffsetInBytes:UInt=0, ElementCount:UInt=MAX_VIEW_ELEMENTS)
		Super.New(Type_Size, Data, OffsetInBytes, ElementCount)
	End

	Method New(View:BufferView, ElementCount:UInt=MAX_VIEW_ELEMENTS, ExtraOffset:UInt=0)
		Super.New(Type_Size, View, ElementCount, ExtraOffset)
	End

	' Constructor(s) (Protected):
	Protected

	Method New(Type_Size:UInt, ElementCount:UInt, __Direct:Bool=False)
		Super.New(Type_Size, ElementCount, __Direct)
	End

	Method New(Type_Size:UInt, Data:DataBuffer, OffsetInBytes:UInt=0, ElementCount:UInt=MAX_VIEW_ELEMENTS)
		Super.New(Type_Size, Data, OffsetInBytes, ElementCount)
	End

	Method New(Type_Size:UInt, View:BufferView, ElementCount:UInt=MAX_VIEW_ELEMENTS, ExtraOffset:UInt=0)
		Super.New(Type_Size, View, ElementCount, ExtraOffset)
	End

	Public

	' Methods (Public):
	Method GetUnsigned:Int(Index:UInt)
		Return (Get(Index) & $FFFFFFFF)
	End

	Method SetUnsigned:Void(Index:UInt, Value:Int)
		Set(Index, (Value & $FFFFFFFF))

		Return
	End

	' Methods (Protected):
	Protected

	Method GetRaw_Unsafe:Int(Address:UInt) ' Final
		Return Data.PeekInt(Address)
	End

	Method SetRaw_Unsafe:Void(Address:UInt, Value:Int) ' Final
		Data.PokeInt(Address, Value)

		Return
	End

	Public
End

Class ShortArrayView Extends IntArrayView ' ArrayView<Int> ' Short
	' Constant variable(s):
	Const Type_Size:= SizeOf_Short

	' Constructor(s) (Public):
	Method New(Count:UInt, __Direct:Bool=False)
		Super.New(Type_Size, Count, __Direct)
	End

	Method New(Data:DataBuffer, OffsetInBytes:UInt=0, ElementCount:UInt=MAX_VIEW_ELEMENTS)
		Super.New(Type_Size, Data, OffsetInBytes, ElementCount)
	End

	Method New(View:BufferView, ElementCount:UInt=MAX_VIEW_ELEMENTS, ExtraOffset:UInt=0)
		Super.New(Type_Size, View, ElementCount, ExtraOffset)
	End

	' Constructor(s) (Protected):
	Protected

	Method New(Type_Size:UInt, ElementCount:UInt, __Direct:Bool=False)
		Super.New(Type_Size, ElementCount, __Direct)
	End

	Method New(Type_Size:UInt, Data:DataBuffer, OffsetInBytes:UInt=0, ElementCount:UInt=MAX_VIEW_ELEMENTS)
		Super.New(Type_Size, Data, OffsetInBytes, ElementCount)
	End

	Method New(Type_Size:UInt, View:BufferView, ElementCount:UInt=MAX_VIEW_ELEMENTS, ExtraOffset:UInt=0)
		Super.New(Type_Size, View, ElementCount, ExtraOffset)
	End

	Public

	' Methods (Public):
	Method GetUnsigned:Int(Index:UInt) ' Short
		Return (Get(Index) & $FFFF)
	End

	Method SetUnsigned:Void(Index:UInt, Value:Int) ' Short
		Set(Index, (Value & $FFFF))

		Return
	End

	' Methods (Protected):
	Protected

	Method GetRaw_Unsafe:Int(Address:UInt) ' Final ' Short
		Return Data.PeekShort(Address)
	End

	Method SetRaw_Unsafe:Void(Address:UInt, Value:Int) ' Final ' Short
		Data.PokeShort(Address, Value)

		Return
	End

	Public
End

Class ByteArrayView Extends ShortArrayView ' ArrayView<Int> ' Byte
	' Constant variable(s):
	Const Type_Size:= SizeOf_Byte

	' Constructor(s):
	Method New(Count:UInt, __Direct:Bool=False)
		Super.New(Type_Size, Count, __Direct)
	End

	Method New(Data:DataBuffer, OffsetInBytes:UInt=0, ElementCount:UInt=MAX_VIEW_ELEMENTS)
		Super.New(Type_Size, Data, OffsetInBytes, ElementCount)
	End

	Method New(View:BufferView, ElementCount:UInt=MAX_VIEW_ELEMENTS, ExtraOffset:UInt=0)
		Super.New(Type_Size, View, ElementCount, ExtraOffset)
	End

	' Methods (Public):
	#If REGAL_UTIL_BUFFERVIEW_BYTE_OPTIMIZATIONS
		' These two methods follow the integrity rules of 'Offset':
		Method Get:Int(Address:UInt) ' Byte
			Return GetRaw(Offset + Address)
		End

		Method Set:Void(Address:UInt, Value:Int) ' Byte
			SetRaw(Offset + Address, Value)

			Return
		End

		#Rem
			Method IndexToAddress:UInt(Address:UInt) ' Index:UInt
				Return Address
			End

			Method AddressToIndex:UInt(Address:UInt)
				Return Address
			End
		#End
	#End

	Method GetUnsigned:Int(Address:UInt) ' Byte
		Return (Get(Address) & $FF)
	End

	Method SetUnsigned:Void(Index:UInt, Value:Int) ' Byte
		Set(Index, (Value & $FF))

		Return
	End

	' Methods (Protected):
	Protected

	Method GetRaw_Unsafe:Int(Address:UInt) ' Final ' Byte
		Return Data.PeekByte(Address)
	End

	Method SetRaw_Unsafe:Void(Address:UInt, Value:Int) ' Final ' Byte
		Data.PokeByte(Address, Value)

		Return
	End

	Public
End

Class FloatArrayView Extends MathArrayView<Float> ' DoubleArrayView
	' Constant variable(s):
	Const Type_Size:= SizeOf_Float ' 4 ' 8

	' Constructor(s):
	Method New(Count:UInt, __Direct:Bool=False)
		Super.New(Type_Size, Count, __Direct)
	End

	Method New(Data:DataBuffer, OffsetInBytes:UInt=0, ElementCount:UInt=MAX_VIEW_ELEMENTS)
		Super.New(Type_Size, Data, OffsetInBytes, ElementCount)
	End

	Method New(View:BufferView, ElementCount:UInt=MAX_VIEW_ELEMENTS, ExtraOffset:UInt=0)
		Super.New(Type_Size, View, ElementCount, ExtraOffset)
	End

	' Methods (Protected):
	Protected

	Method GetRaw_Unsafe:Float(Address:UInt) ' Final ' Double
		Return Data.PeekFloat(Address)
	End

	Method SetRaw_Unsafe:Void(Address:UInt, Value:Float) ' Final ' Double
		Data.PokeFloat(Address, Value)

		Return
	End

	Public
End

' This class contains generic utilities for 'ArrayView' objects.
Class ArrayViewOperation<A, B> Abstract
	#Rem
		This performs a raw memory copy from one view to another.

		Address translations are performed before copy-operations
		take place, and are checked accordingly.

		The 'Count' argument specifies the number of elements to be copied from 'Input'.

		If preliminary bounds checks fail, this command will return 'False'.
	#End

	Function Transfer:Bool(Input:A, InputIndex:UInt, Output:B, OutputIndex:Int, Count:UInt) ' ArrayView ' ElementView
		' Get the appropriate element size.
		Local ElementSize:= Input.ElementSize ' Min(Input.ElementSize, Output.ElementSize)
		Local BytesToTransfer:= (ElementSize * Count)

		' Calculate the end-points we'll be reaching:
		Local InByteBounds:= Input.IndexToRawAddress(InputIndex + Count)
		Local OutByteBounds:= Output.IndexToRawAddress(OutputIndex) + BytesToTransfer ' Output.IndexToRawAddress(OutputIndex + Count)

		' Make sure the end-points fit within our buffer segments:
		If (InByteBounds > Input.Size Or OutByteBounds > Output.Size) Then
			Return False
		Endif

		' The starting raw address in the output buffer.
		Local OutputAddress:= Output.IndexToRawAddress(OutputIndex)

		' The starting raw address in the input buffer.
		Local InputAddress:= Input.IndexToRawAddress(InputIndex)

		' Perform a raw memory copy from 'Input.Data' to 'Output.Data'.
		Input.Data.CopyBytes(InputAddress, Output.Data, OutputAddress, BytesToTransfer)

		' Return the default response.
		Return True
	End

	' This performs an element-level copy from one view to another.
	' If preliminary bounds checks fail, this command will return 'False'.
	Function Copy:Bool(Input:A, InputIndex:UInt, Output:B, OutputIndex:Int, Count:UInt) ' ArrayView ' ElementView
		' Calculate the appropriate element size.
		Local InElementSize:= Input.ElementSize
		Local OutElementSize:= Output.ElementSize

		' Calculate the end-points we'll be reaching:
		Local InByteBounds:= Input.IndexToRawAddress(InputIndex + Count)
		Local OutByteBounds:= Output.IndexToRawAddress(OutputIndex + Count)

		' Make sure the end-points fit within our buffer segments:
		If (InByteBounds > Input.Size Or OutByteBounds > Output.Size) Then
			Return False
		Endif

		' The starting raw address in the output buffer.
		Local OutputAddress:= Output.IndexToRawAddress(OutputIndex)

		' The starting raw address in the input buffer.
		Local InputAddress:= Input.IndexToRawAddress(InputIndex)

		' Continue until we've reached our described bounds:
		While (InputAddress < InByteBounds)
			#If CONFIG = "debug"
				If (OutputAddress >= OutByteBounds) Then
					Exit
				Endif
			#End

			' Copy the value located at 'InputAddress' into the output at 'OutputAddress'.
			Output.SetRaw_Unsafe(OutputAddress, Input.GetRaw_Unsafe(InputAddress))

			' Move forward by one entry on each address:
			InputAddress += InElementSize
			OutputAddress += OutElementSize
		Wend

		' Return the default response.
		Return True
	End

	' Constructor(s) (Private):
	Private

	Method New() ' Final
		' This constructor is reserved.
	End

	Public
End

Class ElementViewOperation Extends ArrayViewOperation<ElementView, ElementView>
	' Nothing so far.
End


Forgot to add an import to 'filepath'.

Forgot to add an import to 'filepath'.

Strict

Public

#Rem
	This acts as a compatibility-layer with the official 'brl' implementation.

	This API intends to be as accurate as possible, allowing
	users to build consistent codebases between platforms.

	ATTENTION: This sub-module does not follow the "standalone" behavioral
	rules applied to the other modules.

	To use this sub-module, you must have the 'regal.ioutil.publicdatastream'
	module installed, and any dependencies it requires.

	In addition, this uses both the standard 'brl.stream' module,
	as well as the internal file-system modules/extensions.
#End

' Imports (Public):
Import brl.stream

' Imports (Private):
Private

Import regal.ioutil.publicdatastream

Import filepath
Import filesystem
Import legend

Public

' Preprocessor related:
#If VIRTUALOS_CREATEFILE_IMPLEMENTED And (VIRTUALOS_EXTENSION_LOADBUFFER Or VIRTUALOS_EXTENSION_SAVEBUFFER)
	#VIRTUALOS_FILESTREAM_IMPLEMENTED = True
#End

#If VIRTUALOS_EXTENSION_LOADBUFFER
	#VIRTUALOS_FILESTREAM_CAN_LOAD = True
#End

#If VIRTUALOS_EXTENSION_SAVEBUFFER
	#VIRTUALOS_FILESTREAM_CAN_SAVE = True
#End

#If VIRTUALOS_FILESTREAM_IMPLEMENTED
	' Classes:
	Class FileStream Extends PublicDataStream
		' Constant variable(s):

		' Defaults:
		Const Default_Size:= 4096 ' 4KB

		' Functions:
		Function Open:FileStream(Path:String, Mode:String)
			Try
				Return New FileStream(Path, Mode)
			Catch E:StreamError
				' Nothing so far.
			End

			Return Null
		End

		' Constructor(s) (Public):
		Method New(Path:String, Mode:String, Size:Int=Default_Size, FixByteOrder:Bool=Default_BigEndianStorage, SizeLimit:Int=NOLIMIT)
			Super.New(Size, FixByteOrder, True, SizeLimit)

			EstablishStream(ResolveProtocolPath(Path), Mode)
		End

		' Constructor(s) (Protected):
		Protected

		Method EstablishStream:Void(Path:String, Mode:String)
			Select Mode
				#If VIRTUALOS_FILESTREAM_CAN_LOAD
					Case "r", "u"
						ReadFileData(RealPath(Path), True)
					Case "a"
						ReadFileData(RealPath(Path), False)
				#End

				#If VIRTUALOS_FILESTREAM_CAN_SAVE
					Case "w"
						CreateFile(Path)
				#End

				Default
					Throw New FileStreamOpenException("Invalid file-mode detected.", Path, Self)
			End Select

			Self.Path = Path
			Self.Mode = Mode

			Return
		End

		Public

		' Methods (Public):
		Method Close:Void()
			#If VIRTUALOS_FILESTREAM_CAN_SAVE
				If (IsOutputStream) Then
					' Push data to the file-system.
					WriteFileData(RealPath(Self.Path))
				Endif
			#End

			' Close the stream properly.
			Super.Close()

			Return
		End

		' Methods (Protected):
		Protected

		#If VIRTUALOS_FILESTREAM_CAN_LOAD
			Method ReadFileData:DataBuffer(RealPath:String, ResetPosition:Bool=True)
				Local Contents:= __OS_LoadBuffer(RealPath)

				If (Contents = Null) Then
					Return Null
				Endif

				Local Position:= Self.Position

				WriteAll(Contents, 0, Contents.Length)

				If (ResetPosition) Then
					Seek(Position)
				Endif

				Return Contents
			End
		#End

		#If VIRTUALOS_FILESTREAM_CAN_SAVE
			Method WriteFileData:Bool(RealPath:String)
				Local Output:= New DataBuffer(Self.Length)

				Self.Data.CopyBytes(Offset, Output, 0, Length)

				If (Not __OS_SaveBuffer(RealPath, Output)) Then
					Return False
				Endif

				'Output.Discard()

				' Return the default response.
				Return True
			End
		#End

		Public

		' Properties:
		Method IsInputStream:Bool() Property
			#If VIRTUALOS_FILESTREAM_CAN_LOAD
				Return (Mode = "r")
			#Else
				Return False
			#End
		End

		Method IsOutputStream:Bool() Property
			#If VIRTUALOS_FILESTREAM_CAN_SAVE
				Return (Mode = "w" Or Mode = "a" Or Mode = "u") ' (Not IsInputStream)
			#Else
				Return False
			#End
		End

		' Fields (Protected):
		Protected

		Field Path:String, Mode:String

		Public
	End
#End

' Exceptions:
Class FileStreamOpenException Extends StreamError
	' Constructor(s):
	Method New(Message:String, Path:String, FS:FileStream)
		Super.New(FS)

		Self.Message = Message
	End

	' Methods:
	Method ToString:String() ' Property
		Return Message
	End

	' Fields (Protected):
	Protected

	Field Message:String

	Public
End

Strict

Public

#Rem
	This acts as a compatibility-layer with the official 'brl' implementation.

	This API intends to be as accurate as possible, allowing
	users to build consistent codebases between platforms.

	ATTENTION: This sub-module does not follow the "standalone" behavioral
	rules applied to the other modules.

	To use this sub-module, you must have the 'regal.ioutil.publicdatastream'
	module installed, and any dependencies it requires.

	In addition, this uses both the standard 'brl.stream' module,
	as well as the internal file-system modules/extensions.
#End

' Imports (Public):
Import brl.stream

' Imports (Private):
Private

Import regal.ioutil.publicdatastream

Import filesystem
Import legend

Public

' Preprocessor related:
#If VIRTUALOS_CREATEFILE_IMPLEMENTED And (VIRTUALOS_EXTENSION_LOADBUFFER Or VIRTUALOS_EXTENSION_SAVEBUFFER)
	#VIRTUALOS_FILESTREAM_IMPLEMENTED = True
#End

#If VIRTUALOS_EXTENSION_LOADBUFFER
	#VIRTUALOS_FILESTREAM_CAN_LOAD = True
#End

#If VIRTUALOS_EXTENSION_SAVEBUFFER
	#VIRTUALOS_FILESTREAM_CAN_SAVE = True
#End

#If VIRTUALOS_FILESTREAM_IMPLEMENTED
	' Classes:
	Class FileStream Extends PublicDataStream
		' Constant variable(s):

		' Defaults:
		Const Default_Size:= 4096 ' 4KB

		' Functions:
		Function Open:FileStream(Path:String, Mode:String)
			Try
				Return New FileStream(Path, Mode)
			Catch E:StreamError
				' Nothing so far.
			End

			Return Null
		End

		' Constructor(s) (Public):
		Method New(Path:String, Mode:String, Size:Int=Default_Size, FixByteOrder:Bool=Default_BigEndianStorage, SizeLimit:Int=NOLIMIT)
			Super.New(Size, FixByteOrder, True, SizeLimit)

			EstablishStream(ResolveProtocolPath(Path), Mode)
		End

		' Constructor(s) (Protected):
		Protected

		Method EstablishStream:Void(Path:String, Mode:String)
			Select Mode
				#If VIRTUALOS_FILESTREAM_CAN_LOAD
					Case "r", "u"
						ReadFileData(RealPath(Path), True)
					Case "a"
						ReadFileData(RealPath(Path), False)
				#End

				#If VIRTUALOS_FILESTREAM_CAN_SAVE
					Case "w"
						CreateFile(Path)
				#End

				Default
					Throw New FileStreamOpenException("Invalid file-mode detected.", Path, Self)
			End Select

			Self.Path = Path
			Self.Mode = Mode

			Return
		End

		Public

		' Methods (Public):
		Method Close:Void()
			#If VIRTUALOS_FILESTREAM_CAN_SAVE
				If (IsOutputStream) Then
					' Push data to the file-system.
					WriteFileData(RealPath(Self.Path))
				Endif
			#End

			' Close the stream properly.
			Super.Close()

			Return
		End

		' Methods (Protected):
		Protected

		#If VIRTUALOS_FILESTREAM_CAN_LOAD
			Method ReadFileData:DataBuffer(RealPath:String, ResetPosition:Bool=True)
				Local Contents:= __OS_LoadBuffer(RealPath)

				If (Contents = Null) Then
					Return Null
				Endif

				Local Position:= Self.Position

				WriteAll(Contents, 0, Contents.Length)

				If (ResetPosition) Then
					Seek(Position)
				Endif

				Return Contents
			End
		#End

		#If VIRTUALOS_FILESTREAM_CAN_SAVE
			Method WriteFileData:Bool(RealPath:String)
				Local Output:= New DataBuffer(Self.Length)

				Self.Data.CopyBytes(Offset, Output, 0, Length)

				If (Not __OS_SaveBuffer(RealPath, Output)) Then
					Return False
				Endif

				'Output.Discard()

				' Return the default response.
				Return True
			End
		#End

		Public

		' Properties:
		Method IsInputStream:Bool() Property
			#If VIRTUALOS_FILESTREAM_CAN_LOAD
				Return (Mode = "r")
			#Else
				Return False
			#End
		End

		Method IsOutputStream:Bool() Property
			#If VIRTUALOS_FILESTREAM_CAN_SAVE
				Return (Mode = "w" Or Mode = "a" Or Mode = "u") ' (Not IsInputStream)
			#Else
				Return False
			#End
		End

		' Fields (Protected):
		Protected

		Field Path:String, Mode:String

		Public
	End
#End

' Exceptions:
Class FileStreamOpenException Extends StreamError
	' Constructor(s):
	Method New(Message:String, Path:String, FS:FileStream)
		Super.New(FS)

		Self.Message = Message
	End

	' Methods:
	Method ToString:String() ' Property
		Return Message
	End

	' Fields (Protected):
	Protected

	Field Message:String

	Public
End


Fixes for scale fix :)

Fixes for scale fix :)

Strict

Import flixel.flxcamera
Import flixel.flxg
Import flixel.flxu

Class FlxTilemapBuffer

	Field x:Float

	Field y:Float

	Field width:Float

	Field height:Float

	Field rows:Int

	Field columns:Int

	Field dirty:Bool

	Field scaleFixX:Float

	Field scaleFixY:Float

	Method New(tileWidth:Float, tileHeight:Float, widthInTiles:Int, heightInTiles:Int, camera:FlxCamera = Null)
		If (camera = Null) camera = FlxG.camera

		columns = Ceil(camera.Width / tileWidth) + 1
		If (columns > widthInTiles) columns = widthInTiles

		rows = Ceil(camera.Height / tileHeight) + 1
		If (rows > heightInTiles) rows = heightInTiles

		width = columns * tileWidth
		height = rows * tileHeight

		dirty = True

		Local scaledTileWidth:Float = tileWidth * camera.Zoom * FlxG._deviceScaleFactorX
		Local scaledTileHeight:Float = tileHeight * camera.Zoom * FlxG._deviceScaleFactorY
		Local roundScaledTileWidth:Float = FlxU.Round(scaledTileWidth)
		Local roundScaledTileHeight:Float = FlxU.Round(scaledTileHeight)

		If (Abs(roundScaledTileWidth - scaledTileWidth) > 0) Then
			roundScaledTileWidth += 1

			If (roundScaledTileWidth - scaledTileWidth > 0) Then
				scaleFixX = roundScaledTileWidth / scaledTileWidth
			Else
				scaleFixX = scaledTileWidth / roundScaledTileWidth
			End If
		Else
			scaleFixX = 1
		End If

		If (Abs(roundScaledTileHeight - scaledTileHeight) > 0) Then
			roundScaledTileHeight += 1

			If (roundScaledTileHeight - scaledTileHeight > 0) Then
				scaleFixY = roundScaledTileHeight / scaledTileHeight
			Else
				scaleFixY = scaledTileHeight / roundScaledTileHeight
			End If
		Else
			scaleFixY = 1
		End If
	End Method

End Class

Strict

Import flixel.flxcamera
Import flixel.flxg
Import flixel.flxu

Class FlxTilemapBuffer

	Field x:Float

	Field y:Float

	Field width:Float

	Field height:Float

	Field rows:Int

	Field columns:Int

	Field dirty:Bool

	Field scaleFixX:Float

	Field scaleFixY:Float

	Method New(tileWidth:Float, tileHeight:Float, widthInTiles:Int, heightInTiles:Int, camera:FlxCamera = Null)
		If (camera = Null) camera = FlxG.camera

		columns = Ceil(camera.Width / tileWidth) + 1
		If (columns > widthInTiles) columns = widthInTiles

		rows = Ceil(camera.Height / tileHeight) + 1
		If (rows > heightInTiles) rows = heightInTiles

		width = columns * tileWidth
		height = rows * tileHeight

		dirty = True

		Local scaledTileWidth:Float = tileWidth * camera.Zoom * FlxG._deviceScaleFactorX
		Local scaledTileHeight:Float = tileHeight * camera.Zoom * FlxG._deviceScaleFactorY
		Local roundScaledTileWidth:Float = FlxU.Round(scaledTileWidth)
		Local roundScaledTileHeight:Float = FlxU.Round(scaledTileHeight)

		If (roundScaledTileWidth - scaledTileWidth > 0) Then
			scaleFixX = roundScaledTileWidth / scaledTileWidth
		Else
			scaleFixX = 1
		End If

		If (roundScaledTileHeight - scaledTileHeight > 0) Then
			scaleFixY = roundScaledTileHeight / scaledTileHeight
		Else
			scaleFixY = 1
		End If
	End Method

End Class


Update simd.monkey

Update simd.monkey

#If LANG<>"cpp"
#Error "SIMD only supported on C++ targets"
#Endif

Import "native/simd.${LANG}"

Extern

Class @Float32x4 Extends Object="SSE_Float32x4"
End

Class SIMD
	' Float32x4 Factory
	Function MakeFloat32x4:Float32x4(x:Float, y:Float, z:Float, w:Float)
	Function MakeFloat32x4Zero:Float32x4()
	Function MakeFloat32x4Reverse:Float32x4(x:Float, y:Float, z:Float, w:Float)
	Function MakeFloat32x4One:Float32x4(x:Float)
	' Float32x4 Set Operations
	Function Set:Void(destination:Float32x4, x:Float, y:Float, z:Float, w:Float)
	Function SetZero:Void(destination:Float32x4)
	Function SetOne:Void(destination:Float32x4)
	Function SetReverse:Void(destination:Float32x4, x:Float, y:Float, z:Float, w:Float)
	' Float32x4 Load and Store
	Function Load:Void(destination:Float32x4, source:Float[])
	Function Store:Void(destination:Float[], source:Float32x4)
	' Float32x4 Arithmetic
	Function Add:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4)
	Function Sub:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4)
	Function Mul:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4)
	Function Div:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4)
	Function Min:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4)
	Function Max:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4)
	Function Sqrt:Void(destination:Float32x4, source:Float32x4)
	Function Rsqrt:Void(destination:Float32x4, source:Float32x4)
	' Float32x4 Logical Operations
	Function BAnd:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4)
	Function BAndNot:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4)
	Function BOr:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4)
	Function BXor:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4)
End

' Float32x4 Shuffle
Function SIMD_Shuffle:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4, mask:Int) = "SIMD_SHUFFLE"
Function SIMD_ShuffleHelper:Int(x:Int, y:Int, z:Int, w:Int) = "_MM_SHUFFLE"

#If LANG<>"cpp"
#Error "SIMD only supported on C++ targets"
#Endif

Import "native/simd.${LANG}"

Extern

Class @Float32x4 Extends Object="SSE_Float32x4"
End

Class SIMD
	' Float32x4 Factory
	Function MakeFloat32x4:Float32x4(x:Float, y:Float, z:Float, w:Float)
	Function MakeFloat32x4Zero:Float32x4()
	Function MakeFloat32x4Reverse:Float32x4(x:Float, y:Float, z:Float, w:Float)
	Function MakeFloat32x4One:Float32x4(x:Float)
	' Float32x4 Set Operations
	Function Set:Void(destination:Float32x4, x:Float, y:Float, z:Float, w:Float)
	Function SetZero:Void(destination:Float32x4)
	Function SetOne:Void(destination:Float32x4)
	Function SetReverse:Void(destination:Float32x4, x:Float, y:Float, z:Float, w:Float)
	' Float32x4 Load and Store
	Function Load:Void(destination:Float32x4, source:Float[])
	Function Store:Void(destination:Float[], source:Float32x4)
	' Float32x4 Arithmetic
	Function Add:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4)
	Function Sub:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4)
	Function Mul:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4)
	Function Div:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4)
	Function Min:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4)
	Function Max:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4)
	Function Sqrt:Void(destination:Float32x4, source:Float32x4)
	Function Rsqrt:Void(destination:Float32x4, source:Float32x4)
	' Float32x4 Logical Operations
	Function BAnd:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4)
	Function BAndNot:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4)
	Function BOr:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4)
	Function BXor:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4)
	' Float32x4 Shuffle

	'Function Shuffle:Void(destination:Float32x4, operand:Float32x4, mask:Int)
End

Function SIMD_Shuffle:Void(destination:Float32x4, operandR:Float32x4, operandL:Float32x4, mask:Int) = "SIMD_SHUFFLE"
Function SIMD_ShuffleHelper:Int(x:Int, y:Int, z:Int, w:Int) = "_MM_SHUFFLE"


Added EaseInBounceTween, EaseOutBounceTween & EaseInOutBounceTween functions to maths

#Rem
Copyright (c) 2011 Steve Revill and Shane Woolcock
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#End

Function QuadTween:Float(b:Float, c:Float, t:Float, d:Float = 1)
	Local diff:Float = c - b
	t /= d / 2
	If t < 1 Return diff / 2 * t * t + b
	t -= 1
	Return -diff / 2 * (t * (t - 2) - 1) + b
End

Function QuinticTween:Float(b:Float, c:Float, t:Float, d:Float = 1)
	Local diff:Float = c - b
	t /= d / 2
	If (t < 1) Return diff / 2 * t * t * t * t * t + b
	t -= 2
	Return diff / 2 * (t * t * t * t * t + 2) + b
End

Function TweenCalc:Float(p1:Float, p2:Float, t:Float)
	Return p1 + t * (p2 - p1)
End

Function TweenSmooth:Float(p1:Float, p2:Float, t:Float)
	Local v:Float = SmoothStep(t)
	Return p1 + v * (p2 - p1)
End

Function SmoothStep:Float(x:Float, interpSmooth:Int = 1)
	For Local i:Int = 0 Until interpSmooth
		x *= x * (3 - 2 * x)
	Next

	Return x' x*x * (3-2*x)
End

Function TweenUp:Float(p1:Float, p2:Float, t:Float)
	Local v:Float = SmoothStep(t)
	v = Pow(v, 2) 'power of 2.
	Return p1 + v * (p2 - p1)
End

Function TweenDown:Float(p1:Float, p2:Float, t:Float)
	Local v:Float = SmoothStep(t)
	v = 1 - Pow(1 - v, 2) 'InvSquared
	Return p1 + v * (p2 - p1)
End

Function Bezier:Float(p1:Float, p2:Float, cp1:Float, cp2:Float, t:Float)
	Local v:Float = p1 * Pow( (1 - t), 3) + 3 * cp1 * Pow( (1 - t), 2) * t + 3 * cp2 * (1 - t) * Pow(t, 2) + p2 * Pow(t, 3)
	Return v
End

Function EaseInBounceTween:Float(t:Float, b:Float, c:Float, d:Float = 1)
	Local diff:Float = c - b
	Return diff - EaseOutBounceTween(d - t, 0, diff, d) + b
End

Function EaseOutBounceTween:Float(t:Float, b:Float, c:Float, d:Float = 1)
	Local diff:Float = c - b
	t /= d
	If (t < (1 / 2.75))
		Return diff * (7.5625 * t * t) + b
	ElseIf(t < (2 / 2.75))
		t -= (1.5 / 2.75)
		Return diff * (7.5625 * t * t + 0.75) + b
	ElseIf(t < (2.5 / 2.75))
		t -= (2.25 / 2.75)
		Return diff * (7.5625 * t * t + 0.9375) + b
	Else
		t -= (2.625 / 2.75)
		Return diff * (7.5625 * t * t + 0.984375) + b
	End
End

Function EaseInOutBounceTween:Float(t:Float, b:Float, c:Float, d:Float = 1)
	Local diff:Float = c - b
	If (t < d / 2)
		Return EaseInBounceTween(t * 2, 0, diff, d) * 0.5 + b
	End
	Return EaseOutBounceTween(t * 2 - d, 0, diff, d) * 0.5 + diff * 0.5 + b
End