/* 
 * This file is automaticaly generated, Please dont edit this file! 
 */
#include <engine/block.h> 







































void block_add( block * this, struct member * memberInstance ) {

		array_add( this->members,  memberInstance );

	}

void block_enableAutoUpload( block * this ) {

		this->autoUpload	= 1;

	}


char * block_getBufferTypeText( block * this ) {

		switch( this->bufferType ) {

			case GL_SHADER_STORAGE_BUFFER:

				return "GL_SHADER_STORAGE_BUFFER";

			break;

			case GL_UNIFORM_BUFFER:

				return "GL_UNIFORM_BUFFER";

			break;
		}

		return "buffer message not found";

	}

void block_createBuffer( block * this ) {

		unsigned int blockBufferSize	= this->bufferSize; 

		

		this->data	= ( float * ) malloc( blockBufferSize );

		glGenBuffers( 1, &this->buffer );

		glBindBuffer( this->bufferType, this->buffer );

		glBindBufferBase( this->bufferType, this->index, this->buffer );

		glBufferData( this->bufferType, blockBufferSize, 0, GL_DYNAMIC_DRAW );

	}

void block_upload( block * this ) {

		

		

		

		

		


		glBindBuffer( this->bufferType, this->buffer );

		glBindBufferBase( this->bufferType,  this->bindingPoint, this->buffer );

		glBufferSubData( this->bufferType, 0, this->bufferSize, this->data );

	}

void block_mapBufferError( block * this, void * pointer ) {

		if ( pointer == NULL ){

			GLenum errorCode = glGetError();

			switch( errorCode ) {

				case GL_INVALID_ENUM:

					printf("GL_INVALID_ENUM\n");

				break;

				case GL_INVALID_OPERATION:

					printf("GL_INVALID_OPERATION\n");

				break;

				case GL_INVALID_VALUE:

					printf("GL_INVALID_VALUE\n");

				break;

			}


			printf("null pointer on buffer:		%i\n", errorCode);

			return;

		}

	}

void * block_getMemberArray( block * this, char * name ) {

		glMemoryBarrier( GL_SHADER_STORAGE_BARRIER_BIT );

		vector_vector2 * output	= vector_vector2_newPointer();


		int uniformCount 	= array_length( this->members );

		for (int i = 0; i < uniformCount; ++i)
		{
			member * currentMember = array_get( this->members,  i );

			char * memberName	= ( char * ) currentMember->name;

			if( char_operator_compare( memberName ,  name) ) {

				int size	= currentMember->size * 8;

				int offset	= currentMember->offset / 4;

				output->items 	= glMapBufferRange( GL_SHADER_STORAGE_BUFFER, 0, size, GL_MAP_WRITE_BIT ); 

				output->total	= currentMember->size;
				
				block_mapBufferError( this,  output->items );


			}

		}

		glUnmapBuffer( GL_SHADER_STORAGE_BUFFER );


		return output;

	}

void block_setMemberArrayRow( block * this, char * name,  int arrayIndex,  float * data ) {

		int memberCount 	= array_length( this->members );

		for (int i = 0; i < memberCount; ++i)
		{
			member * currentMember = array_get( this->members,  i );

			char * memberName	= ( char * ) currentMember->name;

			if( char_operator_compare( memberName ,  name) ) {

				int size		= currentMember->size * 8;

				int arrayStride = currentMember->arrayStride;

				int offset		= arrayStride * arrayIndex;

				

				


				if( this->autoUpload ) {



					glBindBuffer( this->bufferType, this->buffer );

					glBindBufferBase( this->bufferType, this->bindingPoint, this->buffer );

					glBufferSubData( this->bufferType, offset, arrayStride, data );

				}


				memcpy( this->data + offset, data, arrayStride );

				

			}

		}

	}

void block_setMemberArray( block * this, char * name,  float * data ) {

		int memberCount 	= array_length( this->members );

		for (int i = 0; i < memberCount; ++i)
		{
			member * currentMember = array_get( this->members,  i );

			char * memberName	= ( char * ) currentMember->name;

			if( char_operator_compare( memberName ,  name) ) {

				int size	= currentMember->size * 8;

				int offset	= currentMember->offset / 4;

				memcpy( this->data + offset, data, size );

			}

		}

	}

void block_setMemberItem( block * this, char * name,  int index,  void * value ) {


		int uniformCount 	= array_length( this->members );

		

		for (int i = 0; i < uniformCount; ++i)
		{
			member * currentMember = array_get( this->members,  i );

			char * memberName	= ( char * ) currentMember->name;

			if( char_operator_compare( memberName ,  name) ) {

			
						int stride;	

						int strideNormalized;

						int size;

						int offset;


				switch( currentMember->type ) {

					case GL_FLOAT_VEC2:

						stride 				= currentMember->arrayStride;

						strideNormalized	=  stride  / sizeof( float ) ;

						

					

						vector2 * vector2Value	= ( vector2 * ) value;

						size				= 8;

						offset				= currentMember->offset;



						if( this->autoUpload ) {

							GLint arrayIndex				= ( strideNormalized * index * 2 * 8 );

							float data[2]					= { vector2Value->x, vector2Value->y };

							printf("%i:	(size:%i)	%f %f\n", arrayIndex, data[0], data[1]);


							glBindBuffer( this->bufferType, this->buffer );

							glBindBufferBase( this->bufferType, this->bindingPoint, this->buffer );

							glBufferSubData( this->bufferType, arrayIndex, size, data );



						} else {

							GLint dataOffset				= offset / sizeof( float );

							GLint arrayIndex				= ( strideNormalized * index );

							
							if( currentMember->topLevelSize == 1 ) {

								

							}


							

							this->data[ dataOffset + arrayIndex ] 		= vector2Value->x;

							this->data[ dataOffset + 1 + arrayIndex ] 	= vector2Value->y;

						}

						

					break;

					case GL_FLOAT_VEC3:
		
						stride 				= currentMember->arrayStride;

						strideNormalized	= stride  / sizeof( float ) ;


						vector3 * vector3Value	= ( vector3 * ) value;

						size				= 12;

						offset			= currentMember->offset;



						if( this->autoUpload ) {

							float data[3]	= { vector3Value->x, vector3Value->y, vector3Value->z };

						


							glBindBuffer( this->bufferType, this->buffer );

							glBindBufferBase( this->bufferType, this->bindingPoint, this->buffer );

							glBufferSubData( this->bufferType, offset, size, data );



						} else {

							GLint dataOffset				= offset / sizeof( float );

							GLint arrayIndex				= ( strideNormalized * index );

							this->data[ dataOffset + arrayIndex ] 		= vector3Value->x;

							this->data[ dataOffset + 1 + arrayIndex ] 	= vector3Value->y;

							this->data[ dataOffset + 2 + arrayIndex ] 	= vector3Value->z;

						}

					break;

					case GL_SAMPLER_2D:

	
					break;

				}

			}

		}

	}

void block_setData( block * this, float * data ) {

		this->data = data;

	}

void block_setMember( block * this, char * name,  void * value ) {

		int uniformCount 	= array_length( this->members );

		

		for (int i = 0; i < uniformCount; ++i)
		{
			member * currentMember = array_get( this->members,  i );

			char * memberName	= ( char * ) currentMember->name;

			if( char_operator_compare( memberName ,  name) ) {

			

				GLuint size = 8;

				GLint offset		= currentMember->offset;

				switch( currentMember->type ) {

					case GL_INT:

						int intValue	= *( int * ) value;

						printf("set int value:	%i offset:	%i\n", intValue, offset);

						

						if( this->autoUpload ) {

							float data[1]	= { value };

						


							glBindBuffer( this->bufferType, this->buffer );

							glBindBufferBase( this->bufferType, this->bindingPoint, this->buffer );

							glBufferSubData( this->bufferType, offset, size, data );



						} else {

							GLint dataOffset				= offset / sizeof( float );

							this->data[ dataOffset ] 		= intValue;

							

						}

					break;

					case GL_FLOAT:

						float floatValue	= *( float * ) value;

						printf("set int value:	%f offset:	%i\n", floatValue, offset);

						

						if( this->autoUpload ) {

							float data[1]	= { value };

						


							glBindBuffer( this->bufferType, this->buffer );

							glBindBufferBase( this->bufferType, this->bindingPoint, this->buffer );

							glBufferSubData( this->bufferType, offset, size, data );



						} else {

							GLint dataOffset				= offset / sizeof( float );

							this->data[ dataOffset ] 		= floatValue;

							

						}

					break;

					case GL_FLOAT_VEC2:

						vector2 * vector2Value	= ( vector2 * ) value;

						if( this->autoUpload ) {

							float data[2]	= { vector2Value->x, vector2Value->y };


							glBindBuffer( this->bufferType, this->buffer );

							glBindBufferBase( this->bufferType, this->bindingPoint, this->buffer );

							glBufferSubData( this->bufferType, offset, size, data );



						} else {

							GLint dataOffset				= offset / sizeof( float );

							this->data[ dataOffset ] 		= vector2Value->x;

							this->data[ dataOffset + 1 ] 	= vector2Value->y;

						}

					break;

					case GL_FLOAT_VEC3:

						vector3 * vector3Value	= ( vector3 * ) value;

						

					break;

					case GL_SAMPLER_2D:

	
					break;

				}

			}


		}


	}

block block_new() {

	block instance;

	instance.members = array_newPointer();

	instance.autoUpload =  0;

	return instance;

}

block * block_newPointer() {

	struct block * pointer = malloc( sizeof ( struct block ) );

	pointer->members = array_newPointer();

	pointer->autoUpload =  0;

	return pointer;

}

