Fixed matrix stuff.

Fixed matrix stuff.

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

' ***** Start mojo.bmax.bmx ******

Global app:gxtkApp

Type gxtkApp
	Field ginput:gxtkInput
	Field gaudio:gxtkAudio
	Field ggraphics:gxtkGraphics

	Field dead:Int=0
	Field suspended:Int=0
	Field vloading:Int=0
	Field maxloading:Int=0
	Field updateRate:Int=0
	Field nextUpdate:Float=0
	Field updatePeriod:Float=0
	Field startMillis:Float=0

	Method New()' gxtkApp()
		app=Self
		ggraphics=New gxtkGraphics
	EndMethod

	Method Setup()
		ginput=New gxtkInput
		gaudio=New gxtkAudio

		bb_input_SetInputDevice(ginput)
		bb_audio_SetAudioDevice(gaudio)

		startMillis=BlitzMaxMillisecs()

		SetFrameRate( 0 )

		InvokeOnCreate()
		InvokeOnRender()
		Update()
	EndMethod

	Method Update()
		While Not AppTerminate()
			Local updates:Int = 0

			Local cont:Int = 1
			While (cont)
				nextUpdate:+updatePeriod
				InvokeOnUpdate()
				If Not updatePeriod Then cont = 0
				If nextUpdate>BlitzMaxMillisecs() Then cont = 0
				updates:+1
				If updates = 7 Then
					nextUpdate = BlitzMaxMillisecs()
					cont = 0
				EndIf
			Wend
			InvokeOnRender()
		Wend
	EndMethod

	Method InvokeOnCreate()
		If dead Return
		dead = 1
		OnCreate()
		dead = 0
	EndMethod

	Method InvokeOnUpdate()
		If dead Or suspended Or Not updateRate Or vloading Return
		OnUpdate()
	EndMethod

	Method InvokeOnRender()
		If dead Or suspended Return
		ggraphics.BeginRender()
		If vloading
			OnLoading()
		Else
			OnRender()
		EndIf
		ggraphics.EndRender()
	EndMethod

	Method SetFrameRate( fps:Int )
		If fps
			updatePeriod=1000.0/fps
			nextUpdate=BlitzMaxMillisecs() +updatePeriod
		Else
			updatePeriod=0
		EndIf
	EndMethod

	Method LoadState:String()
'		var file:SharedObject=SharedObject.getLocal( "gxtkapp" );
'		var state:String=file.data.state;
'		file.close();
'		if( state ) return state;
		Return ""
	EndMethod

	Method SaveState:Int( state:String )
'		var file:SharedObject=SharedObject.getLocal( "gxtkapp" );
'		file.data.state=state;
'		file.close();
		Return 0
	EndMethod

	Method LoadString:String( path:String )
		path = "data/" + path
		Return LoadText( path )
	EndMethod

	' ***** GXTK API *****

	Method GraphicsDevice:gxtkGraphics()
		Return ggraphics
	EndMethod

	Method InputDevice:gxtkInput()
		Return ginput
	EndMethod

	Method AudioDevice:gxtkAudio()
		Return gaudio
	EndMethod

	Method SetUpdateRate:Int(hertz:Int)
		updateRate = hertz
		If Not vloading Then SetFrameRate(updateRate)
		Return 0
	EndMethod

	Method MilliSecs:Int()
		Return BlitzMaxMillisecs() - startMillis
	EndMethod

	Method Loading:Int()
		Return vloading
	EndMethod

	Method OnCreate:Int()
		Return 0
	EndMethod

	Method OnUpdate:Int()
		Return 0
	EndMethod

	Method OnSuspend:Int()
		Return 0
	EndMethod

	Method OnResume:Int()
		Return 0
	EndMethod

	Method OnRender:Int()
		Return 0
	EndMethod

	Method OnLoading:Int()
		Return 0
	EndMethod
EndType

Type gxtkGraphics
	Field gmode:Int = 1
	Field ix:Float=1,iy:Float,jx:Float,jy:Float=1,tx:Float,ty:Float
	Field sx:Float=1,sy:Float=1,rot:Float=0

	Method Mode:Int()
		Return gmode
	EndMethod

	Method Cls:Int(r:Int = 0, g:Int = 0, b:Int = 0)
		BlitzMaxCls(r, g, b)
		Return 0
	EndMethod

	Method DrawPoint:Int(x:Float, y:Float)
		Local nx:Float = TransX(x,y)
		Local ny:Float = TransY(x,y)
		Plot nx, ny
	EndMethod

	Method LoadSurface:gxtkSurface(path:String)
		Local image:TImage = LoadImage("data/"+path)
		If image Then
			Local gs:gxtkSurface = New gxtkSurface
			gs.setImage(image)
			Return gs
		EndIf
		Return Null
	EndMethod

	Method BeginRender()
	EndMethod

	Method EndRender()
		Flip
	EndMethod

	Method SetColor:Int(r:Int, g:Int, b:Int)
		BlitzMaxSetColor(r, g, b)
		Return 0
	EndMethod

	Method SetAlpha:Int(a:Float)
		BlitzMaxSetAlpha(a)
		Return 0
	EndMethod

	Method SetBlend:Int(blend:Int)
		BlitzMaxSetBlend(blend)
		Return 0
	EndMethod

	Method Width:Int()
		Return GraphicsWidth()
	EndMethod

	Method Height:Int()
		Return GraphicsHeight()
	EndMethod

	Method SetScissor:Int(x:Int, y:Int, w:Int, h:Int)
		SetViewport(x, y, w, h) ' NOT TESTED!
		Return 0
	EndMethod

	Method TransX:Float(x:Float, y:Float)
		Return ix*x + jx*y + tx
	EndMethod

	Method TransY:Float(x:Float, y:Float)
		Return iy*x + jy*y + ty
	EndMethod

	Method SetMatrix:Int(ix:Float,iy:Float,jx:Float,jy:Float,tx:Float,ty:Float)
		Self.ix = ix ; Self.iy = iy
		Self.jx = jx ; Self.jy = jy
		Self.tx = tx ; Self.ty = ty
		sx = Sqr( (ix*ix) + (jx*jx) )
		sy = Sqr( (iy*iy) + (jy*jy) )
		rot = -Atan2( jx, ix )
		SetTransform( rot, sx, sy )
		Return 0
	EndMethod

	Method DrawSurface:Int(surface:gxtkSurface,x:Float,y:Float)
		Local nx:Float = TransX(x,y)
		Local ny:Float = TransY(x,y)
		DrawImage(surface.image, nx, ny, 0)
		Return 0
	EndMethod

	Method DrawSurface2:Int(surface:gxtkSurface,x:Float,y:Float, srcx:Int, srcy:Int, srcw:Int, srch:Int )
		Local nx:Float = TransX(x,y)
		Local ny:Float = TransY(x,y)
		DrawSubImageRect(surface.image, nx, ny, srcw, srch, srcx, srcy, srcw, srch)
		Return 0
	EndMethod

	Method DrawLine:Int( x1:Float,y1:Float,x2:Float,y2:Float )
		Local nx1:Float = TransX(x1,y1)
		Local ny1:Float = TransY(x1,y1)
		Local nx2:Float = TransX(x2,y2)
		Local ny2:Float = TransY(x2,y2)
		' Need to reset transform so that BlitzMax doesn't try to apply rotation
		SetTransform( 0, 1, 1 )
		BlitzMaxDrawLine(nx1, ny1, nx2, ny2)
		SetTransform( rot, sx, sy )
		Return 0
	EndMethod

	Method DrawOval:Int( x:Float, y:Float, w:Float, h:Float )
		Local nx:Float = TransX(x,y)
		Local ny:Float = TransY(x,y)
		BlitzMaxDrawOval(nx, ny, w, h)
		Return 0
	EndMethod

	Method DrawPoly:Int(vertices:Float[])
		' setting the origin to use the current rotation translation
		SetOrigin(TransX(0,0), TransY(0,0))
		BlitzMaxDrawPoly( vertices )
		SetOrigin(0, 0)
		Return 0
	EndMethod

	Method DrawRect:Int( x:Float, y:Float, w:Float, h:Float )
		Local nx:Float = TransX(x,y)
		Local ny:Float = TransY(x,y)
		BlitzMaxDrawRect(nx, ny, w, h)
		Return 0
	EndMethod
EndType

Type gxtkInput
	Method MouseX:Float()
		Return BRL.PolledInput.MouseX()
	EndMethod

	Method MouseY:Float()
		Return BRL.PolledInput.MouseY()
	EndMethod

	Method KeyDown:Int( key:Int )
		if( key = 384 ) key = 1 ' change TOUCH0 to MOUSE_LMB

		If( key >= 1 And key <= 3 )
			Return BRL.PolledInput.MouseDown( key )
		EndIf
		If key < 256
			Return BRL.PolledInput.KeyDown( key )
		Else
			Return 0
		EndIf
	EndMethod

	Method KeyHit:Int( key:Int )
		if( key = 384 ) key = 1 ' change TOUCH0 to MOUSE_LMB
		If( key >= 1 And key <= 3 )
			Return BRL.PolledInput.MouseHit( key )
		EndIf
		If key < 256
			Return BRL.PolledInput.KeyHit( key )
		Else
			Return 0
		EndIf
	EndMethod

	Method GetChar:Int()
		Return BRL.PolledInput.GetChar()
	EndMethod

	Method JoyX:Int( index:Int )
		Return Pub.FreeJoy.JoyX( index )
	EndMethod

	Method JoyY:Int( index:Int )
		Return Pub.FreeJoy.JoyY( index )
	EndMethod

	Method JoyZ:Int( index:Int )
		Return Pub.FreeJoy.JoyZ( index )
	EndMethod

	Method TouchX:Float( index:Int )
		Return BRL.PolledInput.MouseX()
	EndMethod

	Method TouchY:Float( index:Int )
		Return BRL.PolledInput.MouseY()
	EndMethod

	Method AccelX:Int()
		return 0
	EndMethod

	Method AccelY:Int()
		return 0
	EndMethod

	Method AccelZ:Int()
		return 0
	EndMethod

	Method SetKeyboardEnabled:Int( enabled:int )
		Return 0
	EndMethod
EndType

Type gxtkChannel
	Field channel:TChannel	' null then not playing
	Field sample:gxtkSample
	Field loops:int
	'Field transform:SoundTransform=new SoundTransform()
	'Field pausepos:Number
	Field state:int

	Method New()
		channel = New TChannel
	EndMethod
EndType

Type gxtkAudio
	Field amusicState:Int = 0
	Field channels:gxtkChannel[] = New gxtkChannel[33]

	Method New()
		For local i:Int = 0 To 33 - 1
			channels[i] = New gxtkChannel
		Next
	EndMethod

	Method MusicState:Int()
'		If( musicState = 1 And music.isPlaying() = False )
'			musicState = 0;
'		Endif
		Return amusicState
	EndMethod

	Method PlayMusic:Int( path:String, flags:Int )
		Return 0
	EndMethod

	Method ChannelState:int( channel:int )
		Return -1
	EndMethod

	Method StopMusic()
	EndMethod

	Method StopChannel( channel:Int )
	EndMethod

	Method PlaySample( sound:gxtkSample, channel:Int, flags:Int )
		Local chan:gxtkChannel = channels[channel]

		'If chan.state <> 0 Then chan.channel.Stop() <-- this crashes after the first play!?

		chan.sample = sound
		'chan.loops = flags ? 0x7fffffff : 0;
		'chan.channel = sample.sound.play( 0,chan.loops,chan.transform );
		'chan.channel = sound
		chan.state=1

		PlaySound( sound.sound, chan.channel )
	EndMethod

	Method SetPan( channel:Int, pan:Float )
		Local chan:gxtkChannel = channels[channel]
		chan.channel.SetPan(pan)
	EndMethod

	Method SetRate( channel:Int, rate:Float )
		Local chan:gxtkChannel = channels[channel]
		chan.channel.SetRate(rate)
	EndMethod

	Method PauseMusic:Int()
		Return 0
	EndMethod

	Method ResumeMusic:Int()
		Return 0
	EndMethod

	Method SetMusicVolume:Int( volume:Float )
		Return 0
	EndMethod

	Method SetVolume:Int( channel:Int, volume:Float )
		Local chan:gxtkChannel = channels[channel]
		chan.channel.SetVolume(volume)
		Return 0
	EndMethod

	Method LoadSample:gxtkSample( path:String )
		Local extension:String = ExtractExt( path)
		If extension = "ogg" Or extension = "wav" Then
			Local sound:TSound = LoadSound("data/"+path)
			If sound Then
				Local gs:gxtkSample = New gxtkSample
				gs.setSound(sound)
				Return gs
			EndIf
		Else
			RuntimeError "BlitzMax can only use ogg and wav file formats"
		EndIf
		Return Null
	EndMethod
EndType

Type gxtkSample
	Field sound:TSound

	Method setSound(sound:TSound)
		Self.sound = sound
	EndMethod

	Method Discard()
		Self.sound = null
	EndMethod
EndType

Function BlitzMaxDrawPoly:Int(vertices:Float[])
	DrawPoly vertices
	Return 0
EndFunction

Function BlitzMaxDrawRect:Int( x:Float, y:Float, w:Float, h:Float )
	DrawRect x, y, w, h
	Return 0
EndFunction

Function BlitzMaxDrawOval:Int( x:Float, y:Float, w:Float, h:Float )
	DrawOval x, y, w, h
	Return 0
EndFunction

Function BlitzMaxDrawLine:Int( x1:Float,y1:Float,x2:Float,y2:Float )
	DrawLine x1, y1, x2, y2
	Return 0
EndFunction

Function BlitzMaxMillisecs:Int()
	Return MilliSecs()
EndFunction

Function BlitzMaxSetColor(r:Int, g:Int, b:Int)
	SetColor(r, g, b)
EndFunction

Function BlitzMaxSetBlend(blend:Int)
	Select blend
		Case 0
			SetBlend( ALPHABLEND )
		Case 1
			SetBlend( LIGHTBLEND )
	End Select
EndFunction

Function BlitzMaxSetAlpha(a:Float)
	SetAlpha(a)
EndFunction

Function BlitzMaxCls(r:Int = 0, g:Int = 0, b:Int = 0)
	SetClsColor(r, g, b)
	Cls
EndFunction

Type gxtkSurface
	Field w:Int, h:Int
	Field image:TImage

	Method setImage(image:TImage)
		Self.image = image
	EndMethod

	Method Width:Int()
		Return image.Width
	EndMethod

	Method Height:Int()
		Return image.Height
	EndMethod

	Method Discard()
	EndMethod
EndType

' ***** End mojo.bmax.bmx ******

' ***** Start mojo.bmax.bmx ******

Global app:gxtkApp

Type gxtkApp
	Field ginput:gxtkInput
	Field gaudio:gxtkAudio
	Field ggraphics:gxtkGraphics

	Field dead:Int=0
	Field suspended:Int=0
	Field vloading:Int=0
	Field maxloading:Int=0
	Field updateRate:Int=0
	Field nextUpdate:Float=0
	Field updatePeriod:Float=0
	Field startMillis:Float=0

	Method New()' gxtkApp()
		app=Self
		ggraphics=New gxtkGraphics
	EndMethod

	Method Setup()
		ginput=New gxtkInput
		gaudio=New gxtkAudio

		bb_input_SetInputDevice(ginput)
		bb_audio_SetAudioDevice(gaudio)

		startMillis=BlitzMaxMillisecs()

		SetFrameRate( 0 )

		InvokeOnCreate()
		InvokeOnRender()
		Update()
	EndMethod

	Method Update()
		While Not AppTerminate()
			Local updates:Int = 0

			Local cont:Int = 1
			While (cont)
				nextUpdate:+updatePeriod
				InvokeOnUpdate()
				If Not updatePeriod Then cont = 0
				If nextUpdate>BlitzMaxMillisecs() Then cont = 0
				updates:+1
				If updates = 7 Then
					nextUpdate = BlitzMaxMillisecs()
					cont = 0
				EndIf
			Wend
			InvokeOnRender()
		Wend
	EndMethod

	Method InvokeOnCreate()
		If dead Return
		dead = 1
		OnCreate()
		dead = 0
	EndMethod

	Method InvokeOnUpdate()
		If dead Or suspended Or Not updateRate Or vloading Return
		OnUpdate()
	EndMethod

	Method InvokeOnRender()
		If dead Or suspended Return
		ggraphics.BeginRender()
		If vloading
			OnLoading()
		Else
			OnRender()
		EndIf
		ggraphics.EndRender()
	EndMethod

	Method SetFrameRate( fps:Int )
		If fps
			updatePeriod=1000.0/fps
			nextUpdate=BlitzMaxMillisecs() +updatePeriod
		Else
			updatePeriod=0
		EndIf
	EndMethod

	Method LoadState:String()
'		var file:SharedObject=SharedObject.getLocal( "gxtkapp" );
'		var state:String=file.data.state;
'		file.close();
'		if( state ) return state;
		Return ""
	EndMethod

	Method SaveState:Int( state:String )
'		var file:SharedObject=SharedObject.getLocal( "gxtkapp" );
'		file.data.state=state;
'		file.close();
		Return 0
	EndMethod

	Method LoadString:String( path:String )
		path = "data/" + path
		Return LoadText( path )
	EndMethod

	' ***** GXTK API *****

	Method GraphicsDevice:gxtkGraphics()
		Return ggraphics
	EndMethod

	Method InputDevice:gxtkInput()
		Return ginput
	EndMethod

	Method AudioDevice:gxtkAudio()
		Return gaudio
	EndMethod

	Method SetUpdateRate:Int(hertz:Int)
		updateRate = hertz
		If Not vloading Then SetFrameRate(updateRate)
		Return 0
	EndMethod

	Method MilliSecs:Int()
		Return BlitzMaxMillisecs() - startMillis
	EndMethod

	Method Loading:Int()
		Return vloading
	EndMethod

	Method OnCreate:Int()
		Return 0
	EndMethod

	Method OnUpdate:Int()
		Return 0
	EndMethod

	Method OnSuspend:Int()
		Return 0
	EndMethod

	Method OnResume:Int()
		Return 0
	EndMethod

	Method OnRender:Int()
		Return 0
	EndMethod

	Method OnLoading:Int()
		Return 0
	EndMethod
EndType

Type gxtkGraphics
	Field gmode:Int = 1

	Method Mode:Int()
		Return gmode
	EndMethod

	Method Cls:Int(r:Int = 0, g:Int = 0, b:Int = 0)
		BlitzMaxCls(r, g, b)
		Return 0
	EndMethod

	Method DrawPoint:Int(x:Float, y:Float)
		Plot x, y
	EndMethod

	Method LoadSurface:gxtkSurface(path:String)
		Local image:TImage = LoadImage("data/"+path)
		If image Then
			Local gs:gxtkSurface = New gxtkSurface
			gs.setImage(image)
			Return gs
		EndIf
		Return Null
	EndMethod

	Method BeginRender()
	EndMethod

	Method EndRender()
		Flip
	EndMethod

	Method SetColor:Int(r:Int, g:Int, b:Int)
		BlitzMaxSetColor(r, g, b)
		Return 0
	EndMethod

	Method SetAlpha:Int(a:Float)
		BlitzMaxSetAlpha(a)
		Return 0
	EndMethod

	Method SetBlend:Int(blend:Int)
		BlitzMaxSetBlend(blend)
		Return 0
	EndMethod

	Method Width:Int()
		Return GraphicsWidth()
	EndMethod

	Method Height:Int()
		Return GraphicsHeight()
	EndMethod

	Method SetScissor:Int(x:Int, y:Int, w:Int, h:Int)
		SetViewport(x, y, w, h) ' NOT TESTED!
		Return 0
	EndMethod

	Method SetMatrix:Int(ix:Float,iy:Float,jx:Float,jy:Float,tx:Float,ty:Float)
		Local sx:Float = Sqr( (ix*ix) + (jx*jx) )
		Local sy:Float = Sqr( (iy*iy) + (jy*jy) )
		Local rot:Float = -Atan2( jx, ix )
		SetTransform( rot, sx, sy )
		SetOrigin( tx, ty )
		Return 0
	EndMethod

	Method DrawSurface:Int(surface:gxtkSurface,x:Float,y:Float)
		DrawImage(surface.image, x, y, 0)
		Return 0
	EndMethod

	Method DrawSurface2:Int(surface:gxtkSurface,x:Float,y:Float, srcx:Int, srcy:Int, srcw:Int, srch:Int )
		DrawSubImageRect(surface.image, x, y, srcw, srch, srcx, srcy, srcw, srch)
		Return 0
	EndMethod

	Method DrawLine:Int( x1:Float,y1:Float,x2:Float,y2:Float )
		BlitzMaxDrawLine(x1, y1, x2, y2)
		Return 0
	EndMethod

	Method DrawOval:Int( x:Float, y:Float, w:Float, h:Float )
		BlitzMaxDrawOval(x, y, w, h)
		Return 0
	EndMethod

	Method DrawPoly:Int(vertices:Float[])
		BlitzMaxDrawPoly( vertices )
		Return 0
	EndMethod

	Method DrawRect:Int( x:Float, y:Float, w:Float, h:Float )
		BlitzMaxDrawRect(x, y, w, h)
		Return 0
	EndMethod
EndType

Type gxtkInput
	Method MouseX:Float()
		Return BRL.PolledInput.MouseX()
	EndMethod

	Method MouseY:Float()
		Return BRL.PolledInput.MouseY()
	EndMethod

	Method KeyDown:Int( key:Int )
		if( key = 384 ) key = 1 ' change TOUCH0 to MOUSE_LMB

		If( key >= 1 And key <= 3 )
			Return BRL.PolledInput.MouseDown( key )
		EndIf
		If key < 256
			Return BRL.PolledInput.KeyDown( key )
		Else
			Return 0
		EndIf
	EndMethod

	Method KeyHit:Int( key:Int )
		if( key = 384 ) key = 1 ' change TOUCH0 to MOUSE_LMB
		If( key >= 1 And key <= 3 )
			Return BRL.PolledInput.MouseHit( key )
		EndIf
		If key < 256
			Return BRL.PolledInput.KeyHit( key )
		Else
			Return 0
		EndIf
	EndMethod

	Method GetChar:Int()
		Return BRL.PolledInput.GetChar()
	EndMethod

	Method JoyX:Int( index:Int )
		Return Pub.FreeJoy.JoyX( index )
	EndMethod

	Method JoyY:Int( index:Int )
		Return Pub.FreeJoy.JoyY( index )
	EndMethod

	Method JoyZ:Int( index:Int )
		Return Pub.FreeJoy.JoyZ( index )
	EndMethod

	Method TouchX:Float( index:Int )
		Return BRL.PolledInput.MouseX()
	EndMethod

	Method TouchY:Float( index:Int )
		Return BRL.PolledInput.MouseY()
	EndMethod

	Method AccelX:Int()
		return 0
	EndMethod

	Method AccelY:Int()
		return 0
	EndMethod

	Method AccelZ:Int()
		return 0
	EndMethod

	Method SetKeyboardEnabled:Int( enabled:int )
		Return 0
	EndMethod
EndType

Type gxtkChannel
	Field channel:TChannel	' null then not playing
	Field sample:gxtkSample
	Field loops:int
	'Field transform:SoundTransform=new SoundTransform()
	'Field pausepos:Number
	Field state:int

	Method New()
		channel = New TChannel
	EndMethod
EndType

Type gxtkAudio
	Field amusicState:Int = 0
	Field channels:gxtkChannel[] = New gxtkChannel[33]

	Method New()
		For local i:Int = 0 To 33 - 1
			channels[i] = New gxtkChannel
		Next
	EndMethod

	Method MusicState:Int()
'		If( musicState = 1 And music.isPlaying() = False )
'			musicState = 0;
'		Endif
		Return amusicState
	EndMethod

	Method PlayMusic:Int( path:String, flags:Int )
		Return 0
	EndMethod

	Method ChannelState:int( channel:int )
		Return -1
	EndMethod

	Method StopMusic()
	EndMethod

	Method StopChannel( channel:Int )
	EndMethod

	Method PlaySample( sound:gxtkSample, channel:Int, flags:Int )
		Local chan:gxtkChannel = channels[channel]

		'If chan.state <> 0 Then chan.channel.Stop() <-- this crashes after the first play!?

		chan.sample = sound
		'chan.loops = flags ? 0x7fffffff : 0;
		'chan.channel = sample.sound.play( 0,chan.loops,chan.transform );
		'chan.channel = sound
		chan.state=1

		PlaySound( sound.sound, chan.channel )
	EndMethod

	Method SetPan( channel:Int, pan:Float )
		Local chan:gxtkChannel = channels[channel]
		chan.channel.SetPan(pan)
	EndMethod

	Method SetRate( channel:Int, rate:Float )
		Local chan:gxtkChannel = channels[channel]
		chan.channel.SetRate(rate)
	EndMethod

	Method PauseMusic:Int()
		Return 0
	EndMethod

	Method ResumeMusic:Int()
		Return 0
	EndMethod

	Method SetMusicVolume:Int( volume:Float )
		Return 0
	EndMethod

	Method SetVolume:Int( channel:Int, volume:Float )
		Local chan:gxtkChannel = channels[channel]
		chan.channel.SetVolume(volume)
		Return 0
	EndMethod

	Method LoadSample:gxtkSample( path:String )
		Local extension:String = ExtractExt( path)
		If extension = "ogg" Or extension = "wav" Then
			Local sound:TSound = LoadSound("data/"+path)
			If sound Then
				Local gs:gxtkSample = New gxtkSample
				gs.setSound(sound)
				Return gs
			EndIf
		Else
			RuntimeError "BlitzMax can only use ogg and wav file formats"
		EndIf
		Return Null
	EndMethod
EndType

Type gxtkSample
	Field sound:TSound

	Method setSound(sound:TSound)
		Self.sound = sound
	EndMethod

	Method Discard()
		Self.sound = null
	EndMethod
EndType

Function BlitzMaxDrawPoly:Int(vertices:Float[])
	DrawPoly vertices
	Return 0
EndFunction

Function BlitzMaxDrawRect:Int( x:Float, y:Float, w:Float, h:Float )
	DrawRect x, y, w, h
	Return 0
EndFunction

Function BlitzMaxDrawOval:Int( x:Float, y:Float, w:Float, h:Float )
	DrawOval x, y, w, h
	Return 0
EndFunction

Function BlitzMaxDrawLine:Int( x1:Float,y1:Float,x2:Float,y2:Float )
	DrawLine x1, y1, x2, y2
	Return 0
EndFunction

Function BlitzMaxMillisecs:Int()
	Return MilliSecs()
EndFunction

Function BlitzMaxSetColor(r:Int, g:Int, b:Int)
	SetColor(r, g, b)
EndFunction

Function BlitzMaxSetBlend(blend:Int)
	Select blend
		Case 0
			SetBlend( ALPHABLEND )
		Case 1
			SetBlend( LIGHTBLEND )
	End Select
EndFunction

Function BlitzMaxSetAlpha(a:Float)
	SetAlpha(a)
EndFunction

Function BlitzMaxCls(r:Int = 0, g:Int = 0, b:Int = 0)
	SetClsColor(r, g, b)
	Cls
EndFunction

Type gxtkSurface
	Field w:Int, h:Int
	Field image:TImage

	Method setImage(image:TImage)
		Self.image = image
	EndMethod

	Method Width:Int()
		Return image.Width
	EndMethod

	Method Height:Int()
		Return image.Height
	EndMethod

	Method Discard()
	EndMethod
EndType

' ***** End mojo.bmax.bmx ******


Added example2

Added example2

SuperStrict
Import htbaapub.xmlrpc

Local client:TXMLRPC_Client = New TXMLRPC_Client.Create()
client.SetTransport(New TXMLRPC_Transport_Http.Create("www.upcdatabase.com", "/rpc"))

Local parameters:TXMLRPC_Call_Parameters = TXMLRPC_Call_Parameters.Create(xmlrpc_vector_array)
parameters.AppendString(Null, "0045496718749")

Local response:TXMLRPC_Response_Data = client.Call("lookupEAN", parameters)

Local description:TXMLRPC_Value_String = TXMLRPC_Value_String(response.data.ValueForKey("description"))
Local issuerCountry:TXMLRPC_Value_String = TXMLRPC_Value_String(response.data.ValueForKey("issuerCountry"))
Local ean:TXMLRPC_Value_String = TXMLRPC_Value_String(response.data.ValueForKey("ean"))

Print description.name + ": " + description.ToString()
Print description.name + ": " + issuerCountry.ToString()
Print description.name + ": " + ean.ToString()

error: pathspec 'examples/example2.bmx' did not match any file(s) known to git


Create mandelbrot.bmx

Create mandelbrot.bmx

SuperStrict
Framework brl.GLGraphics
Import brl.TIMER
Import brl.TextStream
Import pub.OpenGL
Import pub.Glew
Import brl.Retro
Import brl.PNGLoader

Const GW:Int = 1120, GH:Int = 630
Const aspectratio:Float = 16.0 / 9.0

If AppArgs.Length > 1
	TAnimFrame.LoadFromFile(AppArgs[1])
End If

Global TIMER:TTimer = CreateTimer(30)
Global VERTEX_SHADER_CODE:String = LoadText("vs.glsl")
Global FRAGMENT_SHADER_CODE:String = LoadText("fs.glsl")

InitGL
Global ProgramObj:Int
InitShaders
glUseProgram(ProgramObj)

Global camS:Float = 0.02
Global camX:Float = 0.0, camY:Float = 0.0
Global camZoom:Float = 4.0

Global itr:Int = 50
Global uk:Int = 0
Global threshold:Float = 4.0

Global v1x:Float = 1.0, v1y:Float = 0.0
Global v2x:Float = 1.0, v2y:Float = 0.0
Global v3x:Float = 1.0, v3y:Float = 0.0

Global p1x:Float = -1.0, p1y:Float = 0.0
Global p2x:Float = 1.0, p2y:Float = 0.0

Global p3x:Float = 0.0, p3y:Float = -1.0
Global p4x:Float = 0.0, p4y:Float = 1.0

Global orbittrapradius1:Float = 0.25
Global orbittrapradius2:Float = 0.25
Global aa:Int = 0

Global disphelp:Int = 0

Global cf:TAnimFrame, cflink:TLink

'Render()
'SaveSceenshot()
'End

Global MDown:Int, MX:Int, MY:Int
Global zwsp:Float
While Not KeyHit(KEY_ESCAPE)
	MDown = MouseDown(MOUSE_LEFT) Shl 2 + MouseDown(MOUSE_MIDDLE) Shl 1 + MouseDown(MOUSE_RIGHT)
	MX = MouseX()
	MY = MouseY()

	CheckInput()

	Render()

	If disphelp
		glUseProgram(0)
		DrawHelp
		glUseProgram(ProgramObj)
	End If

	Flip 0
	glCls
	WaitTimer TIMER
Wend
End

Function CheckInput()
	If KeyDown(KEY_2) camS:*1.05 Else If KeyDown(KEY_1) camS:/1.05

	itr:+KeyDown(KEY_4) - KeyDown(KEY_3)
	uk:+KeyHit(KEY_V) - KeyHit(KEY_C)

	If KeyDown(KEY_Y) camZoom:*(1.01) Else If KeyDown(KEY_X) camZoom:/(1.01)

	If KeyDown(KEY_6) threshold:*(1.05) Else If KeyDown(KEY_5) threshold:/(1.05)

	If KeyDown(KEY_8) orbittrapradius1:*(1.05) Else If KeyDown(KEY_7) orbittrapradius1:/(1.05)
	If KeyDown(KEY_0) orbittrapradius2:*(1.05) Else If KeyDown(KEY_9) orbittrapradius2:/(1.05)

	If KeyHit(KEY_B) Then aa = 1 - aa

	camX:+(KeyDown(KEY_D) - KeyDown(KEY_A)) * camS
	camY:+(KeyDown(KEY_W) - KeyDown(KEY_S)) * camS

	v1x:+(KeyDown(KEY_R) - KeyDown(KEY_F)) * camS
	v1y:+(KeyDown(KEY_T) - KeyDown(KEY_G)) * camS
	v2x:+(KeyDown(KEY_Z) - KeyDown(KEY_H)) * camS
	v2y:+(KeyDown(KEY_U) - KeyDown(KEY_J)) * camS
	v3x:+(KeyDown(KEY_I) - KeyDown(KEY_K)) * camS
	v3y:+(KeyDown(KEY_O) - KeyDown(KEY_L)) * camS

	If MDown & %100
		If KeyDown(KEY_LCONTROL)
			p3x = camX + camZoom * MX / Float(GW) - camZoom / 2.0
			p3y = camY - camZoom / aspectratio * MY / Float(GH) + camZoom / aspectratio / 2.0
		Else
			p1x = camX + camZoom * MX / Float(GW) - camZoom / 2.0
			p1y = camY - camZoom / aspectratio * MY / Float(GH) + camZoom / aspectratio / 2.0
		End If
	End If
	If MDown & %001
		If KeyDown(KEY_LCONTROL)
			p4x = camX + camZoom * MX / Float(GW) - camZoom / 2.0
			p4y = camY - camZoom / aspectratio * MY / Float(GH) + camZoom / aspectratio / 2.0
		Else
			p2x = camX + camZoom * MX / Float(GW) - camZoom / 2.0
			p2y = camY - camZoom / aspectratio * MY / Float(GH) + camZoom / aspectratio / 2.0
		End If
	End If

	If KeyHit(KEY_ENTER) disphelp = 1 - disphelp

	If KeyHit(KEY_DOWN)
		If KeyDown(KEY_RCONTROL)
			TAnimFrame.AddFrame(cflink, 1)
			Print "frame modified"
		Else
			cf = TAnimFrame.AddFrame(cflink) Print "frame added"
			If cflink = Null Then cflink = TAnimFrame.list.FindLink(cf) Else cflink = cflink.NextLink()
		End If
	End If

	If KeyHit(KEY_RIGHT)
		If KeyDown(KEY_RCONTROL)
			cflink = TAnimFrame.list.LastLink()
			cf = TAnimFrame(TAnimFrame.list.Last())
			If cf Then cf.setGlobalsToFrame()
		Else If cflink.NextLink()
			cflink = cflink.NextLink()
			cf = TAnimFrame(TAnimFrame(cflink.Value()))
			If cf Then cf.setGlobalsToFrame()
		End If
	End If

	If KeyHit(KEY_LEFT)
		If KeyDown(KEY_RCONTROL)
			cflink = TAnimFrame.list.FirstLink()
			cf = TAnimFrame(TAnimFrame.list.First())
			If cf Then cf.setGlobalsToFrame()
		Else If cflink.PrevLink()
			cflink = cflink.PrevLink()
			cf = TAnimFrame(TAnimFrame(cflink.Value()))
			If cf Then cf.setGlobalsToFrame()
		End If
	End If

	If KeyHit(KEY_BACKSPACE) And cf
		cflink = cflink.PrevLink()
		cf.list.Remove(cf)
		If cf Then cf = TAnimFrame(cflink.Value())
		Print "frame deleted"
	End If

	If cf
		Local timevar:TFloat = TFloat(cf.getVar("time"))
		If KeyDown(KEY_PAGEUP) Then timevar.v:*1.1 Print timevar.v Else ..
		If KeyDown(KEY_PAGEDOWN) Then timevar.v:/1.1 Print timevar.v
	End If

	If KeyHit(KEY_RSHIFT) And cf Then cf.setGlobalsToFrame()

	If KeyHit(KEY_UP) Then TAnimFrame.PlayAnim(0.04)

	If KeyHit(KEY_F10) Then TAnimFrame.SaveToFile("anim" + MilliSecs() + ".txt")

	If KeyHit(KEY_F11)
		If KeyDown(KEY_RCONTROL)
			TAnimFrame.SaveAnim(0.02, "anim" + MilliSecs(), Input("Skip Nr Frames:").ToInt())
		Else
			TAnimFrame.SaveAnim(0.02, "anim" + MilliSecs())
		End If
	End If

	If KeyHit(KEY_F12)
		If KeyDown(KEY_RCONTROL)
			SaveSceenshot(Input("resolution multiplier:").ToInt())
		Else
			SaveSceenshot(4)
		End If
	End If
End Function

Function Render(x:Int = 0, y:Int = 0, s:Int = 1)
	glUniform1f(glGetUniformLocation(ProgramObj, "pixelsize"), (camZoom / Float(s)) / Float(GW))
	glUniform1i(glGetUniformLocation(ProgramObj, "MaxItr"), itr)
	glUniform1i(glGetUniformLocation(ProgramObj, "uk"), uk)
	glUniform1f(glGetUniformLocation(ProgramObj, "threshold"), threshold * threshold)
	glUniform2f(glGetUniformLocation(ProgramObj, "v1"), v1x, v1y)
	glUniform2f(glGetUniformLocation(ProgramObj, "v2"), v2x, v2y)
	glUniform2f(glGetUniformLocation(ProgramObj, "v3"), v3x, v3y)
	glUniform2f(glGetUniformLocation(ProgramObj, "p1"), p1x, p1y)
	glUniform2f(glGetUniformLocation(ProgramObj, "p2"), p2x, p2y)
	glUniform2f(glGetUniformLocation(ProgramObj, "p3"), p3x, p3y)
	glUniform2f(glGetUniformLocation(ProgramObj, "p4"), p4x, p4y)
	glUniform1f(glGetUniformLocation(ProgramObj, "orbittrapradius1"), orbittrapradius1)
	glUniform1f(glGetUniformLocation(ProgramObj, "orbittrapradius2"), orbittrapradius2)
	glUniform1i(glGetUniformLocation(ProgramObj, "aa"), aa)

	Local vx:Float, vy:Float
	Local w:Float, h:Float
	vy = camZoom / 2.0

	w = camZoom / Float(s)
	h = camZoom / Float(s) / aspectratio

	vx = camX - vy + w * x
	vy = camY + vy / aspectratio - h * y

	glBegin(GL_QUADS)
		glTexCoord2f(vx, vy) ;glVertex2i(0, 0)
		glTexCoord2f(vx + w, vy) ;glVertex2i(GW, 0)
		glTexCoord2f(vx + w, vy - h) ;glVertex2i(GW, GH)
		glTexCoord2f(vx, vy - h) ;glVertex2i(0, GH)
	glEnd
End Function

Function InitGL()
	Graphics GW, GH', 32, 60, 0
	SetGraphicsDriver(GLGraphicsDriver())
	glewInit()

	glMatrixMode(GL_PROJECTION)
	glLoadIdentity()

	glOrtho(0, GW, GH, 0, -1, 1)

	glMatrixMode(GL_MODELVIEW)
	glLoadIdentity()
End Function

Function glCls()
	glClear GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT
End Function

Function InitShaders()
	ProgramObj = glCreateProgram()
	Local VertexShdr:Int = glCreateShader(GL_VERTEX_SHADER_ARB)
	Local FragmentShdr:Int = glCreateShader(GL_FRAGMENT_SHADER_ARB)

	Local vsc:Byte Ptr = VERTEX_SHADER_CODE.ToCString()
	Local vsl:Int = VERTEX_SHADER_CODE.Length
	Local fsc:Byte Ptr = FRAGMENT_SHADER_CODE.ToCString()
	Local fsl:Int = FRAGMENT_SHADER_CODE.Length

	glShaderSource(VertexShdr, 1, Varptr vsc, Varptr vsl)
		glShaderSource(FragmentShdr, 1, Varptr fsc, Varptr fsl)

		MemFree(vsc)
	MemFree(fsc)

	glCompileShader(VertexShdr) ;CheckForErrors(VertexShdr)
	glCompileShader(FragmentShdr) ;CheckForErrors(FragmentShdr)

	glAttachShader(ProgramObj, VertexShdr)
	glAttachShader(ProgramObj, FragmentShdr)

	glDeleteShader(VertexShdr)
	glDeleteShader(FragmentShdr)

	glLinkProgram(ProgramObj) ;CheckForErrors(ProgramObj)
End Function

Function CheckForErrors(ShaderObject:Int)
	Local ErrorLength:Int

	glGetShaderiv(ShaderObject, GL_OBJECT_INFO_LOG_LENGTH_ARB, Varptr ErrorLength)

		If ErrorLength
		Local Message:Byte[ErrorLength], Dummy:Int

		glGetShaderInfoLog(ShaderObject, ErrorLength, Varptr Dummy, Varptr Message[0])
		'		SaveText("Shader object '" + ShaderObject + "':~n" + StringFromCharArray(Message), "error.txt")
		WriteStdout "Shader object '" + ShaderObject + "':~n" + StringFromCharArray(Message)
		WriteStdout "~n"
	EndIf
End Function

Function StringFromCharArray:String(Array:Byte[])
	Local Output:String
	For Local I:Int = 0 To Array.Length - 1
		Output:+Chr(Array[I])
	Next

	Return Output
End Function

Function SaveSceenshot(s:Int = 3, fn:String = "", compression:Int = 5, infosdtout:Int = 1)
	Local cnt:Int
	Local pm:TPixmap = CreatePixmap(GW * s, GH * s, PF_BGRA8888)
	Local c:Byte Ptr = MemAlloc(3 * (GW + GW Mod 4) * (GH + GH Mod 4))

	For Local x1:Int = 0 Until s
		If infosdtout WriteStdout (x1 + 1) + " of " + s + "~n"
		For Local y1:Int = 0 Until s
			Render(x1, y1, s)
			glReadPixels(0, 0, (GW + GW Mod 4), (GH + GH Mod 4), GL_RGB, GL_UNSIGNED_BYTE, c)
			cnt = 0
			For Local y:Int = GH - 1 To 0 Step - 1
				For Local x:Int = 0 Until GW
					WritePixel(pm, x1 * GW + x, y1 * GH + y, $ff000000 + $10000 * c[cnt] + $100 * c[cnt + 1] + c[cnt + 2])
					cnt:+3
				Next
				cnt:+3 * (GW Mod 4)
			Next
		Next
	Next

	If infosdtout WriteStdout "Saving..."
	If fn = "" Then fn = (MilliSecs()) + ".png"
	SavePixmapPNG(pm, fn, compression)
	If infosdtout WriteStdout "Done.~n~n"
End Function

Function DrawHelp()
	GLDrawText "cam =" + camX + ", " + camY, 0, 0
	GLDrawText "v1  =" + v1x + ", " + v1y, 0, 16
	GLDrawText "v2  =" + v2x + ", " + v2y, 0, 32
	GLDrawText "v3  =" + v3x + ", " + v3y, 0, 48
	GLDrawText "p1  =" + p1x + ", " + p1y, 0, 64
	GLDrawText "p2  =" + p2x + ", " + p2y, 0, 80
	GLDrawText "p3  =" + p3x + ", " + p3y, 0, 96
	GLDrawText "p4  =" + p4x + ", " + p4y, 0, 112
	GLDrawText "thd =" + threshold, 0, 128
	GLDrawText "otr1=" + orbittrapradius1, 0, 144
	GLDrawText "otr2=" + orbittrapradius2, 0, 160
	GLDrawText "itr =" + itr, 0, 176
	GLDrawText "k   =" + uk, 0, 192
End Function

Function Catmul:Float(v0:Float, v1:Float, v2:Float, v3:Float, x:Float)
	Local a0:Float, a1:Float, a2:Float, a3:Float, x2:Float

	x2 = x * x
	a0 = -0.5 * v0 + 1.5 * v1 - 1.5 * v2 + 0.5 * v3
	a1 = v0 - 2.5 * v1 + 2 * v2 - 0.5 * v3
	a2 = -0.5 * v0 + 0.5 * v2
	a3 = v1
'	a0 = v3 - v2 - v0 + v1
'	a1 = v0 - v1 - a0
'	a2 = v2 - v0
'	a3 = v1

	Return a0 * x * x2 + a1 * x2 + a2 * x + a3
End Function

Function Clip:Float(v1:Float, v2:Float, x:Float)
	Return x * v2 + v1 * (1.0 - x)
End Function

Type TAnimFrame
	Global list:TList = CreateList()

	Field varlist:TList

	Method New()
		varlist = CreateList()
	End Method

	Method Del()
		list.Remove(Self)
	End Method

	Function AddFrame:TAnimFrame(link:TLink = Null, modify:Int = 0)
		Local t:TAnimFrame
		If modify
			If link = Null
				t = New TAnimFrame
				t.list.AddLast(t)
			Else
				t = TAnimFrame(link.Value())
			End If
		Else
			t = New TAnimFrame
			If link = Null
				t.list.AddLast(t)
			Else
				t.list.InsertAfterLink(t, link)
			End If
		End If

		Local timevar:Object = t.getVar("time")
		If timevar = Null
			t.setVar("time", TFloat.N(1.0))
		Else
			t.setVar("time", TFloat(timevar))
		End If

		t.setVar("camX", TFloat.N(camX))
		t.setVar("camY", TFloat.N(camY))

		t.setVar("camZoom", TFloat.N(camZoom))

		t.setVar("itr", TInt.N(itr))

		t.setVar("v1x", TFloat.N(v1x))
		t.setVar("v1y", TFloat.N(v1y))
		t.setVar("v2x", TFloat.N(v2x))
		t.setVar("v2y", TFloat.N(v2y))
		t.setVar("v3x", TFloat.N(v3x))
		t.setVar("v3y", TFloat.N(v3y))

		t.setVar("p1x", TFloat.N(p1x))
		t.setVar("p1y", TFloat.N(p1y))
		t.setVar("p2x", TFloat.N(p2x))
		t.setVar("p2y", TFloat.N(p2y))
		t.setVar("p3x", TFloat.N(p3x))
		t.setVar("p3y", TFloat.N(p3y))
		t.setVar("p4x", TFloat.N(p4x))
		t.setVar("p4y", TFloat.N(p4y))

		t.setVar("uk", TInt.N(uk))

		t.setVar("threshold", TFloat.N(threshold))

		t.setVar("orbittrapradius1", TFloat.N(orbittrapradius1))
		t.setVar("orbittrapradius2", TFloat.N(orbittrapradius2))
		Return t
	End Function

	Method getVar:Object(name:String)
		For Local t:TAnimFrameVar = EachIn varlist
			If t.name = name
				Return t.v
			End If
		Next
		Return Null
	End Method

	Method setVar(name:String, v:Object)
		For Local t:TAnimFrameVar = EachIn varlist
			If t.name = name
				t.v = v
				Return
			End If
		Next
		Local t:TAnimFrameVar = New TAnimFrameVar
		t.name = name
		t.v = v
		varlist.AddLast(t)
		Return
	End Method

	Function PlayAnim(speed:Float)
		Local f1:TAnimFrame, f1link:TLink
		Local f2:TAnimFrame, f2link:TLink
		Local time:Float
		Local x:Float = 0

		f1 = TAnimFrame(f1.list.First())
		f1link = f1.list.FirstLink()
		If f1link = Null Then Return
		f2link = f1link.NextLink()
		If f2link = Null Then Return
		f2 = TAnimFrame(f2link.Value())

		While Not KeyHit(KEY_ESCAPE)

			setGlobals(f1, f1link, f2, f2link, x)

			Render()

			If disphelp DrawHelp()

			time = Clip(TFloat(f1.getVar("time")).v,  ..
			TFloat(f2.getVar("time")).v, x)

			x:+speed / time
			If x >= 1
				f1link = f2link
				f1 = f2
				f2link = f1link.NextLink()
				If f2link = Null Return
				f2 = TAnimFrame(f2link.Value())
				x = x - 1.0
			End If

			Flip 0
			glCls
			WaitTimer TIMER
		Wend
	End Function

	Function SaveAnim(speed:Float, folder:String, skip:Int = 0)
		Local framenr:Int = 0

		CreateDir(folder)

		Local f1:TAnimFrame, f1link:TLink
		Local f2:TAnimFrame, f2link:TLink
		Local time:Float
		Local x:Float = 0

		f1 = TAnimFrame(f1.list.First())
		f1link = f1.list.FirstLink()
		If f1link = Null Then Return
		f2link = f1link.NextLink()
		If f2link = Null Then Return
		f2 = TAnimFrame(f2link.Value())

		While Not KeyHit(KEY_ESCAPE)
			setGlobals(f1, f1link, f2, f2link, x)

			If framenr >= skip
				SaveSceenshot(2, folder + "/" + framenr + ".png", 1, 0)
				Print "Frame Nr. " + framenr
			End If

			time = Clip(TFloat(f1.getVar("time")).v,  ..
			TFloat(f2.getVar("time")).v, x)

			x:+speed / time
			If x >= 1
				f1link = f2link
				f1 = f2
				f2link = f1link.NextLink()
				If f2link = Null Then End
				f2 = TAnimFrame(f2link.Value())
				x = x - 1.0
			End If

			framenr:+1
			'Flip 0
			'glCls
			'WaitTimer TIMER
		Wend
	End Function

	Function setGlobals(f1:TAnimFrame, f1link:TLink, f2:TAnimFrame, f2link:TLink, x:Float)
		Local f0:TAnimFrame, f3:TAnimFrame
		Local f0link:TLink, f3link:TLink

		f0link = f1link.PrevLink()
		f3link = f2link.NextLink()

		If f0link = Null Then f0link = f1link
		If f3link = Null Then f3link = f2link

		f0 = TAnimFrame(f0link.Value())
		f3 = TAnimFrame(f3link.Value())

		camX = Catmul(TFloat(f0.getVar("camX")).v,  ..
		TFloat(f1.getVar("camX")).v,  ..
		TFloat(f2.getVar("camX")).v,  ..
		TFloat(f3.getVar("camX")).v, x)

		camY = Catmul(TFloat(f0.getVar("camY")).v,  ..
		TFloat(f1.getVar("camY")).v,  ..
		TFloat(f2.getVar("camY")).v,  ..
		TFloat(f3.getVar("camY")).v, x)

		camZoom = Catmul(TFloat(f0.getVar("camZoom")).v,  ..
		TFloat(f1.getVar("camZoom")).v,  ..
		TFloat(f2.getVar("camZoom")).v,  ..
		TFloat(f3.getVar("camZoom")).v, x)
'		camZoom = Clip(TFloat(f1.getVar("camZoom")).v,  ..
'		TFloat(f2.getVar("camZoom")).v, x)

		itr = Clip(TInt(f1.getVar("itr")).v,  ..
		TInt(f2.getVar("itr")).v, x)

		v1x = Catmul(TFloat(f0.getVar("v1x")).v,  ..
		TFloat(f1.getVar("v1x")).v,  ..
		TFloat(f2.getVar("v1x")).v,  ..
		TFloat(f3.getVar("v1x")).v, x)

		v1y = Catmul(TFloat(f0.getVar("v1y")).v,  ..
		TFloat(f1.getVar("v1y")).v,  ..
		TFloat(f2.getVar("v1y")).v,  ..
		TFloat(f3.getVar("v1y")).v, x)

		v2x = Catmul(TFloat(f0.getVar("v2x")).v,  ..
		TFloat(f1.getVar("v2x")).v,  ..
		TFloat(f2.getVar("v2x")).v,  ..
		TFloat(f3.getVar("v2x")).v, x)

		v2y = Catmul(TFloat(f0.getVar("v2y")).v,  ..
		TFloat(f1.getVar("v2y")).v,  ..
		TFloat(f2.getVar("v2y")).v,  ..
		TFloat(f3.getVar("v2y")).v, x)

		v3x = Catmul(TFloat(f0.getVar("v3x")).v,  ..
		TFloat(f1.getVar("v3x")).v,  ..
		TFloat(f2.getVar("v3x")).v,  ..
		TFloat(f3.getVar("v3x")).v, x)

		v3y = Catmul(TFloat(f0.getVar("v3y")).v,  ..
		TFloat(f1.getVar("v3y")).v,  ..
		TFloat(f2.getVar("v3y")).v,  ..
		TFloat(f3.getVar("v3y")).v, x)

		p1x = Catmul(TFloat(f0.getVar("p1x")).v,  ..
		TFloat(f1.getVar("p1x")).v,  ..
		TFloat(f2.getVar("p1x")).v,  ..
		TFloat(f3.getVar("p1x")).v, x)

		p1y = Catmul(TFloat(f0.getVar("p1y")).v,  ..
		TFloat(f1.getVar("p1y")).v,  ..
		TFloat(f2.getVar("p1y")).v,  ..
		TFloat(f3.getVar("p1y")).v, x)

		p2x = Catmul(TFloat(f0.getVar("p2x")).v,  ..
		TFloat(f1.getVar("p2x")).v,  ..
		TFloat(f2.getVar("p2x")).v,  ..
		TFloat(f3.getVar("p2x")).v, x)

		p2y = Catmul(TFloat(f0.getVar("p2y")).v,  ..
		TFloat(f1.getVar("p2y")).v,  ..
		TFloat(f2.getVar("p2y")).v,  ..
		TFloat(f3.getVar("p2y")).v, x)

		p3x = Catmul(TFloat(f0.getVar("p3x")).v,  ..
		TFloat(f1.getVar("p3x")).v,  ..
		TFloat(f2.getVar("p3x")).v,  ..
		TFloat(f3.getVar("p3x")).v, x)

		p3y = Catmul(TFloat(f0.getVar("p3y")).v,  ..
		TFloat(f1.getVar("p3y")).v,  ..
		TFloat(f2.getVar("p3y")).v,  ..
		TFloat(f3.getVar("p3y")).v, x)

		p4x = Catmul(TFloat(f0.getVar("p4x")).v,  ..
		TFloat(f1.getVar("p4x")).v,  ..
		TFloat(f2.getVar("p4x")).v,  ..
		TFloat(f3.getVar("p4x")).v, x)

		p4y = Catmul(TFloat(f0.getVar("p4y")).v,  ..
		TFloat(f1.getVar("p4y")).v,  ..
		TFloat(f2.getVar("p4y")).v,  ..
		TFloat(f3.getVar("p4y")).v, x)

		uk = Clip(TInt(f1.getVar("uk")).v,  ..
		TInt(f2.getVar("uk")).v, x)

		threshold = Clip(TFloat(f1.getVar("threshold")).v,  ..
		TFloat(f2.getVar("threshold")).v, x)

		orbittrapradius1 = Clip(TFloat(f1.getVar("orbittrapradius1")).v,  ..
		TFloat(f2.getVar("orbittrapradius1")).v, x)

		orbittrapradius2 = Clip(TFloat(f1.getVar("orbittrapradius2")).v,  ..
		TFloat(f2.getVar("orbittrapradius2")).v, x)

	End Function

	Method setGlobalsToFrame()
		camX = TFloat(getVar("camX")).v

		camY = TFloat(getVar("camY")).v
		camZoom = TFloat(getVar("camZoom")).v

		itr = TInt(getVar("itr")).v

		v1x = TFloat(getVar("v1x")).v
		v1y = TFloat(getVar("v1y")).v
		v2x = TFloat(getVar("v2x")).v
		v2y = TFloat(getVar("v2y")).v
		v3x = TFloat(getVar("v3x")).v
		v3y = TFloat(getVar("v3y")).v

		p1x = TFloat(getVar("p1x")).v
		p1y = TFloat(getVar("p1y")).v
		p2x = TFloat(getVar("p2x")).v
		p2y = TFloat(getVar("p2y")).v
		p3x = TFloat(getVar("p3x")).v
		p3y = TFloat(getVar("p3y")).v
		p4x = TFloat(getVar("p4x")).v
		p4y = TFloat(getVar("p4y")).v

		uk = TInt(getVar("uk")).v
		threshold = TFloat(getVar("threshold")).v
		orbittrapradius1 = TFloat(getVar("orbittrapradius1")).v
		orbittrapradius2 = TFloat(getVar("orbittrapradius2")).v
	End Method

	Function SaveToFile(filename:String)
		Local f:TStream = WriteFile(filename)
		For Local t:TAnimFrame = EachIn TAnimFrame.list
			f.WriteLine "{"
			For Local v:TAnimFrameVar = EachIn t.varlist
				If TFloat(v.v) <> Null
					f.WriteLine "~t" + v.name + " = " + TFloat(v.v).v + "f;"
				Else If TInt(v.v) <> Null
					f.WriteLine "~t" + v.name + " = " + TInt(v.v).v + "i;"
				Else If TDouble(v.v) <> Null
					f.WriteLine "~t" + v.name + " = " + TDouble(v.v).v + "d;"
				End If
			Next
			f.WriteLine "}"
		Next
		f.Close
	End Function

	Function LoadFromFile(file:String)
		If FileType(file) = 1
			file = LoadText(file)
			file = Replace(file, " ", "")
			file = Replace(file, Chr(9), "")
			file = Replace(file, Chr(10), "")
			file = Replace(file, Chr(13), "")

			Local gs:Int = 1, ge:Int = 0, content:String

			While ge < Len(file)
				gs = Instr(file, "{", ge)
				ge = Instr(file, "}", gs + 1)
				content = Mid(file, gs + 1, ge - gs - 1)

				Local cs:Int = 1, ce:Int = 0, eq:Int
				Local name:String, value:String, dt:String

				Local t:TAnimFrame = New TAnimFrame
				t.list.AddLast(t)

				While ce < Len(content)
					ce = Instr(content, ";", cs)
					value = Mid(content, cs, ce - cs)
					eq = Instr(value, "=")

					name = Left(value, eq - 1)
					dt = Right(value, 1)
					value = Mid(Left(value, value.Length - 1), eq + 1)

					Select dt
						Case "f"
							t.setVar(name, TFloat.N(value.ToFloat()))
						Case "i"
							t.setVar(name, TInt.N(value.ToInt()))
						Case "d"
							t.setVar(name, TDouble.N(value.ToDouble()))
					End Select

					cs = ce + 1
				Wend

			Wend
		Else
			RuntimeError("File does not exist!")
		End If
	End Function

End Type

Type TAnimFrameVar
	Field name:String
	Field v:Object
End Type

Type TInt
	Field v:Int
	Function N:TInt(v:Int)
		Local t:TInt = New TInt
		t.v = v
		Return t
	End Function
End Type

Type TFloat
	Field v:Float
	Function N:TFloat(v:Float)
		Local t:TFloat = New TFloat
		t.v = v
		Return t
	End Function
End Type

Type TDouble
	Field v:Double
	Function N:TDouble(v:Double)
		Local t:TDouble = New TDouble
		t.v = v
		Return t
	End Function
End Type

error: pathspec 'MandelbrotShader2/mandelbrot.bmx' did not match any file(s) known to git


Create fractal_music.bmx

Create fractal_music.bmx

SuperStrict
Framework brl.Retro
Import BRL.Timer
Import bah.rtmidi

Local filename:String
If AppArgs.Length > 1
	filename = AppArgs[1]
Else
	filename = Input("Datei angeben: ")
End If

Global score:TmidiScore = New TmidiScore
score.midiOut = New TRtMidiOut.Create()
score.midiOut.openPort(0)
OnEnd(CleanUp)

score.loadMusic(filename)

score.saveAsMidi(StripExt(filename) + ".mid")

'score.play

End

Function CleanUp()
	score.midiOut.closePort()
	score.midiOut.Free()
	Delay(300)
End Function

Function NoteFromString:Byte(n:String)
	If n = "p" Then Return $ff
	Local os:Int = 0
	Local t:String = Mid(n, 2, 1)
	If t = "#" Or t = "b"
		t = Left(n, 2)
		os = Mid(n, 3).ToInt() + 2
	Else
		t = Left(n, 1)
		os = Mid(n, 2).ToInt() + 2
	End If
	Select t
		Case "C"
			Return 0 + $0C * os
		Case "C#"
			Return 1 + $0C * os
		Case "D"
			Return 2 + $0C * os
		Case "D#"
			Return 3 + $0C * os
		Case "E"
			Return 4 + $0C * os
		Case "F"
			Return 5 + $0C * os
		Case "F#"
			Return 6 + $0C * os
		Case "G"
			Return 7 + $0C * os
		Case "G#"
			Return 8 + $0C * os
		Case "A"
			Return 9 + $0C * os
		Case "A#"
			Return 10 + $0C * os
		Case "B"
			Return 11 + $0C * os
	End Select
End Function

Function L_System:String(itr:Int, a:String, rules:String[])
	For Local n:Int = 0 Until itr
		Local a1:String
		For Local i:Int = 0 Until Len(a)
			For Local s:String = EachIn rules
				If Chr(s[0]) = Chr(a[i])
					a1 = a1 + Mid(s, 3)
					Exit
				End If
			Next
		Next
		a = a1
	Next
	Return a
End Function

Type TmidiNote
	Field note:Byte
	Field length:Int
End Type

Type TmidiChannel
	Field id:Int

	Field notes:TmidiNote[]
	Field instrument:Byte
	Field volume:Byte

	Field currentNote:Int
	Field arrlength:Int
	Field currentNoteTimer:Int

	Method fromStrings(pstr:String, pindex:String[], vstr:String, vindex:String[])
		pstr = Left(pstr, Len(vstr))
		vstr = Left(vstr, Len(pstr))

		Local l:Int = Len(pstr)

		notes = New TmidiNote[l]
		arrlength = l

		For Local i:Int = 0 Until l
			Local p:Int, t:TmidiNote = New TmidiNote
			p = 0
			For Local s:String = EachIn pindex
				If Chr(s[0]) = Chr(pstr[i])
					t.note = NoteFromString(Mid(s, 3))
					p = 1
				End If
			Next
			If p = 0 Then t.Note = $ff
			p = 0
			For Local s:String = EachIn vindex
				If Chr(s[0]) = Chr(vstr[i])
					t.length = Mid(s, 3).ToInt()
					p = 1
				End If
			Next
			If p = 0 Then t.length = 4
			notes[i] = t
		Next
	End Method
End Type

Type TmidiScore
	Field channels:TList
	Field speedHz:Float
	Field midiOut:TRtMidiOut

	Method New()
		channels = CreateList()
	End Method

	Method addChannel(channel:TmidiChannel)
		Self.channels.AddLast(channel)
	End Method

	Method play()
		Local timer:TTimer = CreateTimer(speedHz)

		Local channelnr:Int = 0, channels_finished:Byte = 0
		For Local c:TmidiChannel = EachIn channels
			midi2Byte(midiOut, $C0 | c.id, c.instrument)
			midi3Byte(midiOut, $B0 | c.id, $07, c.volume)
			c.currentNote = 0
			c.currentNoteTimer = 0

			channelnr:+1
		Next
		While channels_finished <> channelnr
			channelnr = 0
			channels_finished = 0
			For Local c:TmidiChannel = EachIn channels
				If c.currentNote < c.arrlength
					If c.currentNoteTimer = c.notes[c.currentNote].length
						If c.notes[c.currentNote].Note <> $ff
							midi3Byte(midiOut, $80 | c.id, c.notes[c.currentNote].Note, $3F)
						End If

						c.currentNote:+1
						c.currentNoteTimer = 0
					End If

					If c.currentNoteTimer = 0 And c.currentNote < c.arrlength And c.notes[c.currentNote].Note <> $ff
						midi3Byte(midiOut, $90 | c.id, c.notes[c.currentNote].note, $3F)
					End If
					c.currentNoteTimer:+1
				Else
					channels_finished:+1
				End If
				channelnr:+1
			Next
			WaitTimer(timer)
		Wend
	End Method

	Method loadMusic(file:String)
		If FileType(file) = 1
			file = LoadText(file)
			file = Replace(file, " ", "")
			file = Replace(file, Chr(9), "")
			file = Replace(file, Chr(10), "")
			file = Replace(file, Chr(13), "")

			Local gs:Int = 1, ge:Int = 0, content:String, title:String

			Repeat
				gs = Instr(file, "/*")
				If gs = 0 Exit
				ge = Instr(file, "*/", gs)
				file = Mid(file, 1, gs - 1) + Mid(file, ge + 2)
			Forever

			gs = 1;ge = 0

			While ge < Len(file)
				gs = Instr(file, "{", ge)
				title = Mid(file, ge + 1, gs - ge - 1)
				ge = Instr(file, "}", gs + 1)
				content = Mid(file, gs + 1, ge - gs - 1)

				Local cs:Int = 0, ce:Int = 0
				Select title
					Case "general"
						cs = Instr(content, "speed")
						If cs <> 0
							cs:+6
							ce = Instr(content, ";", cs)
							speedHz = Mid(content, cs, ce - cs).ToFloat()
						End If

					Case "channel"
						Local c:TmidiChannel = New TmidiChannel
						Self.addChannel(c)

						Local pitr:Int, pstart:String, prules:String[], pindex:String[], pbegin:String, pend:String
						Local vitr:Int, vstart:String, vrules:String[], vindex:String[], vbegin:String, vend:String

						cs = Instr(content, "id")
						If cs <> 0
							cs:+3
							ce = Instr(content, ";", cs)
							c.id = Mid(content, cs, ce - cs).ToInt()
						End If

						cs = Instr(content, "instrument")
						If cs <> 0
							cs:+11
							ce = Instr(content, ";", cs)
							c.instrument = Mid(content, cs, ce - cs).ToInt()
						End If

						cs = Instr(content, "volume")
						If cs <> 0
							cs:+7
							ce = Instr(content, ";", cs)
							c.volume = Mid(content, cs, ce - cs).ToInt()
						End If

						cs = Instr(content, "pitch_iterations")
						If cs <> 0
							cs:+17
							ce = Instr(content, ";", cs)
							pitr = Mid(content, cs, ce - cs).ToInt()
						End If

						cs = Instr(content, "pitch_start")
						If cs <> 0
							cs:+12
							ce = Instr(content, ";", cs)
							pstart = Mid(content, cs, ce - cs)
						End If

						cs = Instr(content, "pitch_rules")
						If cs <> 0
							cs:+12
							ce = Instr(content, ";", cs)
							prules = Mid(content, cs, ce - cs).Split(",")
						End If

						cs = Instr(content, "pitch_index")
						If cs <> 0
							cs:+12
							ce = Instr(content, ";", cs)
							pindex = Mid(content, cs, ce - cs).Split(",")
						End If

						cs = Instr(content, "pitch_begin")
						If cs <> 0
							cs:+12
							ce = Instr(content, ";", cs)
							pbegin = Mid(content, cs, ce - cs)
						End If

						cs = Instr(content, "pitch_end")
						If cs <> 0
							cs:+10
							ce = Instr(content, ";", cs)
							pend = Mid(content, cs, ce - cs)
						End If

						cs = Instr(content, "value_iterations")
						If cs <> 0
							cs:+17
							ce = Instr(content, ";", cs)
							vitr = Mid(content, cs, ce - cs).ToInt()
						End If

						cs = Instr(content, "value_start")
						If cs <> 0
							cs:+12
							ce = Instr(content, ";", cs)
							vstart = Mid(content, cs, ce - cs)
						End If

						cs = Instr(content, "value_rules")
						If cs <> 0
							cs:+12
							ce = Instr(content, ";", cs)
							vrules = Mid(content, cs, ce - cs).Split(",")
						End If

						cs = Instr(content, "value_index")
						If cs <> 0
							cs:+12
							ce = Instr(content, ";", cs)
							vindex = Mid(content, cs, ce - cs).Split(",")
						End If

						cs = Instr(content, "value_begin")
						If cs <> 0
							cs:+12
							ce = Instr(content, ";", cs)
							vbegin = Mid(content, cs, ce - cs)
						End If

						cs = Instr(content, "value_end")
						If cs <> 0
							cs:+10
							ce = Instr(content, ";", cs)
							vend = Mid(content, cs, ce - cs)
						End If

						Local pstr:String, vstr:String
						pstr = pbegin + L_System(pitr, pstart, prules) + pend
						vstr = vbegin + L_System(vitr, vstart, vrules) + vend

						c.fromStrings(pstr, pindex, vstr, vindex)
				End Select
			Wend
		Else
			RuntimeError("File does not exist!")
		End If
	End Method

	Method saveAsMidi(filename:String)
		Local file:TStream = WriteFile(filename)

		Local bytelist:TList = CreateList()

		'HEADER
		toByteArr($4D546864, 4, bytelist)'Name="MThd"
		toByteArr($00000006, 4, bytelist)'Chunck Size
		toByteArr($0000, 2, bytelist)'Format Type
		toByteArr(channels.Count(), 2, bytelist)'Nr of Tracks
		toByteArr($7fff & Int(speedHz * 10), 2, bytelist)'Time Division

		For Local t:TByte = EachIn bytelist
			file.WriteByte(t.v)
		Next

		bytelist.Clear()

		'TRACKS

'		'End of Track Marker
'		bytelist.AddLast(TByte.N(0)) 'delta time
'		bytelist.AddLast(TByte.N($FF))'metaevent
'		bytelist.AddLast(TByte.N($2F))'type
'		bytelist.AddLast(TByte.N($0))'length
'
'		'TRACK header
'		file.WriteBytes(toByteArr($4D54726B, 4), 4)
'		file.WriteBytes(toByteArr(bytelist.Count(), 4), 4)

		For Local c:TmidiChannel = EachIn channels
			bytelist.Clear()

			Local dt:Int = 0

			If c.id <> 9
				'''''''Set Instrument
				bytelist.AddLast(TByte.N(0))'delta time
				bytelist.AddLast(TByte.N($C0 | c.id))'eventtype0|channelnr
				bytelist.AddLast(TByte.N(c.instrument))'p1
			End If

			'''''''Set Volume
			bytelist.AddLast(TByte.N(0))'delta time
			bytelist.AddLast(TByte.N($B0 | c.id))'eventtype0|channelnr
			bytelist.AddLast(TByte.N($07))'p1
			bytelist.addlast(TByte.N(c.volume))'p2

			For Local mn:TmidiNote = EachIn c.notes
				If mn.note <> $ff
					''''''''Note On
					toVariableLength(dt, bytelist)'delta time
					bytelist.AddLast(TByte.N($90 | c.id))'eventtype0|channelnr
					bytelist.AddLast(TByte.N(mn.note))'p1
					bytelist.AddLast(TByte.N($3F))'p2
					dt = mn.length * 20
					''''''''Note Off
					toVariableLength(dt, bytelist)'delta time
					bytelist.AddLast(TByte.N($80 | c.id))'eventtype0|channelnr
					bytelist.AddLast(TByte.N(mn.note))'p1
					bytelist.addlast(TByte.N($3F))'p2
					dt = 0
				Else
					dt:+mn.length * 20
				End If
			Next

			'End of Track Marker
			bytelist.AddLast(TByte.N(0))'delta time
			bytelist.AddLast(TByte.N($FF))'metaevent
			bytelist.AddLast(TByte.N($2F))'type
			bytelist.AddLast(TByte.N($0))'length

			'TRACK header
			file.WriteBytes(toByteArr($4D54726B, 4), 4)
			file.WriteBytes(toByteArr(bytelist.Count(), 4), 4)

			For Local t:TByte = EachIn bytelist
				file.WriteByte(t.v)
			Next
		Next

		file.Close()
	End Method
End Type

Type TByte
	Field v:Byte
	Function N:TByte(v:Byte)
		Local t:TByte = New TByte
		t.v = v
		Return t
	End Function
End Type

Function midi3Byte(midiOut:TRtMidiOut, v1:Byte, v2:Byte, v3:Byte)
	Local m:Byte[3]
	m[0] = v1
	m[1] = v2
	m[2] = v3
	midiOut.putMessage(m, 3)
End Function

Function midi2Byte(midiOut:TRtMidiOut, v1:Byte, v2:Byte)
	Local m:Byte[2]
	m[0] = v1
	m[1] = v2
	midiOut.putMessage(m, 2)
End Function

Function Count:Int(str:String, char:Byte)
	Local cnt:Int = 0
	For Local n:Int = 0 Until Len(str)
		If char = str[n] Then cnt:+1
	Next
	Return cnt
End Function

Function toByteArr:Byte[] (v:Long, length:Int, list:TList = Null)
	Local bytes:Byte[length]
	For Local n:Int = 0 Until length
		Local n2:Int = length - n - 1
		bytes[n] = (v & ($ff Shl (n2 * 8))) Shr (n2 * 8)
		If list <> Null Then list.AddLast(TByte.N(bytes[n]))
	Next
	Return bytes
End Function

Function toVariableLength:Byte[] (v:Int, list:TList = Null)
	If v < %10000000
		Local bytes:Byte[1]
		bytes[0] = v & %01111111
		If list <> Null Then list.AddLast(TByte.n(bytes[0]))
		Return bytes
	Else If v < %100000000000000
		Local bytes:Byte[2]
		bytes[1] = v & %01111111
		bytes[0] = ((v & %011111110000000) Shr 7) | %10000000
		If list <> Null
			list.AddLast(TByte.N(bytes[0]))
			list.AddLast(TByte.N(bytes[1]))
		End If
		Return bytes
	Else If v < %1000000000000000000000
		Local bytes:Byte[3]
		bytes[2] = v & %01111111
		bytes[1] = ((v & %011111110000000) Shr 7) | %10000000
		bytes[0] = ((v & %0111111100000000000000) Shr 14) | %10000000
		If list <> Null
			list.AddLast(TByte.N(bytes[0]))
			list.AddLast(TByte.N(bytes[1]))
			list.AddLast(TByte.N(bytes[2]))
		End If
		Return bytes
	Else
		Local bytes:Byte[4]
		bytes[3] = v & %01111111
		bytes[2] = ((v & %011111110000000) Shr 7) | %10000000
		bytes[1] = ((v & %0111111100000000000000) Shr 14) | %10000000
		bytes[0] = ((v & %01111111000000000000000000000) Shr 21) | %10000000
		If list <> Null
			list.AddLast(TByte.N(bytes[0]))
			list.AddLast(TByte.N(bytes[1]))
			list.AddLast(TByte.N(bytes[2]))
			list.AddLast(TByte.N(bytes[3]))
		End If
		Return bytes
	End If
End Function

error: pathspec 'lindenmayr_notevalues/fractal_music.bmx' did not match any file(s) known to git


Added WorldPick sample.

Added WorldPick sample.

Strict

Import MaxB3D.Drivers
Import MaxB3D.MonkeyHeadLoader
Import MaxB3D.TeapotLoader

Import MaxB3DEx.Helper

Graphics 800,600

Local light:TLight = CreateLight()

Local camera:TCamera = CreateCamera()

Local mesh:TMesh = CreateMonkeyHead()
SetEntityScale mesh,10,10,10
SetEntityPosition mesh,0,0,3
SetEntityPickMode mesh,PICKMODE_POLYGON

Local sphere:TMesh = CreateSphere(32)
SetEntityScale sphere,.125,.125,.125
SetEntityColor sphere,255,0,0

While Not KeyDown(KEY_ESCAPE) And Not AppTerminate()
	If MouseDown(1)
		Local pick:TPick = WorldPick(camera, [Float(MouseX()), Float(MouseY())])
		If pick
			SetEntityPosition sphere,pick.x,pick.y,pick.z
		EndIf
	EndIf

	FlyCam camera

	SetWireFrame KeyDown(KEY_F1)
	''TurnEntity mesh,0,1,0

	RenderWorld
	Flip
Wend

error: pathspec 'functions.mod/doc/worldpick.bmx' did not match any file(s) known to git


Create fracta_music.bmx

Create fracta_music.bmx

SuperStrict
Framework brl.Retro
Import BRL.Timer
Import bah.rtmidi
'Graphics 1000, 200
'
'For Local n:Int = 0 Until 1000
'	Local c:Byte
'	c = Min(Max(PerlinNoise(n / 100.0, 10, 0.98, 0.0), 0.0), 1.0) * 255
'	SetColor c, c, c
'	DrawLine n, 0, n, 200
'Next
'Flip 0
'WaitKey()
'End

'Local filename:String
'If AppArgs.Length > 1
'	filename = AppArgs[1]
'Else
'	filename = Input("Datei angeben: ")
'End If

Global score:TmidiScore = New TmidiScore
score.midiOut = New TRtMidiOut.Create()
score.midiOut.openPort(0)
OnEnd(CleanUp)
SeedRnd MilliSecs()
'score.loadMusic(filename)

Local pitchlist:TList, valuelist:TList
Local notelist:TByte[]
notelist = [TByte.N(60), TByte.N(62), TByte.N(64), TByte.N(65), TByte.N(67), TByte.N(69), TByte.N(71),  ..
			TByte.N(72), TByte.N(74), TByte.N(76), TByte.N(77), TByte.N(79), TByte.N(91), TByte.N(83)]
pitchlist = TList.FromArray(notelist)
notelist = [TByte.N(1), TByte.N(2), TByte.N(4)]
valuelist = TList.FromArray(notelist)

Local channel1:TmidiChannel = New TmidiChannel
channel1.generate(100, 8, 0.95, 0.25, 0.1, pitchlist, 3, 0.99, 0.25, 0.3, valuelist)
channel1.id = 0

channel1.instrument = 0
channel1.volume = 127
score.addChannel(channel1)

For Local t:TByte = EachIn pitchlist
	t.v:-24
Next

Local channel2:TmidiChannel = New TmidiChannel
channel2.generate(100, 8, 0.95, 0.25, 0.1, pitchlist, 3, 0.99, 0.25, 0.3, valuelist)
channel2.id = 1

channel2.instrument = 0
channel2.volume = 127
score.addChannel(channel2)

score.speedHz = 4

score.saveAsMidi("asdf.midi")

'score.play

End

Function CleanUp()
	score.midiOut.closePort()
	score.midiOut.Free()
	Delay(300)
End Function

Function NoteFromString:Byte(n:String)
	If n = "p" Then Return $ff
	Local os:Int = 0
	Local t:String = Mid(n, 2, 1)
	If t = "#" Or t = "b"
		t = Left(n, 2)
		os = Mid(n, 3).ToInt() + 2
	Else
		t = Left(n, 1)
		os = Mid(n, 2).ToInt() + 2
	End If
	Select t
		Case "C"
			Return 0 + $0C * os
		Case "C#"
			Return 1 + $0C * os
		Case "D"
			Return 2 + $0C * os
		Case "D#"
			Return 3 + $0C * os
		Case "E"
			Return 4 + $0C * os
		Case "F"
			Return 5 + $0C * os
		Case "F#"
			Return 6 + $0C * os
		Case "G"
			Return 7 + $0C * os
		Case "G#"
			Return 8 + $0C * os
		Case "A"
			Return 9 + $0C * os
		Case "A#"
			Return 10 + $0C * os
		Case "B"
			Return 11 + $0C * os
	End Select
End Function

Type TmidiNote
	Field note:Byte
	Field length:Int
End Type

Type TmidiChannel
	Field id:Int

	Field notes:TmidiNote[]
	Field instrument:Byte
	Field volume:Byte

	Field currentNote:Int
	Field arrlength:Int
	Field currentNoteTimer:Int

	Method generate(l:Int,  ..
	pitch_octaves:Int, pitch_p:Float, pitch_frq:Float, pitch_frqdstr:Float, pitch_list:TList,  ..
	value_octaves:Int, value_p:Float, value_frq:Float, value_frqdstr:Float, value_list:TList)
		Local arr:TmidiNote[l]
		Local tmp:Float
		notes = arr
		For Local n:Int = 0 Until l
			notes[n] = New TmidiNote
			tmp = PerlinNoise(n / pitch_frq, pitch_octaves, pitch_p, pitch_frqdstr)
			notes[n].note = TByte(pitch_list.ValueAtIndex(Max(Min(tmp * pitch_list.Count(), pitch_list.Count() - 1), 0))).v
			tmp = PerlinNoise(n / value_frq, value_octaves, value_p, value_frqdstr)
			notes[n].length = TByte(value_list.ValueAtIndex(Max(Min(tmp * value_list.Count(), value_list.Count() - 1), 0))).v
		Next

	End Method
End Type

Type TmidiScore
	Field channels:TList
	Field speedHz:Float
	Field midiOut:TRtMidiOut

	Method New()
		channels = CreateList()
	End Method

	Method addChannel(channel:TmidiChannel)
		Self.channels.AddLast(channel)
	End Method

	Method play()
		Local timer:TTimer = CreateTimer(speedHz)

		Local channelnr:Int = 0, channels_finished:Byte = 0
		For Local c:TmidiChannel = EachIn channels
			midi2Byte(midiOut, $C0 | c.id, c.instrument)
			midi3Byte(midiOut, $B0 | c.id, $07, c.volume)
			c.currentNote = 0
			c.currentNoteTimer = 0

			channelnr:+1
		Next
		While channels_finished <> channelnr
			channelnr = 0
			channels_finished = 0
			For Local c:TmidiChannel = EachIn channels
				If c.currentNote < c.arrlength
					If c.currentNoteTimer = c.notes[c.currentNote].length
						If c.notes[c.currentNote].Note <> $ff
							midi3Byte(midiOut, $80 | c.id, c.notes[c.currentNote].Note, $3F)
						End If

						c.currentNote:+1
						c.currentNoteTimer = 0
					End If

					If c.currentNoteTimer = 0 And c.currentNote < c.arrlength And c.notes[c.currentNote].Note <> $ff
						midi3Byte(midiOut, $90 | c.id, c.notes[c.currentNote].note, $3F)
					End If
					c.currentNoteTimer:+1
				Else
					channels_finished:+1
				End If
				channelnr:+1
			Next
			WaitTimer(timer)
		Wend
	End Method

	Method loadMusic(file:String)
		If FileType(file) = 1
			file = LoadText(file)
			file = Replace(file, " ", "")
			file = Replace(file, Chr(9), "")
			file = Replace(file, Chr(10), "")
			file = Replace(file, Chr(13), "")

			Local gs:Int = 1, ge:Int = 0, content:String, title:String

			Repeat
				gs = Instr(file, "/*")
				If gs = 0 Exit
				ge = Instr(file, "*/", gs)
				file = Mid(file, 1, gs - 1) + Mid(file, ge + 2)
			Forever

			gs = 1;ge = 0

			While ge < Len(file)
				gs = Instr(file, "{", ge)
				title = Mid(file, ge + 1, gs - ge - 1)
				ge = Instr(file, "}", gs + 1)
				content = Mid(file, gs + 1, ge - gs - 1)

				Local cs:Int = 0, ce:Int = 0
				Select title
					Case "general"
						cs = Instr(content, "speed")
						If cs <> 0
							cs:+6
							ce = Instr(content, ";", cs)
							speedHz = Mid(content, cs, ce - cs).ToFloat()
						End If

					Case "channel"
						Local c:TmidiChannel = New TmidiChannel
						Self.addChannel(c)

						Local pitr:Int, pstart:String, prules:String[], pindex:String[], pbegin:String, pend:String
						Local vitr:Int, vstart:String, vrules:String[], vindex:String[], vbegin:String, vend:String

						cs = Instr(content, "id")
						If cs <> 0
							cs:+3
							ce = Instr(content, ";", cs)
							c.id = Mid(content, cs, ce - cs).ToInt()
						End If

						cs = Instr(content, "instrument")
						If cs <> 0
							cs:+11
							ce = Instr(content, ";", cs)
							c.instrument = Mid(content, cs, ce - cs).ToInt()
						End If

						cs = Instr(content, "volume")
						If cs <> 0
							cs:+7
							ce = Instr(content, ";", cs)
							c.volume = Mid(content, cs, ce - cs).ToInt()
						End If

						cs = Instr(content, "pitch_iterations")
						If cs <> 0
							cs:+17
							ce = Instr(content, ";", cs)
							pitr = Mid(content, cs, ce - cs).ToInt()
						End If

						cs = Instr(content, "pitch_start")
						If cs <> 0
							cs:+12
							ce = Instr(content, ";", cs)
							pstart = Mid(content, cs, ce - cs)
						End If

						cs = Instr(content, "pitch_rules")
						If cs <> 0
							cs:+12
							ce = Instr(content, ";", cs)
							prules = Mid(content, cs, ce - cs).Split(",")
						End If

						cs = Instr(content, "pitch_index")
						If cs <> 0
							cs:+12
							ce = Instr(content, ";", cs)
							pindex = Mid(content, cs, ce - cs).Split(",")
						End If

						cs = Instr(content, "pitch_begin")
						If cs <> 0
							cs:+12
							ce = Instr(content, ";", cs)
							pbegin = Mid(content, cs, ce - cs)
						End If

						cs = Instr(content, "pitch_end")
						If cs <> 0
							cs:+10
							ce = Instr(content, ";", cs)
							pend = Mid(content, cs, ce - cs)
						End If

						cs = Instr(content, "value_iterations")
						If cs <> 0
							cs:+17
							ce = Instr(content, ";", cs)
							vitr = Mid(content, cs, ce - cs).ToInt()
						End If

						cs = Instr(content, "value_start")
						If cs <> 0
							cs:+12
							ce = Instr(content, ";", cs)
							vstart = Mid(content, cs, ce - cs)
						End If

						cs = Instr(content, "value_rules")
						If cs <> 0
							cs:+12
							ce = Instr(content, ";", cs)
							vrules = Mid(content, cs, ce - cs).Split(",")
						End If

						cs = Instr(content, "value_index")
						If cs <> 0
							cs:+12
							ce = Instr(content, ";", cs)
							vindex = Mid(content, cs, ce - cs).Split(",")
						End If

						cs = Instr(content, "value_begin")
						If cs <> 0
							cs:+12
							ce = Instr(content, ";", cs)
							vbegin = Mid(content, cs, ce - cs)
						End If

						cs = Instr(content, "value_end")
						If cs <> 0
							cs:+10
							ce = Instr(content, ";", cs)
							vend = Mid(content, cs, ce - cs)
						End If

				End Select
			Wend
		Else
			RuntimeError("File does not exist!")
		End If
	End Method

	Method saveAsMidi(filename:String)
		Local file:TStream = WriteFile(filename)

		Local bytelist:TList = CreateList()

		'HEADER
		toByteArr($4D546864, 4, bytelist)'Name="MThd"
		toByteArr($00000006, 4, bytelist)'Chunck Size
		toByteArr($0000, 2, bytelist)'Format Type
		toByteArr(channels.Count(), 2, bytelist)'Nr of Tracks
		toByteArr($7fff & Int(speedHz * 10), 2, bytelist)'Time Division

		For Local t:TByte = EachIn bytelist
			file.WriteByte(t.v)
		Next

		bytelist.Clear()

		'TRACKS

'		'End of Track Marker
'		bytelist.AddLast(TByte.N(0)) 'delta time
'		bytelist.AddLast(TByte.N($FF))'metaevent
'		bytelist.AddLast(TByte.N($2F))'type
'		bytelist.AddLast(TByte.N($0))'length
'
'		'TRACK header
'		file.WriteBytes(toByteArr($4D54726B, 4), 4)
'		file.WriteBytes(toByteArr(bytelist.Count(), 4), 4)

		For Local c:TmidiChannel = EachIn channels
			bytelist.Clear()

			Local dt:Int = 0

			If c.id <> 9
				'''''''Set Instrument
				bytelist.AddLast(TByte.N(0))'delta time
				bytelist.AddLast(TByte.N($C0 | c.id))'eventtype0|channelnr
				bytelist.AddLast(TByte.N(c.instrument))'p1
			End If

			'''''''Set Volume
			bytelist.AddLast(TByte.N(0))'delta time
			bytelist.AddLast(TByte.N($B0 | c.id))'eventtype0|channelnr
			bytelist.AddLast(TByte.N($07))'p1
			bytelist.addlast(TByte.N(c.volume))'p2

			For Local mn:TmidiNote = EachIn c.notes
				If mn.note <> $ff
					''''''''Note On
					toVariableLength(dt, bytelist)'delta time
					bytelist.AddLast(TByte.N($90 | c.id))'eventtype0|channelnr
					bytelist.AddLast(TByte.N(mn.note))'p1
					bytelist.AddLast(TByte.N($3F))'p2
					dt = mn.length * 20
					''''''''Note Off
					toVariableLength(dt, bytelist)'delta time
					bytelist.AddLast(TByte.N($80 | c.id))'eventtype0|channelnr
					bytelist.AddLast(TByte.N(mn.note))'p1
					bytelist.addlast(TByte.N($3F))'p2
					dt = 0
				Else
					dt:+mn.length * 20
				End If
			Next

			'End of Track Marker
			bytelist.AddLast(TByte.N(0))'delta time
			bytelist.AddLast(TByte.N($FF))'metaevent
			bytelist.AddLast(TByte.N($2F))'type
			bytelist.AddLast(TByte.N($0))'length

			'TRACK header
			file.WriteBytes(toByteArr($4D54726B, 4), 4)
			file.WriteBytes(toByteArr(bytelist.Count(), 4), 4)

			For Local t:TByte = EachIn bytelist
				file.WriteByte(t.v)
			Next
		Next

		file.Close()
	End Method
End Type

Type TByte
	Field v:Byte
	Function N:TByte(v:Byte)
		Local t:TByte = New TByte
		t.v = v
		Return t
	End Function
End Type

Function midi3Byte(midiOut:TRtMidiOut, v1:Byte, v2:Byte, v3:Byte)
	Local m:Byte[3]
	m[0] = v1
	m[1] = v2
	m[2] = v3
	midiOut.putMessage(m, 3)
End Function

Function midi2Byte(midiOut:TRtMidiOut, v1:Byte, v2:Byte)
	Local m:Byte[2]
	m[0] = v1
	m[1] = v2
	midiOut.putMessage(m, 2)
End Function

Function Count:Int(str:String, char:Byte)
	Local cnt:Int = 0
	For Local n:Int = 0 Until Len(str)
		If char = str[n] Then cnt:+1
	Next
	Return cnt
End Function

Function toByteArr:Byte[] (v:Long, length:Int, list:TList = Null)
	Local bytes:Byte[length]
	For Local n:Int = 0 Until length
		Local n2:Int = length - n - 1
		bytes[n] = (v & ($ff Shl (n2 * 8))) Shr (n2 * 8)
		If list <> Null Then list.AddLast(TByte.N(bytes[n]))
	Next
	Return bytes
End Function

Function toVariableLength:Byte[] (v:Int, list:TList = Null)
	If v < %10000000
		Local bytes:Byte[1]
		bytes[0] = v & %01111111
		If list <> Null Then list.AddLast(TByte.n(bytes[0]))
		Return bytes
	Else If v < %100000000000000
		Local bytes:Byte[2]
		bytes[1] = v & %01111111
		bytes[0] = ((v & %011111110000000) Shr 7) | %10000000
		If list <> Null
			list.AddLast(TByte.N(bytes[0]))
			list.AddLast(TByte.N(bytes[1]))
		End If
		Return bytes
	Else If v < %1000000000000000000000
		Local bytes:Byte[3]
		bytes[2] = v & %01111111
		bytes[1] = ((v & %011111110000000) Shr 7) | %10000000
		bytes[0] = ((v & %0111111100000000000000) Shr 14) | %10000000
		If list <> Null
			list.AddLast(TByte.N(bytes[0]))
			list.AddLast(TByte.N(bytes[1]))
			list.AddLast(TByte.N(bytes[2]))
		End If
		Return bytes
	Else
		Local bytes:Byte[4]
		bytes[3] = v & %01111111
		bytes[2] = ((v & %011111110000000) Shr 7) | %10000000
		bytes[1] = ((v & %0111111100000000000000) Shr 14) | %10000000
		bytes[0] = ((v & %01111111000000000000000000000) Shr 21) | %10000000
		If list <> Null
			list.AddLast(TByte.N(bytes[0]))
			list.AddLast(TByte.N(bytes[1]))
			list.AddLast(TByte.N(bytes[2]))
			list.AddLast(TByte.N(bytes[3]))
		End If
		Return bytes
	End If
End Function

Function Catmul:Float(v0:Float, v1:Float, v2:Float, v3:Float, x:Float)
	Local a0:Float, a1:Float, a2:Float, a3:Float, x2:Float

	x2 = x * x
'	a0 = -0.5 * v0 + 1.5 * v1 - 1.5 * v2 + 0.5 * v3
'	a1 = v0 - 2.5 * v1 + 2 * v2 - 0.5 * v3
'	a2 = -0.5 * v0 + 0.5 * v2
'	a3 = v1
	a0 = v3 - v2 - v0 + v1
	a1 = v0 - v1 - a0
	a2 = v2 - v0
	a3 = v1

	Return a0 * x * x2 + a1 * x2 + a2 * x + a3
End Function

Function Noise:Float(x:Int, s:Int = 789221)
	x = (x Shl 13) ~ x
	Return 1.0 - ((x * (x * x * 15731 + s) + 1376312589) & $7fffffff) / 2147480774.0'1073740387.0
End Function

Function InterpolatedNoise:Float(x:Float, s:Int = 789221)
	Local intx:Int = Int(x)
	Local fracx:Float = x - intx
	Local v0:Float, v1:Float, v2:Float, v3:Float

	v0 = Noise(intx - 1, s)
	v1 = Noise(intx, s)
	v2 = Noise(intx + 1, s)
	v3 = Noise(intx + 2, s)

	Return Catmul(v0, v1, v2, v3, fracx)
End Function

Function PerlinNoise:Float(x:Float, octaves:Int = 8, p:Float = 0.25, frqdistur:Float = 0.1, s:Int = 789221)
	Local v:Float = 0.0, cnt:Float = 0.0

	Local frq:Float = 1.0
	For Local n:Int = 0 Until octaves
		v:+InterpolatedNoise((x) / frq) * p
		cnt:+p
		p:*p
		frq:/(2.0 + Rnd(-frqdistur, frqdistur))
	Next

	Return v / cnt
End Function

error: pathspec 'perlinnoise/fracta_music.bmx' did not match any file(s) known to git


Added new primitives sample.

Added new primitives sample.

Strict

Import MaxB3D.Drivers
Import MaxB3D.Loaders

Graphics 800,600

Local light:TLight = CreateLight()

Local camera:TCamera = CreateCamera()
SetEntityPosition camera,0,0,-3

Global primitives:TMesh[3]

primitives[0] = CreateBunny()
SetEntityName primitives[0], "Stanford Bunny"
SetEntityScale primitives[0], 2,2,2

primitives[1] = CreateMonkeyHead()
SetEntityName primitives[1], "Suzanne (Blender Monkey)"

primitives[2] = CreateTeapot()
SetEntityName primitives[2], "Utah Teapot"

Local current

While Not KeyDown(KEY_ESCAPE) And Not AppTerminate()
	For Local i = 0 to 9
		If KeyHit(KEY_0 + i)
			current = i
			Exit
		EndIf
	Next

	If KeyHit(KEY_UP) Or KeyHit(KEY_LEFT) current :- 1
	If KeyHit(KEY_DOWN) Or KeyHit(KEY_RIGHT) current :+ 1

	If current > primitives.length -1 current = 0
	If current < 0 current = primitives.length - 1

	For Local i = 0 To primitives.length-1
		SetEntityVisible primitives[i], current = i
	Next

	TurnEntity primitives[current],0,1,0

	SetWireFrame KeyDown(KEY_W)

	RenderWorld
	DoMax2D
	DrawText "Press 1, 2, or 3 to select a particular meshes.",0,0
	DrawText "Press Up/Left or Down/Right to cycle through meshes.",0,15
	DrawText "Current mesh: "+GetEntityName(primitives[current]),0,30

	Flip
Wend

error: pathspec 'doc/samples/kfprimm/new-primitives.bmx' did not match any file(s) known to git


Added module and bmk utils.

Added module and bmk utils.

Rem
Copyright (c) 2010 Tim Howard

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 Rem

Rem
	bbdoc: Maximus module utilities.
End Rem
Type mxModUtils

	Global g_modules:dObjectMap

	Rem
		bbdoc: Get an object map of the current modules.
		returns: An object map containing the current modules.
		about: @force can be used to force re-enumeration of the modules.
	End Rem
	Function GetModules:dObjectMap(force:Int = False)
		If g_modules = Null Or force = True
			g_modules = EnumModules(Null, Null)
		End If
		Return g_modules
	End Function

	Rem
		bbdoc: Check if the user currently has the given module.
		returns: True if the given module was found.
	End Rem
	Function HasModule:Int(modul:String)
		Return GetModules()._Contains(modul)
	End Function

	Rem
		bbdoc: Get the path to the given module or modscope.
		returns: The path to the given module or modscope, or the modules path if the given modid is Null.
	End Rem
	Function ModulePath:String(modid:String)
		Local p:String = mainapp.m_modpath
		If modid Then p:+"/" + modid.Replace(".", ".mod/") + ".mod"
		Return p
	End Function

	Rem
		bbdoc: Get the module scope from the given versioned-module id (for modules with forced versions (or normal ids), e.g. mxModUtils.GetScopeFromID("foo.bar/dev")  would return "foo").
		returns: The scope of the given versioned-module id, or Null if the given versioned-module id was incorrect.
	End Rem
	Function GetScopeFromID:String(verid:String)
		Local i:Int = verid.Find(".")
		If i > -1 Then Return verid[..i]
		Return Null
	End Function

	Rem
		bbdoc: Get the module name from the given versioned-module id (for modules with forced versions (or normal ids), e.g. mxModUtils.GetNameFromID("foo.bar/dev")  would return "bar").
		returns: The name of the given versioned-module id, or Null if the given versioned-module is was incorrect.
	End Rem
	Function GetNameFromID:String(verid:String)
		Local i:Int = verid.Find(".")
		If i > -1 Then Return verid[i + 1..]
		Return Null
	End Function

	Rem
		bbdoc: Get the actual module id from the given versioned-module id (for modules with forced versions (or normal ids), e.g. mxModUtils.GetIDFromVerID("foo.bar/dev")  would return "foo.bar").
		returns: The id of the given versioned-module id.
	End Rem
	Function GetIDFromVerID:String(verid:String)
		Local i:Int = verid.Find("/")
		If i > -1 Then verid = verid[..i]
		Return verid
	End Function

	Rem
		bbdoc: Get the version from the given versioned-module id (for modules with forced versions, e.g. mxModUtils.GetVersionFromVerID("foo.bar/dev) would return "dev").
		returns: The version of the given versioned-module id (which will be Null if the given value is not versioned).
	End Rem
	Function GetVersionFromVerID:String(verid:String)
		Local i:Int = verid.Find("/")
		If i > -1 Then Return verid[i + 1..]
		Return Null
	End Function

	Rem
		bbdoc: Enumerate all of the current modules.
		returns: An object map containing the current modules.
	End Rem
	Function EnumModules:dObjectMap(modid:String = Null, mods:dObjectMap = Null)
		If mods = Null Then mods = New dObjectMap
		Local dir:String = ModulePath(modid)
		Local files:String[] = LoadDir(dir)
		For Local file:String = EachIn files
			Local path:String = dir + "/" + file
			If file[file.length - 4..] <> ".mod" Or FileType(path) <> FILETYPE_DIR Then Continue
			Local t:String = file[..file.length - 4]
			If modid Then t = modid + "." + t
			Local i:Int = t.Find(".")
			If i > -1 And t.Find(".", i + 1) = -1 Then mods._Insert(t, path)
			EnumModules(t, mods)
		Next
		Return mods
	End Function

End Type

Rem
	bbdoc: Maximus BMK utilities.
End Rem
Type mxBMKUtils

	Rem
		bbdoc: Run BMK with the given arguments.
		returns: The exit code from bmk (non-zero when an error occured).
	End Rem
	Function RunBMK:Int(args:String)
		args = "bmk " + args.Trim()
		logger.LogMessage("run: " + args)
		Return system_(args)
	End Function

	Rem
		bbdoc: Make modules with the given arguments.
		returns: The exit code from bmk (non-zero when an error occured).
	End Rem
	Function MakeMods:Int(args:String)
		Return RunBMK("makemods " + args)
	End Function

End Type

error: pathspec 'src/utils.bmx' did not match any file(s) known to git


BlitzMax native code added

BlitzMax native code added

Type flixel

	Function systemMillisecs:Int()
		Return Millisecs()
	End Function

	Function hideMouse()
		bmxHideMouse()
	End Function

	Function showMouse()
		bmxShowMouse()
	End Function

	Function isMobile:Int()
		Return False
	End Function

	Function openURL(url:String)
		bmxOpenURL(url)
	End Function

End Type

Function bmxHideMouse()
	HideMouse()
EndFunction

Function bmxShowMouse()
	ShowMouse()
EndFunction

Function bmxOpenURL(url:String)
	OpenURL(url)
End Function

error: pathspec 'native/flixel.bmax.bmx' did not match any file(s) known to git


Added a threaded PUB/SUB example

Added a threaded PUB/SUB example

Rem

	This is a simple example of a threaded application which uses one PUBLISHER
	thread and serveral SUBSCRIBER threads.
End Rem
SuperStrict
Import htbaapub.zmq

Print "ZMQ Version: " + TZMQ.Version()

Global context:TZMQ_Context = New TZMQ_Context.Create(1)
Global addr:String = "tcp://127.0.0.1:6000"

'The Publisher
Function MyPublisherThread:Object(data:Object)
	'Create a ZMQ_PUB socket
	Local socket:TZMQ_Socket = context.Socket(ZMQ_PUB)
	'Bind to socket to the given address
	socket.Bind(addr)
	Repeat
		'Manually create a TZMQ_Message
		Local msg:TZMQ_Message = New TZMQ_Message.Create("Hello world! " + Rnd(100))
		'Send the message to any SUBSCRIBERs
		socket.Send(msg)
		'Free the message
		'would otherwise be garbage collected, but it doesn't hurt to clean up yourself
		msg.Close()
		Delay 1000
		'Send a String without manually creating a TZMQ_Message object
		socket.Send("Foo Bar " + Rnd(100))
		Delay 1000
	Forever
	'We won't get here, but otherwise clean up
	socket.Close()
	Return Null
End Function

'A Subscriber
Function MySubscriberThread:Object(data:Object)
	'Create a SUBSCRIBER socket
	Local socket:TZMQ_Socket = context.Socket(ZMQ_SUB)
	'Connect to given address
	socket.Connect(addr)
	'Set socket option to subscribe, no filter
	socket.SetSockOpt(ZMQ_SUBSCRIBE, Null)
	Repeat
		'Receive message
		Local msg:TZMQ_Message = socket.Recv()
		If msg <> Null
			Print "Subscriber " + String(data) + " received: " + msg.ToString()
			msg.Close()
		End If
	Forever
	'We won't get here, but otherwise clean up
	socket.Close()
	Return Null
End Function

'create a thread!
Local thread1:TThread = CreateThread(MyPublisherThread, Null)
'Increase amount of subcribers to add more SUBSCRIBERS
'but do note that STDOUT will be scrambled
Local subcribers:Int = 1
For Local i:Int = 1 To subcribers
	Print "Starting subscriber " + i
	CreateThread(MySubscriberThread, String(i))
Next

'Wait for the main thread to finish, which is never
Print WaitThread(thread1).ToString()
'Terminate context
context.Term()

error: pathspec 'examples/example1.bmx' did not match any file(s) known to git


Create KIFS.bmx

Create KIFS.bmx

SuperStrict
Framework brl.GLGraphics
Import brl.TIMER
Import brl.TextStream
Import pub.OpenGL
Import pub.Glew
Import brl.Retro
Import brl.PNGLoader

Const GW:Int = 640, GH:Int = 360

If AppArgs.Length > 1
	TAnimFrame.LoadFromFile(AppArgs[1])
End If

Global TIMER:TTimer = CreateTimer(30)
Global VERTEX_SHADER_CODE:String = LoadText("vs.glsl")
Global FRAGMENT_SHADER_CODE:String = LoadText("fs.glsl")

InitGL
Global ProgramObj:Int
InitShaders
glUseProgram(ProgramObj)

Global camS:Float = 0.04
Global camX:Float = -0.9, camY:Float = -1.35, camZ:Float = -3.6
Global camP:Float = 0.2, camT:Float = -0.37

Global lightX:Float = -1.6, lightY:Float = -1.9, lightZ:Float = -2.4
Global camZoom:Float = 1.0
Global eps:Float = 0.002

Global itr:Int = 10
Global offsetX:Float = 1.0, offsetY:Float = 0.0, offsetZ:Float = 0.0
Global scale:Float = 3.0
Global rotvecX:Float = 0.0, rotvecY:Float = 0.0, rotvecZ:Float = 1.0
Global rotangel:Float = 0.0

Global disphelp:Int = 0

Global cf:TAnimFrame, cflink:TLink

Global MDown:Int, MXS:Int, MYS:Int
While Not KeyHit(KEY_ESCAPE)
	MDown = MouseDown(MOUSE_LEFT) Shl 2 + MouseDown(MOUSE_MIDDLE) Shl 1 + MouseDown(MOUSE_RIGHT)
	MXS = MouseXSpeed()
	MYS = MouseYSpeed()
	If MDown & %100
		MoveMouse GW / 2, GH / 2
		MouseXSpeed()
		MouseYSpeed()
	End If

	CheckInput()

	Render()

	If disphelp DrawHelp()

	Flip 0
	glCls
	WaitTimer TIMER
Wend
End

Function CheckInput()
	offsetX:+(KeyDown(KEY_R) - KeyDown(KEY_F)) * camS
	offsetY:+(KeyDown(KEY_T) - KeyDown(KEY_G)) * camS
	offsetZ:+(KeyDown(KEY_Z) - KeyDown(KEY_H)) * camS

	scale:+(KeyDown(KEY_B) - KeyDown(KEY_V)) * camS

	rotvecX:+(KeyDown(KEY_U) - KeyDown(KEY_J)) * camS
	rotvecY:+(KeyDown(KEY_I) - KeyDown(KEY_K)) * camS
	rotvecZ:+(KeyDown(KEY_O) - KeyDown(KEY_L)) * camS

	rotangel:+(KeyDown(KEY_M) - KeyDown(KEY_N)) * camS * 10.0

	itr:+(KeyDown(KEY_X) - KeyDown(KEY_Y))

	If KeyDown(KEY_2) camS:*1.1 Else If KeyDown(KEY_1) camS:/1.1

	If KeyDown(KEY_4) eps:*1.1 Else If KeyDown(KEY_3) eps:/1.1

	If KeyDown(KEY_6) camZoom:*1.05 Else If KeyDown(KEY_5) camZoom:/1.05

	If MDown & 010
		lightX = camX
		lightY = camY
		lightZ = camZ
	End If

	If KeyDown(KEY_W)
		camX = camX + cos_(camT) * sin_(camP) * camS
		camY = camY - sin_(camT) * camS
		camZ = camZ + cos_(camT) * cos_(camP) * camS
	End If
	If KeyDown(KEY_S)
		camX = camX - cos_(camT) * sin_(camP) * camS
		camY = camY + sin_(camT) * camS
		camZ = camZ - cos_(camT) * cos_(camP) * camS
	End If
	If KeyDown(KEY_D)
		camX = camX + sin_(camP + 1.57079633) * camS
		camZ = camZ + cos_(camP + 1.57079633) * camS
	End If
	If KeyDown(KEY_A)
		camX = camX - sin_(camP + 1.57079633) * camS
		camZ = camZ - cos_(camP + 1.57079633) * camS
	End If
	camY:+(KeyDown(KEY_LSHIFT) - KeyDown(KEY_SPACE)) * camS

	If MDown & %100
		camT:-MYS * 0.01'(KeyDown(KEY_UP) - KeyDown(KEY_DOWN)) * 0.01
		camP:+MXS * 0.01'(KeyDown(KEY_RIGHT) - KeyDown(KEY_LEFT)) * 0.01
	End If

	If KeyHit(KEY_ENTER) disphelp = 1 - disphelp

	If KeyHit(KEY_DOWN)
		If KeyDown(KEY_RCONTROL)
			TAnimFrame.AddFrame(cflink, 1)
			Print "frame modified"
		Else
			cf = TAnimFrame.AddFrame(cflink) Print "frame added"
			If cflink = Null Then cflink = TAnimFrame.list.FindLink(cf) Else cflink = cflink.NextLink()
		End If
	End If

	If KeyHit(KEY_RIGHT)
		If KeyDown(KEY_RCONTROL)
			cflink = TAnimFrame.list.LastLink()
			cf = TAnimFrame(TAnimFrame.list.Last())
			If cf Then cf.setGlobalsToFrame()
		Else If cflink.NextLink()
			cflink = cflink.NextLink()
			cf = TAnimFrame(TAnimFrame(cflink.Value()))
			If cf Then cf.setGlobalsToFrame()
		End If
	End If

	If KeyHit(KEY_LEFT)
		If KeyDown(KEY_RCONTROL)
			cflink = TAnimFrame.list.FirstLink()
			cf = TAnimFrame(TAnimFrame.list.First())
			If cf Then cf.setGlobalsToFrame()
		Else If cflink.PrevLink()
			cflink = cflink.PrevLink()
			cf = TAnimFrame(TAnimFrame(cflink.Value()))
			If cf Then cf.setGlobalsToFrame()
		End If
	End If

	If KeyHit(KEY_BACKSPACE) And cf
		cflink = cflink.PrevLink()
		cf.list.Remove(cf)
		If cf Then cf = TAnimFrame(cflink.Value())
		Print "frame deleted"
	End If

	If cf
		Local timevar:TFloat = TFloat(cf.getVar("time"))
		If KeyDown(KEY_PAGEUP) Then timevar.v:*1.1 Print timevar.v Else ..
		If KeyDown(KEY_PAGEDOWN) Then timevar.v:/1.1 Print timevar.v
	End If

	If KeyHit(KEY_RSHIFT) And cf Then cf.setGlobalsToFrame()

	If KeyHit(KEY_UP) Then TAnimFrame.PlayAnim(0.04)

	If KeyHit(KEY_F10) Then TAnimFrame.SaveToFile("anim" + MilliSecs() + ".txt")

	If KeyHit(KEY_F11)
		If KeyDown(KEY_RCONTROL)
			TAnimFrame.SaveAnim(0.02, "anim" + MilliSecs(), Input("Skip Nr Frames:").ToInt())
		Else
			TAnimFrame.SaveAnim(0.02, "anim" + MilliSecs())
		End If
	End If

	If KeyHit(KEY_F12)
		If KeyDown(KEY_RCONTROL)
			SaveSceenshot(Input("resolution multiplier:").ToInt())
		Else
			SaveSceenshot(6)
		End If
	End If
End Function

Function Render(x:Int = 0, y:Int = 0, s:Int = 1)
	glUseProgram(ProgramObj)

	glUniform3f(glGetUniformLocation(ProgramObj, "cpos"), camX, camY, camZ)
	glUniform2f(glGetUniformLocation(ProgramObj, "crot"), camP, camT)
	glUniform3f(glGetUniformLocation(ProgramObj, "light"), lightX, lightY, lightZ)
	glUniform1f(glGetUniformLocation(ProgramObj, "eps"), eps)

	glUniform1i(glGetUniformLocation(ProgramObj, "itr"), itr)
	glUniform1f(glGetUniformLocation(ProgramObj, "scale"), scale)
	glUniform3f(glGetUniformLocation(ProgramObj, "offset"), offsetX, offsetY, offsetZ)
	glUniform3f(glGetUniformLocation(ProgramObj, "rotvec"), rotvecX, rotvecY, rotvecZ)
	glUniform1f(glGetUniformLocation(ProgramObj, "rotangel"), rotangel)

	Local w:Float = 2.0 * camZoom / Float(s), h:Float = GH / Float(GW)
	Local vx:Float = x * w - camZoom, vy:Float = -camZoom * h
	h = w * h
	vy = vy + y * h

	glBegin(GL_QUADS)
		glTexCoord2f(vx, vy) ;glVertex2i(0, 0)
		glTexCoord2f(vx + w, vy) ;glVertex2i(GW, 0)
		glTexCoord2f(vx + w, vy + h) ;glVertex2i(GW, GH)
		glTexCoord2f(vx, vy + h) ;glVertex2i(0, GH)
	glEnd

	glUseProgram(0)
End Function

Function InitGL()
	GLGraphics GW, GH', 32, 60, 0
	SetGraphicsDriver(GLGraphicsDriver())
	glewInit()

	glMatrixMode(GL_PROJECTION)
	glLoadIdentity()

	glOrtho(0, GW, GH, 0, -1, 1)

	glMatrixMode(GL_MODELVIEW)
	glLoadIdentity()
End Function

Function glCls()
	glClear GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT
End Function

Function InitShaders()
	ProgramObj = glCreateProgram()
	Local VertexShdr:Int = glCreateShader(GL_VERTEX_SHADER_ARB)
	Local FragmentShdr:Int = glCreateShader(GL_FRAGMENT_SHADER_ARB)

	Local vsc:Byte Ptr = VERTEX_SHADER_CODE.ToCString()
	Local vsl:Int = VERTEX_SHADER_CODE.Length
	Local fsc:Byte Ptr = FRAGMENT_SHADER_CODE.ToCString()
	Local fsl:Int = FRAGMENT_SHADER_CODE.Length

	glShaderSource(VertexShdr, 1, Varptr vsc, Varptr vsl)
		glShaderSource(FragmentShdr, 1, Varptr fsc, Varptr fsl)

		MemFree(vsc)
	MemFree(fsc)

	glCompileShader(VertexShdr) ;CheckForErrors(VertexShdr)
	glCompileShader(FragmentShdr) ;CheckForErrors(FragmentShdr)

	glAttachShader(ProgramObj, VertexShdr)
	glAttachShader(ProgramObj, FragmentShdr)

	glDeleteShader(VertexShdr)
	glDeleteShader(FragmentShdr)

	glLinkProgram(ProgramObj) ;CheckForErrors(ProgramObj)
End Function

Function CheckForErrors(ShaderObject:Int)
	Local ErrorLength:Int

	glGetShaderiv(ShaderObject, GL_OBJECT_INFO_LOG_LENGTH_ARB, Varptr ErrorLength)

	If ErrorLength
		Local Message:Byte[ErrorLength], Dummy:Int

		glGetShaderInfoLog(ShaderObject, ErrorLength, Varptr Dummy, Varptr Message[0])
		'SaveText("Shader object '" + ShaderObject + "':~n" + Trim(StringFromCharArray(Message)), "err.txt")
		WriteStdout("Shader object '" + ShaderObject + "':~n" + Trim(StringFromCharArray(Message)))
	EndIf
End Function

Function StringFromCharArray:String(Array:Byte[])
	Local Output:String
	For Local I:Int = 0 To Array.Length - 1
		Output:+Chr(Array[I])
	Next

	Return Output
End Function

Function SaveSceenshot(s:Int = 3, fn:String = "", compression:Int = 5, infosdtout:Int = 1)
	Local cnt:Int
	Local pm:TPixmap = CreatePixmap(GW * s, GH * s, PF_BGRA8888)
	Local c:Byte Ptr = MemAlloc(3 * (GW + GW Mod 4) * (GH + GH Mod 4))

	For Local x1:Int = 0 Until s
		If infosdtout WriteStdout (x1 + 1) + " of " + s + "~n"
		For Local y1:Int = 0 Until s
			Render(x1, y1, s)
			glReadPixels(0, 0, (GW + GW Mod 4), (GH + GH Mod 4), GL_RGB, GL_UNSIGNED_BYTE, c)
			cnt = 0
			For Local y:Int = GH - 1 To 0 Step - 1
				For Local x:Int = 0 Until GW
					WritePixel(pm, x1 * GW + x, y1 * GH + y, $ff000000 + $10000 * c[cnt] + $100 * c[cnt + 1] + c[cnt + 2])
					cnt:+3
				Next
				cnt:+3 * (GW Mod 4)
			Next
		Next
	Next

	If infosdtout WriteStdout "Saving..."
	If fn = "" Then fn = (MilliSecs()) + ".png"
	SavePixmapPNG(pm, fn, compression)
	If infosdtout WriteStdout "Done.~n~n"
End Function

Function DrawHelp()
	GLDrawText "cam   =" + camX + ", " + camY + ", " + camZ, 0, 0
	GLDrawText "offset=" + offsetX + ", " + offsetY + ", " + offsetZ, 0, 16
	GLDrawText "rotvec=" + rotvecX + ", " + rotvecY + ", " + rotvecZ, 0, 32
	GLDrawText "rotang=" + rotangel, 0, 48
	GLDrawText "scale =" + scale, 0, 64
	GLDrawText "itr   =" + itr, 0, 80
	GLDrawText "eps   =" + eps, 0, 96
End Function

Function Catmul:Float(v0:Float, v1:Float, v2:Float, v3:Float, x:Float)
	Local a0:Float, a1:Float, a2:Float, a3:Float, x2:Float

	x2 = x * x
'	a0 = -0.5 * v0 + 1.5 * v1 - 1.5 * v2 + 0.5 * v3
'	a1 = v0 - 2.5 * v1 + 2 * v2 - 0.5 * v3
'	a2 = -0.5 * v0 + 0.5 * v2
'	a3 = v1
	a0 = v3 - v2 - v0 + v1
	a1 = v0 - v1 - a0
	a2 = v2 - v0
	a3 = v1

	Return a0 * x * x2 + a1 * x2 + a2 * x + a3
End Function

Function Clip:Float(v1:Float, v2:Float, x:Float)
	Return x * v2 + v1 * (1.0 - x)
End Function

Type TAnimFrame
	Global list:TList = CreateList()

	Field varlist:TList

	Method New()
		varlist = CreateList()
	End Method

	Method Del()
		list.Remove(Self)
	End Method

	Function AddFrame:TAnimFrame(link:TLink = Null, modify:Int = 0)
		Local t:TAnimFrame
		If modify
			If link = Null
				t = New TAnimFrame
				t.list.AddLast(t)
			Else
				t = TAnimFrame(link.Value())
			End If
		Else
			t = New TAnimFrame
			If link = Null
				t.list.AddLast(t)
			Else
				t.list.InsertAfterLink(t, link)
			End If
		End If

		Local timevar:Object = t.getVar("time")
		If timevar = Null
			t.setVar("time", TFloat.N(1.0))
		Else
			t.setVar("time", TFloat(timevar))
		End If

		t.setVar("camX", TFloat.N(camX))
		t.setVar("camY", TFloat.N(camY))
		t.setVar("camZ", TFloat.N(camZ))
		t.setVar("camP", TFloat.N(camP))
		t.setVar("camT", TFloat.N(camT))

		t.setVar("camZoom", TFloat.N(camZoom))

		t.setVar("lightX", TFloat.N(lightX))
		t.setVar("lightY", TFloat.N(lightY))
		t.setVar("lightZ", TFloat.N(lightZ))

		t.setVar("eps", TFloat.N(eps))

		t.setVar("itr", TInt.N(itr))

		t.setVar("offsetX", TFloat.N(offsetX))
		t.setVar("offsetY", TFloat.N(offsetY))
		t.setVar("offsetZ", TFloat.N(offsetZ))
		t.setVar("scale", TFloat.N(scale))
		t.setVar("rotvecX", TFloat.N(rotvecX))
		t.setVar("rotvecY", TFloat.N(rotvecY))
		t.setVar("rotvecZ", TFloat.N(rotvecZ))
		t.setVar("rotangel", TFloat.N(rotangel))

		Return t
	End Function

	Method getVar:Object(name:String)
		For Local t:TAnimFrameVar = EachIn varlist
			If t.name = name
				Return t.v
			End If
		Next
		Return Null
	End Method

	Method setVar(name:String, v:Object)
		For Local t:TAnimFrameVar = EachIn varlist
			If t.name = name
				t.v = v
				Return
			End If
		Next
		Local t:TAnimFrameVar = New TAnimFrameVar
		t.name = name
		t.v = v
		varlist.AddLast(t)
		Return
	End Method

	Function PlayAnim(speed:Float)
		Local f1:TAnimFrame, f1link:TLink
		Local f2:TAnimFrame, f2link:TLink
		Local time:Float
		Local x:Float = 0

		f1 = TAnimFrame(f1.list.First())
		f1link = f1.list.FirstLink()
		If f1link = Null Then Return
		f2link = f1link.NextLink()
		If f2link = Null Then Return
		f2 = TAnimFrame(f2link.Value())

		While Not KeyHit(KEY_ESCAPE)

			setGlobals(f1, f1link, f2, f2link, x)

			Render()

			If disphelp DrawHelp()

			time = Clip(TFloat(f1.getVar("time")).v,  ..
			TFloat(f2.getVar("time")).v, x)

			x:+speed / time
			If x >= 1
				f1link = f2link
				f1 = f2
				f2link = f1link.NextLink()
				If f2link = Null Return
				f2 = TAnimFrame(f2link.Value())
				x = x - 1.0
			End If

			Flip 0
			glCls
			WaitTimer TIMER
		Wend
	End Function

	Function SaveAnim(speed:Float, folder:String, skip:Int = 0)
		Local framenr:Int = 0

		CreateDir(folder)

		Local f1:TAnimFrame, f1link:TLink
		Local f2:TAnimFrame, f2link:TLink
		Local time:Float
		Local x:Float = 0

		f1 = TAnimFrame(f1.list.First())
		f1link = f1.list.FirstLink()
		If f1link = Null Then Return
		f2link = f1link.NextLink()
		If f2link = Null Then Return
		f2 = TAnimFrame(f2link.Value())

		While Not KeyHit(KEY_ESCAPE)
			setGlobals(f1, f1link, f2, f2link, x)

			If framenr >= skip
				SaveSceenshot(3, folder + "/" + framenr + ".png", 1, 0)
				Print "Frame Nr. " + framenr
			End If

			time = Clip(TFloat(f1.getVar("time")).v,  ..
			TFloat(f2.getVar("time")).v, x)

			x:+speed / time
			If x >= 1
				f1link = f2link
				f1 = f2
				f2link = f1link.NextLink()
				If f2link = Null Then End
				f2 = TAnimFrame(f2link.Value())
				x = x - 1.0
			End If

			framenr:+1
			'Flip 0
			'glCls
			'WaitTimer TIMER
		Wend
	End Function

	Function setGlobals(f1:TAnimFrame, f1link:TLink, f2:TAnimFrame, f2link:TLink, x:Float)
		Local f0:TAnimFrame, f3:TAnimFrame
		Local f0link:TLink, f3link:TLink

		f0link = f1link.PrevLink()
		f3link = f2link.NextLink()

		If f0link = Null Then f0link = f1link
		If f3link = Null Then f3link = f2link

		f0 = TAnimFrame(f0link.Value())
		f3 = TAnimFrame(f3link.Value())

		camX = Catmul(TFloat(f0.getVar("camX")).v,  ..
		TFloat(f1.getVar("camX")).v,  ..
		TFloat(f2.getVar("camX")).v,  ..
		TFloat(f3.getVar("camX")).v, x)

		camY = Catmul(TFloat(f0.getVar("camY")).v,  ..
		TFloat(f1.getVar("camY")).v,  ..
		TFloat(f2.getVar("camY")).v,  ..
		TFloat(f3.getVar("camY")).v, x)

		camZ = Catmul(TFloat(f0.getVar("camZ")).v,  ..
		TFloat(f1.getVar("camZ")).v,  ..
		TFloat(f2.getVar("camZ")).v,  ..
		TFloat(f3.getVar("camZ")).v, x)

		camP = Catmul(TFloat(f0.getVar("camP")).v,  ..
		TFloat(f1.getVar("camP")).v,  ..
		TFloat(f2.getVar("camP")).v,  ..
		TFloat(f3.getVar("camP")).v, x)

		camT = Catmul(TFloat(f0.getVar("camT")).v,  ..
		TFloat(f1.getVar("camT")).v,  ..
		TFloat(f2.getVar("camT")).v,  ..
		TFloat(f3.getVar("camT")).v, x)

		camZoom = Catmul(TFloat(f0.getVar("camZoom")).v,  ..
		TFloat(f1.getVar("camZoom")).v,  ..
		TFloat(f2.getVar("camZoom")).v,  ..
		TFloat(f3.getVar("camZoom")).v, x)

		lightX = Catmul(TFloat(f0.getVar("lightX")).v,  ..
		TFloat(f1.getVar("lightX")).v,  ..
		TFloat(f2.getVar("lightX")).v,  ..
		TFloat(f3.getVar("lightX")).v, x)

		lightY = Catmul(TFloat(f0.getVar("lightY")).v,  ..
		TFloat(f1.getVar("lightY")).v,  ..
		TFloat(f2.getVar("lightY")).v,  ..
		TFloat(f3.getVar("lightY")).v, x)

		lightZ = Catmul(TFloat(f0.getVar("lightZ")).v,  ..
		TFloat(f1.getVar("lightZ")).v,  ..
		TFloat(f2.getVar("lightZ")).v,  ..
		TFloat(f3.getVar("lightZ")).v, x)

		eps = Clip(TFloat(f1.getVar("eps")).v,  ..
		TFloat(f2.getVar("eps")).v, x)

		itr = Clip(TInt(f1.getVar("itr")).v,  ..
		TInt(f2.getVar("itr")).v, x)

		offsetX = Clip(TFloat(f1.getVar("offsetX")).v,  ..
		TFloat(f2.getVar("offsetX")).v, x)

		offsetY = Clip(TFloat(f1.getVar("offsetY")).v,  ..
		TFloat(f2.getVar("offsetY")).v, x)

		offsetZ = Clip(TFloat(f1.getVar("offsetZ")).v,  ..
		TFloat(f2.getVar("offsetZ")).v, x)

		scale = Catmul(TFloat(f0.getVar("scale")).v,  ..
		TFloat(f1.getVar("scale")).v,  ..
		TFloat(f2.getVar("scale")).v,  ..
		TFloat(f3.getVar("scale")).v, x)

		rotvecX = Clip(TFloat(f1.getVar("rotvecX")).v,  ..
		TFloat(f2.getVar("rotvecX")).v, x)

		rotvecY = Clip(TFloat(f1.getVar("rotvecY")).v,  ..
		TFloat(f2.getVar("rotvecY")).v, x)

		rotvecZ = Clip(TFloat(f1.getVar("rotvecZ")).v,  ..
		TFloat(f2.getVar("rotvecZ")).v, x)

		rotangel = Catmul(TFloat(f0.getVar("rotangel")).v,  ..
		TFloat(f1.getVar("rotangel")).v,  ..
		TFloat(f2.getVar("rotangel")).v,  ..
		TFloat(f3.getVar("rotangel")).v, x)

	End Function

	Method setGlobalsToFrame()
		camX = TFloat(getVar("camX")).v
		camY = TFloat(getVar("camY")).v
		camZ = TFloat(getVar("camZ")).v
		camP = TFloat(getVar("camP")).v
		camT = TFloat(getVar("camT")).v
		camZoom = TFloat(getVar("camZoom")).v

		lightX = TFloat(getVar("lightX")).v
		lightY = TFloat(getVar("lightY")).v
		lightZ = TFloat(getVar("lightZ")).v

		eps = TFloat(getVar("eps")).v
		itr = TInt(getVar("itr")).v

		offsetX = TFloat(getVar("offsetX")).v
		offsetY = TFloat(getVar("offsetY")).v
		offsetZ = TFloat(getVar("offsetZ")).v
		scale = TFloat(getVar("scale")).v
		rotvecX = TFloat(getVar("rotvecX")).v
		rotvecY = TFloat(getVar("rotvecY")).v
		rotvecZ = TFloat(getVar("rotvecZ")).v
		rotangel = TFloat(getVar("rotangel")).v
	End Method

	Function SaveToFile(filename:String)
		Local f:TStream = WriteFile(filename)
		For Local t:TAnimFrame = EachIn TAnimFrame.list
			f.WriteLine "{"
			For Local v:TAnimFrameVar = EachIn t.varlist
				If TFloat(v.v) <> Null
					f.WriteLine "~t" + v.name + " = " + TFloat(v.v).v + "f;"
				Else If TInt(v.v) <> Null
					f.WriteLine "~t" + v.name + " = " + TInt(v.v).v + "i;"
				Else If TDouble(v.v) <> Null
					f.WriteLine "~t" + v.name + " = " + TDouble(v.v).v + "d;"
				End If
			Next
			f.WriteLine "}"
		Next
		f.Close
	End Function

	Function LoadFromFile(file:String)
		If FileType(file) = 1
			file = LoadText(file)
			file = Replace(file, " ", "")
			file = Replace(file, Chr(9), "")
			file = Replace(file, Chr(10), "")
			file = Replace(file, Chr(13), "")

			Local gs:Int = 1, ge:Int = 0, content:String

			While ge < Len(file)
				gs = Instr(file, "{", ge)
				ge = Instr(file, "}", gs + 1)
				content = Mid(file, gs + 1, ge - gs - 1)

				Local cs:Int = 1, ce:Int = 0, eq:Int
				Local name:String, value:String, dt:String

				Local t:TAnimFrame = New TAnimFrame
				t.list.AddLast(t)

				While ce < Len(content)
					ce = Instr(content, ";", cs)
					value = Mid(content, cs, ce - cs)
					eq = Instr(value, "=")

					name = Left(value, eq - 1)
					dt = Right(value, 1)
					value = Mid(Left(value, value.Length - 1), eq + 1)

					Select dt
						Case "f"
							t.setVar(name, TFloat.N(value.ToFloat()))
						Case "i"
							t.setVar(name, TInt.N(value.ToInt()))
						Case "d"
							t.setVar(name, TDouble.N(value.ToDouble()))
					End Select

					cs = ce + 1
				Wend

			Wend
		Else
			RuntimeError("File does not exist!")
		End If
	End Function

End Type

Type TAnimFrameVar
	Field name:String
	Field v:Object
End Type

Type TInt
	Field v:Int
	Function N:TInt(v:Int)
		Local t:TInt = New TInt
		t.v = v
		Return t
	End Function
End Type

Type TFloat
	Field v:Float
	Function N:TFloat(v:Float)
		Local t:TFloat = New TFloat
		t.v = v
		Return t
	End Function
End Type

Type TDouble
	Field v:Double
	Function N:TDouble(v:Double)
		Local t:TDouble = New TDouble
		t.v = v
		Return t
	End Function
End Type

error: pathspec 'KIFS/KIFS.bmx' did not match any file(s) known to git


Added start of gile[s] loader.

Added start of gile[s] loader.

Strict

Rem
	bbdoc: Gile[s] mesh loader
End Rem
Module MaxB3D.GLSLoader
ModuleInfo "Author: Kevin Primm"
ModuleInfo "License: MIT"

Import MaxB3D.Core
Import Prime.LibGLS

error: pathspec 'glsloader.mod/glsloader.bmx' did not match any file(s) known to git