
*** boxEngine Documentation v102
*** Michael Figarelli
*** fig.mikes@gmail.com

*** unofficial website: reddit.com/r/boxengine
*** videos/tutorials: youtube.com/user/m2ccc/videos


boxEngine is a simple openGL graphics engine (built on SFML) exposed to Lua (and MoonScript).  
This doc serves as a 'quickstart' for anyone interested in scriping their own boxEngine code.
boxEngine is setup to allow rapid development of games or other visual/audio applications.


====== Running Scripts

it is recommended you start the Command Prompt shortcut provided, and manually run 
boxEngine.exe.  Providing no arguments will run the script 'default.moon', located in 
'\scripts\' .  To run another script, add the parameters '-s scriptfile.moon'.  'Shortcuts' 
to running these are provided with the s_ bat files included.


Other parameters available are '-r screenwidth screenheight' to set the resolution and '-f' 
to set fullscreen.  Note you can use -r max to automatically use the maximum resolution.  
Try 'boxengine.exe -r max -f'.

====== MoonScript

boxEngine supports MoonScript, a language that compiles into Lua.  It is wonderful, and I 
much prefer it to Lua.  See http://moonscript.org/reference/

====== Script Functions

Within each lua script ran through boxEngine, the following functions should be defined in lua:

function Init( )
* called once when the engine is initialized.

function KeyHappen( inVal, inDown, inT )
* called whenever a key is pressed or depressed :( - also called on mouseclicks / mousescrolls.  
Note that mouse scrolling sends only a 'keydown'.
inDown will be one of the following: 1 for 'keydown', 0 for 'keyup', 2 for 'keyrepeat'.

function Draw( t, dt )
* called every frame - this is where all your drawing should take place.  t is the value of 
the current time in seconds, and dt is the delta time - the time in seconds since the previous 
frame.

Note: is is recommended to use the 'drawing class' structure found in template.moon.  A later 
version of boxEngine might just directly call the drawing class's functions.


====== Engine Functions

The following functions are exposed to Lua:

Push()
* pushes the current scene matrix.

Pop()
* pops the current scene matrix.

Move( x )
Move( x, y )
Move( x, y, z )
* moves / translates the current scene matrix.  With a 2d camera, positive y moves up on the screen.

Scale( v )
* scales the current x, y, and z matrix vals by v.

Scale( x, y, z )
* scales the current scene matrix.

Rotate( x, y, z, angle )
Rotate( angle )
* rotates the current scene matrix (angle) amount around the normal defined by x, y, z.
* if using a single argument, the vector (0, 0, 1) will be used.

LookAt( camX, camY, camZ, targetX, targetY, targetZ )
* sets the 3d camera looking at the target

SetCam( dimension [, mode ] )
* dimension must be 2 or 3 - a value of 2 will set the window to 2d mode, 3 will set to 3d mode.
* if dimension = 3, mode [ optionally ] sets the field of view angle.
* if dimension = 2, mode defaults to 0 if not specified, can be 0, 1, or 2.
* mode = 0 will stretch 2d cords from -1 -> 1 on both axis
* mode = 1 will stretch 2d cords from -1 -> 1 on the largest axi [ the other will be cropped <= 1 ]
* mode = 2 will stretch 2d cords from -1 -> 1 on the y axi.

GetMouseScalar()
* returns mouseX, mouseY mouse values, with the origin corresponding to the center of the 
window - corresponds to current SetCam mode - useful for gui or 2d pointer games.  Will not 
run off edge of screen.
* values returned will scale properly with current camera mode, so you should call this after SetCam().

GetMouseTotal()
* returns totalX, totalY mouse values - these are useful for calculating view angle in 3d mode.

===== VISUAL MEDIA ( textures, shaders, geometry )

AddGeom( file [, group ] )
* adds geometry objects from file (type: obj) into specified group.  If no group is specified, 
goes into default group of "".

AddTex( file [, group ] )
* adds texture image from file (type: bmp, jpg, png) into specified group [ default group "" ].

AddShad( file [, group ] )
* adds shader [type: shad] into group...  .shad includes both vertex and fragment sections in 
one file.

All of the Add* functions return the global index

NOTE: calling specific instances of each type of media works the same, with the exception 
that calling tex(-1) and shad(-1) unbinds any bound texture or shader.
This explanation covers geometry, but note that Geom(...) can be substituted with Shad(...) or 
Tex(...) and behave similarly.

Drawing geometry:

Geom( name )  --prefered way to use media.
Geom( globalindex )
Geom( groupname, index )
Geom( groupname, name )
Not supported:  Geom( groupindex, ... )

Binding textures (stays bound until next Tex() call)

Tex( name )
Tex( ... ) --same options as Geom

Binding shaders (stays bound until next Shad() call)

Shad( name )
Shad( ... )

* Geometry is handled in a 'Geometry Manager'.  To use geometry, first call 'AddGeom(...)' to 
add geometry, possibly with a specified group.  Sometimes geometry files include multiple 
objects - all will be loaded into the specified group.

* The fastest way to reference geometry is by the globalindex (but don't rely on an object having 
the same index between runs of your app).  Internally, all media objects are stored in a global 
resizable array, and the groups reference indeces of this array.

* Note that calling Geom( name ) is equivalent to calling Geom( "", name ), so don't expect a 
specified group-loaded object to be globally referenced through Geom( name ).

* All of the above applies to Textures, Shaders and Audio (discussed below)

== Geom-specific functions

You can combine multiple objects into one object for faster drawing.  This is the 'basic' way to 
build a map in-game.  Note that when you combine objects into one, they will all share the bound 
tex/shad when drawn.

NewGeom( name )
NewGeom( group, name )
* creates empty geom obj, returns glob index:

4param:
Place( srcGroup, srcName/index, dstGroup, dstName/index )

3param:
Place( srcGroup, srcName/index, dstGlobIndex )

2param:
Place( srcName, dstName ) //operates in "" group
Place( srcGlobIndex, dstGlobIndex )

* Places one piece of geometry into another, with the current geometry matrix ( explained below ) 
and geom texture matrices applied.

== Geom-Matrices

GPush()
GPop()
GRotate( x,y,z,angle )
GScale( x,y,z )
GMove( x,y,z )
GReset()

== Shader Variables

To send data to a shader, after you add it, bind it and DeclareUniform().  When 
drawing, once it is bound, Uniform() to send value(s) to that shader.

DeclareUniform( uniformIndex, strVarName, numFloats )
* Declares a uniform for this shader. uniformIndex is unique per shader, so you'll start with 0 for each shader.  strVarName is the string variable name in the shader.  currently only supports sending 
1 float.

Uniform( uniformIndex, value )
* Sends value to the shader in the variable / index defined in DeclareUniform()

== Lighting

SetLighting( 0 or 1 )
* turns on or off lighting.  does not work when a shader is active, and setting lighting on will override the current Color() setting.

SetLight( index, x, y, z )
* sets index 0 or 1 light to position ( x, y, z ) - calling this will turn on lighting, and enable this specific light.  only 2 lights are currently available.

SetLightColor( lightNum, r, g, b )
* Sets a light's color. duh.

SetLightAtten( lightNum, constant, linear, exponential )
* Sets a light's atten values. duh.

SetAmbientColor( r, g, b )
* Sets the ambient color when lighting is enabled. duh.

Color( r, g, b, a )
* sets the current color state.  will have no effect on lighted geometry.

Color( lum )
* equivalent to Color( lum, lum, lum, 1 )

BackColor( r, g, b, a )
* sets color the screen is cleared with every frame

Cull( cullOnOff )
* turns on/off backface culling

Depth( depthRead, depthWrite )
* sets the state of the depth buffer.

Blend( mode )
mode:
-1 turns off openGL blending
0 sets standard alpha blending
1 sets additive alpha blending 
if you are using transparency or transparent textures, turn this on ( performance is better with it off ).  Has no effect when lighting is enabled.

Blend( src, dst )
src ranges from 0-8, and sets src blend operation:
GL_ZERO, GL_ONE, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA_SATURATE

dst ranges from 0-7 and sets dst blend operation:
GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA

Logic( val )
-1 disables logic ( default setting )
0-15 sets the current blend logic mode.  Note that setting this will override Blend() settings.
val sets logic op to:
GL_CLEAR, GL_SET, GL_COPY, GL_COPY_INVERTED, GL_NOOP, GL_INVERT, GL_AND, GL_NAND, GL_OR, GL_NOR, GL_XOR, GL_EQUIV, GL_AND_REVERSE, GL_AND_INVERTED, GL_OR_REVERSE, GL_OR_INVERTED


GetMouseScalar()
Returns the X and Y value of the mouse - corresponds to the Camera 2d mode ( for example, SetCam( 2, 0 ) will clamp x & y to -1, 1, SetCam( 2, 2 ) will clamp y to -1, 1, and x to the appropriate ratio ).

SetMouseVis( inOn )
shows or hides mouse - does not need to be called every frame (infact, it shouldn't).

SetMouseFree( inFree )
set free for 2d mode [ or menu selection ], do not set free if using as 3d pov!
	

--note that these are planned to be 'fixed' by next major version - not fully tested yet, probably work!
BeginRTTFull()
* call this before your scene (and call EndRTTFull() at the end) to use full-screen shaders. ( Note that this will likely have better performance later on )

EndRTTFull()
* bind a shader before calling this at the end of your scene, and it will apply to the rendered image.

== Audio/Music

Audio and Music are supported in boxEngine, each working a little differently.
Audio generally loads .wav files, and music .ogg.

Audio internally is managed like the other media types, with groups.

AddAudio( file, [ group ] )
* loads an audio file

Audio( name ), Audio( ...same as others... )...
* Plays audio, returns an index which can be referenced by audioprops - new index each play, can play more than one instance at a time.

AudioProps( index, volume, [ pitch, [ repeat, [ x, y, z ] ] ] )
* Sets audio properties for a currently playing sound.  volume: 0-1, pitch: 0-fast, repeat 0/1
	x, y, z defines the 3d location of a mono-channel sound, default 0, 0, 0 which is full volume.

StopAudio( index )
* Stops a currently playing sound, repeating or not.

Music is handled differently than other media.

AddMusic( index, file )
* loads an ogg music file into index, which is 0-7 (8 available slots to load music, can overwrite old slots).

Music( index )
* plays loaded music, does not return an index, as we manage the indices ourselves.

MusicProps( index, volume, [ pitch, [ repeat, [ x, y, z ] ] ] )
* same as audioProps

StopMusic( index )
* stops music

== Audio Generation/Editing

Yep, you can generate audio with code and edit existing audio - there's a lot of potential here if someone 
wanted to really work with it.  See audiogen.moon for an example.

GetNewAudio( name [, group ] )
* reserves an empty 'loaded audio', returns an index.

SetAudioData( index, array, numchannels, samplespersecond, resampleCoef )
* passes 'array', containing float values from -1.0 to 1.0.
	numChannels (2 for stereo), default 1
	samplespersecond, default 44100 for wav-file quality.
	resampleCoef - if 3, will average every three values into one. default 1.
* the duration is determined by array length / numchannels / samplespersecond / resampleCoef. easy!

GetAudioData( index )
* returns a lua table (array) that represents the audio of the item at index.  data ranges from -1.0 to 1.0

== Text

Ahh, ye old text drawing!  Text() simply draws geometry with the proper texture layout, at the moment it's
up to you to bind the texture (font.png).  Eventually there will be proper multi-font support.

Text( string, [ alignment, [ HorizDist, [ VertDist ] ] ] )
* Draws text of string.
	alignment can be 0, centered, 1, left-align, -1, right-align.  default is 1.
	Horiz and Vert dist are in units of leters, and offset the distances between letters.

Note that due to text changing often, Text() will internally reuse generated text-geometry that doesn't change text/props, and will discard text-geometry that hasn't been used for a duration.  No need to keep track of indexes, just bind the font texture and Text() away!  See text.moon for an example.


== 3d Noise:

Noise( x, y, z )
* returns a float value representing an interpolated point in a 3d noise grid.  The return value will generally range from -.4 to .4, often returning zero.
The noise is calulated as a 3d 'simplex noise'

SetNoiseSeed( inSeed )
* Sets the noise random seed.

== Misc Functions


DrawLine( x1, y1, z1, x2, y2, z2 )
* Draws a line. duh.

BindKey( gameKeyIndex, realKeyIndex [, isSecondary = 0 ] )
* binds keys - if secondary [by default it is not], will not overwrite same gamekey bindings (so more than 1 key can bind to one gameKey).

TypingMode( 1 or 0 )
* by default 0, sends keys as gamekey indices.  If set to 1, sends actual character keys.
Note that some char indices go above 255, so you can't just send new characters to a string.

SetScreenshotDir( dir )
* exactly.  doesn't end with a '\'

SetVSync( 1 or 0 )
* Sets vertical sync to prevent screen tearing, only applied when fullscreen...
With some scenes causes fps lag.




== Space Mappers (physics engines)

SetSpaceMapper( bx_SPACEMAPPER2D )
* Sets the current space mapper to be used (only 2d supported at the moment)

AddSpaceObject( objName, args... )
* Adds static spacemapper objects - only set these objects during init.  Examples as follows

AddSpaceObject( "line2d", v[ 1 ], v[ 2 ], v[ 3 ], v[ 4 ] )
* Adds a 2D line with arguments x1, y1, x2, y2.

MapPoint( inPos, inSpd, inRadius, outLastCollisionPt, outNewPoint, outNewSpd )
* Returns number of collisions.  Regardless of collisions, will set outNewPoint and outNewSpd appropriately - feel free to simply update base pos and spd with the values returned here.  Note that with inRadius == 0, the engine is able to faster map the new point (though obviously many cases require a radius).

MapLine( inStartPos, inEndPos, inRadius, outCollisionPt, outNewEndPoint )
* Returns 0 for no collision, 1 for collision.  if collides, outCollisionPt is the point where line meets wall, and outNewEndPoint is the reflected endpoint of the new line.  Note that you should usually MapLine() for the same line until it returns 0, as MapLine only checks for one ('the next') collision.  If no collision, outCollisionPt == outNewEndPoint and they equal inEndPos.




====== Adding Geometry / Texture / Shader Content:

For all content, if you wish to add to the standard content library, simply put an image, shader, or geometry file into the appropriate data directory.

Geometry: .obj files - when you export, export with normals and UVs, +Y is forward, +Z is up.  Do not export materials.  Groups or objects will work the same.  Make sure you name your geometry object as well as the file - name depends on object (though in the future might take on the filename if only 1 object).

Shaders: see current shaders for reference - a .shad file includes both the vertex and fragment sections.

Sidenote: 'p' takes a screenshot!

Have fun!  Please share any interesting scripts ( with screenshots ) on the boxengine subreddit!
